From 6cd327e86cd0d7e9447e5116f968a9982eb9223c Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Sat, 21 May 2011 18:17:37 +0000 Subject: [PATCH] Committing NowPlaying plugin. Because it requires VS2010 Pro to compile, it is not built by default. --- Plugins/PluginMediaKey/PluginMediaKey.cpp | 4 +- Plugins/PluginMediaKey/PluginMediaKey.rc | 2 +- Plugins/PluginNowPlaying/NowPlaying.cpp | 478 + Plugins/PluginNowPlaying/NowPlaying.h | 51 + Plugins/PluginNowPlaying/Player.cpp | 390 + Plugins/PluginNowPlaying/Player.h | 135 + Plugins/PluginNowPlaying/PlayerAIMP.cpp | 464 + Plugins/PluginNowPlaying/PlayerAIMP.h | 61 + Plugins/PluginNowPlaying/PlayerFoobar.cpp | 502 + Plugins/PluginNowPlaying/PlayerFoobar.h | 84 + Plugins/PluginNowPlaying/PlayerGeneric.cpp | 163 + Plugins/PluginNowPlaying/PlayerGeneric.h | 46 + Plugins/PluginNowPlaying/PlayerITunes.cpp | 587 + Plugins/PluginNowPlaying/PlayerITunes.h | 99 + Plugins/PluginNowPlaying/PlayerSpotify.cpp | 263 + Plugins/PluginNowPlaying/PlayerSpotify.h | 57 + Plugins/PluginNowPlaying/PlayerWMP.cpp | 723 + Plugins/PluginNowPlaying/PlayerWMP.h | 146 + Plugins/PluginNowPlaying/PlayerWinamp.cpp | 481 + Plugins/PluginNowPlaying/PlayerWinamp.h | 61 + Plugins/PluginNowPlaying/PluginNowPlaying.rc | 48 + .../PluginNowPlaying/PluginNowPlaying.vcxproj | 367 + .../PluginNowPlaying.vcxproj.filters | 313 + .../PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h | 726 + Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h | 97 + Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h | 353 + .../PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h | 39 + Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h | 1601 ++ .../SDKs/iTunes/iTunesCOMInterface.h | 14384 ++++++++++++++++ .../SDKs/iTunes/iTunesCOMInterface_i.c | 175 + Plugins/PluginNowPlaying/StdAfx.cpp | 19 + Plugins/PluginNowPlaying/StdAfx.h | 38 + Plugins/PluginNowPlaying/readme.txt | 7 + Plugins/PluginNowPlaying/sha2/hmac_sha2.c | 544 + Plugins/PluginNowPlaying/sha2/hmac_sha2.h | 140 + Plugins/PluginNowPlaying/sha2/sha2.c | 950 + Plugins/PluginNowPlaying/sha2/sha2.h | 108 + Plugins/PluginNowPlaying/taglib/COPYING.LGPL | 502 + Plugins/PluginNowPlaying/taglib/COPYING.MPL | 470 + .../taglib/ape/ape-tag-format.txt | 170 + .../PluginNowPlaying/taglib/ape/apefile.cpp | 270 + Plugins/PluginNowPlaying/taglib/ape/apefile.h | 171 + .../PluginNowPlaying/taglib/ape/apefooter.cpp | 236 + .../PluginNowPlaying/taglib/ape/apefooter.h | 173 + .../PluginNowPlaying/taglib/ape/apeitem.cpp | 230 + Plugins/PluginNowPlaying/taglib/ape/apeitem.h | 204 + .../taglib/ape/apeproperties.cpp | 224 + .../taglib/ape/apeproperties.h | 98 + .../PluginNowPlaying/taglib/ape/apetag.cpp | 271 + Plugins/PluginNowPlaying/taglib/ape/apetag.h | 170 + .../taglib/asf/asfattribute.cpp | 356 + .../taglib/asf/asfattribute.h | 203 + .../PluginNowPlaying/taglib/asf/asffile.cpp | 543 + Plugins/PluginNowPlaying/taglib/asf/asffile.h | 120 + .../taglib/asf/asfpicture.cpp | 185 + .../PluginNowPlaying/taglib/asf/asfpicture.h | 217 + .../taglib/asf/asfproperties.cpp | 107 + .../taglib/asf/asfproperties.h | 74 + .../PluginNowPlaying/taglib/asf/asftag.cpp | 201 + Plugins/PluginNowPlaying/taglib/asf/asftag.h | 186 + .../taglib/audioproperties.cpp | 51 + .../PluginNowPlaying/taglib/audioproperties.h | 110 + Plugins/PluginNowPlaying/taglib/config.h | 2 + Plugins/PluginNowPlaying/taglib/fileref.cpp | 266 + Plugins/PluginNowPlaying/taglib/fileref.h | 263 + .../PluginNowPlaying/taglib/flac/flacfile.cpp | 499 + .../PluginNowPlaying/taglib/flac/flacfile.h | 222 + .../taglib/flac/flacmetadatablock.cpp | 51 + .../taglib/flac/flacmetadatablock.h | 75 + .../taglib/flac/flacpicture.cpp | 221 + .../taglib/flac/flacpicture.h | 208 + .../taglib/flac/flacproperties.cpp | 158 + .../taglib/flac/flacproperties.h | 98 + .../taglib/flac/flacunknownmetadatablock.cpp | 83 + .../taglib/flac/flacunknownmetadatablock.h | 81 + .../PluginNowPlaying/taglib/mp4/mp4atom.cpp | 197 + Plugins/PluginNowPlaying/taglib/mp4/mp4atom.h | 77 + .../taglib/mp4/mp4coverart.cpp | 89 + .../PluginNowPlaying/taglib/mp4/mp4coverart.h | 71 + .../PluginNowPlaying/taglib/mp4/mp4file.cpp | 145 + Plugins/PluginNowPlaying/taglib/mp4/mp4file.h | 103 + .../PluginNowPlaying/taglib/mp4/mp4item.cpp | 149 + Plugins/PluginNowPlaying/taglib/mp4/mp4item.h | 72 + .../taglib/mp4/mp4properties.cpp | 169 + .../taglib/mp4/mp4properties.h | 61 + .../PluginNowPlaying/taglib/mp4/mp4tag.cpp | 636 + Plugins/PluginNowPlaying/taglib/mp4/mp4tag.h | 104 + .../PluginNowPlaying/taglib/mpc/mpcfile.cpp | 325 + Plugins/PluginNowPlaying/taglib/mpc/mpcfile.h | 175 + .../taglib/mpc/mpcproperties.cpp | 140 + .../taglib/mpc/mpcproperties.h | 85 + .../taglib/mpeg/id3v1/id3v1genres.cpp | 219 + .../taglib/mpeg/id3v1/id3v1genres.h | 66 + .../taglib/mpeg/id3v1/id3v1tag.cpp | 248 + .../taglib/mpeg/id3v1/id3v1tag.h | 181 + .../id3v2/frames/attachedpictureframe.cpp | 222 + .../mpeg/id3v2/frames/attachedpictureframe.h | 230 + .../mpeg/id3v2/frames/commentsframe.cpp | 178 + .../taglib/mpeg/id3v2/frames/commentsframe.h | 168 + .../frames/generalencapsulatedobjectframe.cpp | 176 + .../frames/generalencapsulatedobjectframe.h | 178 + .../mpeg/id3v2/frames/popularimeterframe.cpp | 137 + .../mpeg/id3v2/frames/popularimeterframe.h | 132 + .../taglib/mpeg/id3v2/frames/privateframe.cpp | 128 + .../taglib/mpeg/id3v2/frames/privateframe.h | 111 + .../mpeg/id3v2/frames/relativevolumeframe.cpp | 236 + .../mpeg/id3v2/frames/relativevolumeframe.h | 274 + .../id3v2/frames/textidentificationframe.cpp | 271 + .../id3v2/frames/textidentificationframe.h | 258 + .../frames/uniquefileidentifierframe.cpp | 118 + .../id3v2/frames/uniquefileidentifierframe.h | 113 + .../taglib/mpeg/id3v2/frames/unknownframe.cpp | 84 + .../taglib/mpeg/id3v2/frames/unknownframe.h | 79 + .../frames/unsynchronizedlyricsframe.cpp | 162 + .../id3v2/frames/unsynchronizedlyricsframe.h | 157 + .../taglib/mpeg/id3v2/frames/urllinkframe.cpp | 192 + .../taglib/mpeg/id3v2/frames/urllinkframe.h | 172 + .../taglib/mpeg/id3v2/id3v2.2.0.txt | 1660 ++ .../taglib/mpeg/id3v2/id3v2.3.0.txt | 2022 +++ .../taglib/mpeg/id3v2/id3v2.4.0-frames.txt | 1734 ++ .../taglib/mpeg/id3v2/id3v2.4.0-structure.txt | 733 + .../taglib/mpeg/id3v2/id3v2extendedheader.cpp | 71 + .../taglib/mpeg/id3v2/id3v2extendedheader.h | 93 + .../taglib/mpeg/id3v2/id3v2footer.cpp | 60 + .../taglib/mpeg/id3v2/id3v2footer.h | 82 + .../taglib/mpeg/id3v2/id3v2frame.cpp | 549 + .../taglib/mpeg/id3v2/id3v2frame.h | 414 + .../taglib/mpeg/id3v2/id3v2framefactory.cpp | 433 + .../taglib/mpeg/id3v2/id3v2framefactory.h | 167 + .../taglib/mpeg/id3v2/id3v2header.cpp | 243 + .../taglib/mpeg/id3v2/id3v2header.h | 175 + .../taglib/mpeg/id3v2/id3v2synchdata.cpp | 77 + .../taglib/mpeg/id3v2/id3v2synchdata.h | 70 + .../taglib/mpeg/id3v2/id3v2tag.cpp | 475 + .../taglib/mpeg/id3v2/id3v2tag.h | 300 + .../PluginNowPlaying/taglib/mpeg/mpegfile.cpp | 593 + .../PluginNowPlaying/taglib/mpeg/mpegfile.h | 277 + .../taglib/mpeg/mpegheader.cpp | 276 + .../PluginNowPlaying/taglib/mpeg/mpegheader.h | 166 + .../taglib/mpeg/mpegproperties.cpp | 254 + .../taglib/mpeg/mpegproperties.h | 118 + .../taglib/mpeg/xingheader.cpp | 115 + .../PluginNowPlaying/taglib/mpeg/xingheader.h | 100 + .../taglib/ogg/flac/oggflacfile.cpp | 269 + .../taglib/ogg/flac/oggflacfile.h | 118 + .../PluginNowPlaying/taglib/ogg/oggfile.cpp | 427 + Plugins/PluginNowPlaying/taglib/ogg/oggfile.h | 112 + .../PluginNowPlaying/taglib/ogg/oggpage.cpp | 340 + Plugins/PluginNowPlaying/taglib/ogg/oggpage.h | 211 + .../taglib/ogg/oggpageheader.cpp | 323 + .../taglib/ogg/oggpageheader.h | 232 + .../taglib/ogg/speex/speexfile.cpp | 112 + .../taglib/ogg/speex/speexfile.h | 99 + .../taglib/ogg/speex/speexproperties.cpp | 170 + .../taglib/ogg/speex/speexproperties.h | 89 + .../taglib/ogg/vorbis/vorbisfile.cpp | 117 + .../taglib/ogg/vorbis/vorbisfile.h | 118 + .../taglib/ogg/vorbis/vorbisproperties.cpp | 183 + .../taglib/ogg/vorbis/vorbisproperties.h | 125 + .../taglib/ogg/xiphcomment.cpp | 319 + .../PluginNowPlaying/taglib/ogg/xiphcomment.h | 202 + .../taglib/riff/aiff/aifffile.cpp | 112 + .../taglib/riff/aiff/aifffile.h | 102 + .../taglib/riff/aiff/aiffproperties.cpp | 153 + .../taglib/riff/aiff/aiffproperties.h | 82 + .../PluginNowPlaying/taglib/riff/rifffile.cpp | 254 + .../PluginNowPlaying/taglib/riff/rifffile.h | 121 + .../taglib/riff/wav/wavfile.cpp | 119 + .../taglib/riff/wav/wavfile.h | 102 + .../taglib/riff/wav/wavproperties.cpp | 120 + .../taglib/riff/wav/wavproperties.h | 91 + Plugins/PluginNowPlaying/taglib/tag.cpp | 83 + Plugins/PluginNowPlaying/taglib/tag.h | 173 + .../PluginNowPlaying/taglib/taglib_config.h | 2 + .../PluginNowPlaying/taglib/taglib_export.h | 46 + Plugins/PluginNowPlaying/taglib/tagunion.cpp | 185 + Plugins/PluginNowPlaying/taglib/tagunion.h | 95 + .../PluginNowPlaying/taglib/toolkit/taglib.h | 186 + .../taglib/toolkit/tbytevector.cpp | 698 + .../taglib/toolkit/tbytevector.h | 425 + .../taglib/toolkit/tbytevectorlist.cpp | 102 + .../taglib/toolkit/tbytevectorlist.h | 91 + .../taglib/toolkit/tdebug.cpp | 55 + .../PluginNowPlaying/taglib/toolkit/tdebug.h | 71 + .../PluginNowPlaying/taglib/toolkit/tfile.cpp | 564 + .../PluginNowPlaying/taglib/toolkit/tfile.h | 270 + .../PluginNowPlaying/taglib/toolkit/tlist.h | 252 + .../PluginNowPlaying/taglib/toolkit/tlist.tcc | 316 + .../PluginNowPlaying/taglib/toolkit/tmap.h | 200 + .../PluginNowPlaying/taglib/toolkit/tmap.tcc | 196 + .../taglib/toolkit/tstring.cpp | 811 + .../PluginNowPlaying/taglib/toolkit/tstring.h | 483 + .../taglib/toolkit/tstringlist.cpp | 123 + .../taglib/toolkit/tstringlist.h | 115 + .../taglib/toolkit/unicode.cpp | 303 + .../PluginNowPlaying/taglib/toolkit/unicode.h | 149 + .../taglib/trueaudio/trueaudiofile.cpp | 272 + .../taglib/trueaudio/trueaudiofile.h | 180 + .../taglib/trueaudio/trueaudioproperties.cpp | 136 + .../taglib/trueaudio/trueaudioproperties.h | 93 + .../taglib/wavpack/wavpackfile.cpp | 267 + .../taglib/wavpack/wavpackfile.h | 164 + .../taglib/wavpack/wavpackproperties.cpp | 194 + .../taglib/wavpack/wavpackproperties.h | 104 + Rainmeter.sln | 8 +- 205 files changed, 63050 insertions(+), 4 deletions(-) create mode 100644 Plugins/PluginNowPlaying/NowPlaying.cpp create mode 100644 Plugins/PluginNowPlaying/NowPlaying.h create mode 100644 Plugins/PluginNowPlaying/Player.cpp create mode 100644 Plugins/PluginNowPlaying/Player.h create mode 100644 Plugins/PluginNowPlaying/PlayerAIMP.cpp create mode 100644 Plugins/PluginNowPlaying/PlayerAIMP.h create mode 100644 Plugins/PluginNowPlaying/PlayerFoobar.cpp create mode 100644 Plugins/PluginNowPlaying/PlayerFoobar.h create mode 100644 Plugins/PluginNowPlaying/PlayerGeneric.cpp create mode 100644 Plugins/PluginNowPlaying/PlayerGeneric.h create mode 100644 Plugins/PluginNowPlaying/PlayerITunes.cpp create mode 100644 Plugins/PluginNowPlaying/PlayerITunes.h create mode 100644 Plugins/PluginNowPlaying/PlayerSpotify.cpp create mode 100644 Plugins/PluginNowPlaying/PlayerSpotify.h create mode 100644 Plugins/PluginNowPlaying/PlayerWMP.cpp create mode 100644 Plugins/PluginNowPlaying/PlayerWMP.h create mode 100644 Plugins/PluginNowPlaying/PlayerWinamp.cpp create mode 100644 Plugins/PluginNowPlaying/PlayerWinamp.h create mode 100644 Plugins/PluginNowPlaying/PluginNowPlaying.rc create mode 100644 Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj create mode 100644 Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters create mode 100644 Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h create mode 100644 Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h create mode 100644 Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h create mode 100644 Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h create mode 100644 Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h create mode 100644 Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h create mode 100644 Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c create mode 100644 Plugins/PluginNowPlaying/StdAfx.cpp create mode 100644 Plugins/PluginNowPlaying/StdAfx.h create mode 100644 Plugins/PluginNowPlaying/readme.txt create mode 100644 Plugins/PluginNowPlaying/sha2/hmac_sha2.c create mode 100644 Plugins/PluginNowPlaying/sha2/hmac_sha2.h create mode 100644 Plugins/PluginNowPlaying/sha2/sha2.c create mode 100644 Plugins/PluginNowPlaying/sha2/sha2.h create mode 100644 Plugins/PluginNowPlaying/taglib/COPYING.LGPL create mode 100644 Plugins/PluginNowPlaying/taglib/COPYING.MPL create mode 100644 Plugins/PluginNowPlaying/taglib/ape/ape-tag-format.txt create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apefile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apefile.h create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apefooter.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apefooter.h create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apeitem.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apeitem.h create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apeproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apeproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apetag.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ape/apetag.h create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asfattribute.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asfattribute.h create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asffile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asffile.h create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asfpicture.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asfpicture.h create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asfproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asfproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asftag.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/asf/asftag.h create mode 100644 Plugins/PluginNowPlaying/taglib/audioproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/audioproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/config.h create mode 100644 Plugins/PluginNowPlaying/taglib/fileref.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/fileref.h create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.h create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacpicture.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacpicture.h create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.h create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4atom.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4atom.h create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.h create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4file.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4file.h create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4item.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4item.h create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4properties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4properties.h create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4tag.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mp4/mp4tag.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpc/mpcfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpc/mpcfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.2.0.txt create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.3.0.txt create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-frames.txt create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-structure.txt create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/xingheader.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/mpeg/xingheader.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/oggfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/oggfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/oggpage.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/oggpage.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.h create mode 100644 Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.h create mode 100644 Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/riff/rifffile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/riff/rifffile.h create mode 100644 Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/tag.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/tag.h create mode 100644 Plugins/PluginNowPlaying/taglib/taglib_config.h create mode 100644 Plugins/PluginNowPlaying/taglib/taglib_export.h create mode 100644 Plugins/PluginNowPlaying/taglib/tagunion.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/tagunion.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/taglib.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tdebug.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tdebug.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tlist.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tlist.tcc create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tmap.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tmap.tcc create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tstring.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tstring.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.h create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/unicode.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/toolkit/unicode.h create mode 100644 Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.h create mode 100644 Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.h create mode 100644 Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.h create mode 100644 Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.cpp create mode 100644 Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.h diff --git a/Plugins/PluginMediaKey/PluginMediaKey.cpp b/Plugins/PluginMediaKey/PluginMediaKey.cpp index 03505543..c1442e8a 100644 --- a/Plugins/PluginMediaKey/PluginMediaKey.cpp +++ b/Plugins/PluginMediaKey/PluginMediaKey.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 poiru + Copyright (C) 2010 Birunthan Mohanathas (www.poiru.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -101,5 +101,5 @@ UINT GetPluginVersion() LPCTSTR GetPluginAuthor() { - return L"poiru"; + return L"Birunthan Mohanathas (www.poiru.net)"; } \ No newline at end of file diff --git a/Plugins/PluginMediaKey/PluginMediaKey.rc b/Plugins/PluginMediaKey/PluginMediaKey.rc index fa9dd490..6a239a70 100644 --- a/Plugins/PluginMediaKey/PluginMediaKey.rc +++ b/Plugins/PluginMediaKey/PluginMediaKey.rc @@ -31,7 +31,7 @@ BEGIN VALUE "FileDescription", "MediaKey Plugin for Rainmeter" VALUE "FileVersion", "1.0.0.0" VALUE "InternalName", "PluginMediaKey" - VALUE "LegalCopyright", "Copyright (C) 2010 - poiru" + VALUE "LegalCopyright", "Copyright (C) 2010 - Birunthan Mohanathas" VALUE "OriginalFilename", "PluginMediaKey.dll" VALUE "ProductName", "Rainmeter" #ifdef _WIN64 diff --git a/Plugins/PluginNowPlaying/NowPlaying.cpp b/Plugins/PluginNowPlaying/NowPlaying.cpp new file mode 100644 index 00000000..a38f409f --- /dev/null +++ b/Plugins/PluginNowPlaying/NowPlaying.cpp @@ -0,0 +1,478 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "../../Library/Export.h" +#include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point +#include "NowPlaying.h" +#include "PlayerAIMP.h" +#include "PlayerFoobar.h" +#include "PlayerITunes.h" +#include "PlayerSpotify.h" +#include "PlayerWinamp.h" +#include "PlayerWMP.h" + +static CPlayer* g_AIMP = NULL; +static CPlayer* g_Foobar = NULL; +static CPlayer* g_iTunes = NULL; +static CPlayer* g_Spotify = NULL; +static CPlayer* g_Winamp = NULL; +static CPlayer* g_WMP = NULL; + +static MeasureMap g_Values; +static bool g_DisableLeazingZero = false; +std::wstring g_CachePath; + +void SecondsToTime(UINT seconds, WCHAR* buffer) +{ + int hours = seconds; + int mins = seconds; + hours /= 3600; + mins %= 3600; + int secs = mins; + mins /= 60; + secs %= 60; + + if (hours) + { + _snwprintf_s(buffer, 32, _TRUNCATE, g_DisableLeazingZero ? L"%i:%02i:%02i" : L"%02i:%02i:%02i", hours, mins, secs); + } + else + { + _snwprintf_s(buffer, 32, _TRUNCATE, g_DisableLeazingZero ? L"%i:%02i" : L"%02i:%02i", mins, secs); + } +} + +/* +** Initialize +** +** Called when the measure is initialized. +** +*/ +UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id) +{ + if (g_Values.empty()) + { + WCHAR buffer[MAX_PATH]; + GetTempPath(MAX_PATH, buffer); + wcscat(buffer, L"Rainmeter-Cache\\"); + CreateDirectory(buffer, NULL); + g_CachePath = buffer; + } + + UINT maxValue = 0; + MeasureData* data = new MeasureData; + + // Read settings from the ini-file + LPCTSTR str = ReadConfigString(section, L"PlayerName", NULL); + if (str) + { + if (str[0] == L'[') + { + int len = wcslen(str) - 2; + if (len > 0) + { + MeasureMap::iterator it; + for (it = g_Values.begin(); it != g_Values.end(); ++it) + { + if (wcsncmp(&str[1], it->second->section.c_str(), len) == 0 && + wcscmp(iniFile, it->second->iniFile.c_str()) == 0) + { + // Use same player instance as pointed section + data->player = it->second->player; + } + } + + if (!data->player) + { + std::wstring error = L"NowPlayingPlugin: The referenced measure PlayerName="; + error += str; + error += L" does not exist."; + LSLog(LOG_WARNING, L"Rainmeter", error.c_str()); + return maxValue; + } + } + } + else + { + data->section = section; + data->iniFile = iniFile; + + if (_wcsicmp(L"AIMP", str) == 0) + { + if (!g_AIMP) + { + g_AIMP = new CPlayerAIMP; + } + data->player = g_AIMP; + } + else if (_wcsicmp(L"iTunes", str) == 0) + { + if (!g_iTunes) + { + g_iTunes = new CPlayerITunes; + } + data->player = g_iTunes; + } + else if (_wcsicmp(L"foobar2000", str) == 0) + { + if (!g_Foobar) + { + g_Foobar = new CPlayerFoobar; + } + data->player = g_Foobar; + } + else if (_wcsicmp(L"Spotify", str) == 0) + { + if (!g_Spotify) + { + g_Spotify = new CPlayerSpotify; + } + data->player = g_Spotify; + } + else if (_wcsicmp(L"WinAmp", str) == 0) + { + if (!g_Winamp) + { + g_Winamp = new CPlayerWinamp; + } + data->player = g_Winamp; + } + else if (_wcsicmp(L"WMP", str) == 0) + { + if (!g_WMP) + { + g_WMP = new CPlayerWMP; + } + data->player = g_WMP; + } + else + { + std::wstring error = L"PlayerName="; + error += str; + error += L" is not valid in section ["; + error += section; + error += L"] of the following file: \n\n"; + error += iniFile; + MessageBox(NULL, error.c_str(), L"Rainmeter", MB_OK | MB_ICONERROR | MB_TOPMOST); + delete data; + return maxValue; + } + + str = ReadConfigString(section, L"PlayerPath", NULL); + if (str && *str) + { + data->player->SetPlayerPath(str); + } + + str = ReadConfigString(section, L"DisableLeadingZero", NULL); + if (str && *str) + { + g_DisableLeazingZero = (1 == _wtoi(str)); + } + + str = ReadConfigString(section, L"TrackChangeAction", NULL); + if (str && *str) + { + data->player->SetTrackChangeAction(str); + } + } + } + + str = ReadConfigString(section, L"PlayerType", NULL); + if (str) + { + if (_wcsicmp(L"ARTIST", str) == 0) + { + data->measure = MEASURE_ARTIST; + } + else if (_wcsicmp(L"TITLE", str) == 0) + { + data->measure = MEASURE_TITLE; + } + else if (_wcsicmp(L"ALBUM", str) == 0) + { + data->measure = MEASURE_ALBUM; + } + else if (_wcsicmp(L"COVER", str) == 0) + { + data->measure = MEASURE_COVER; + } + else if (_wcsicmp(L"DURATION", str) == 0) + { + data->measure = MEASURE_DURATION; + } + else if (_wcsicmp(L"POSITION", str) == 0) + { + data->measure = MEASURE_POSITION; + } + else if (_wcsicmp(L"PROGRESS", str) == 0) + { + data->measure = MEASURE_PROGRESS; + maxValue = 100; + } + else if (_wcsicmp(L"RATING", str) == 0) + { + data->measure = MEASURE_RATING; + maxValue = 5; + } + else if (_wcsicmp(L"STATE", str) == 0) + { + data->measure = MEASURE_STATE; + } + else if (_wcsicmp(L"VOLUME", str) == 0) + { + data->measure = MEASURE_VOLUME; + maxValue = 100; + } + } + + data->player->AddInstance(data->measure); + g_Values[id] = data; + return maxValue; +} + +/* +** Finalize +** +** Called when the measure is destroyed (during refresh/quit). +** +*/ +void Finalize(HMODULE instance, UINT id) +{ + MeasureMap::iterator i = g_Values.find(id); + if (i != g_Values.end()) + { + (*i).second->player->RemoveInstance(); + delete (*i).second; + g_Values.erase(i); + } +} + +/* +** Update +** +** Called on each update. +** +*/ +UINT Update(UINT id) +{ + MeasureMap::iterator i = g_Values.find(id); + if (i != g_Values.end()) + { + if (!(*i).second->section.empty()) + { + // Only allow main measure to update + (*i).second->player->UpdateData(); + } + + CPlayer* player = (*i).second->player; + + switch ((*i).second->measure) + { + case MEASURE_RATING: + return player->GetRating(); + + case MEASURE_DURATION: + return player->GetDuration(); + + case MEASURE_POSITION: + return player->GetPosition(); + + case MEASURE_PROGRESS: + if (player->GetDuration()) + { + return (player->GetPosition() * 100) / player->GetDuration(); + } + return 0; + + case MEASURE_STATE: + return (int)player->GetState(); + + case MEASURE_VOLUME: + return player->GetVolume(); + } + } + + return 0; +} + +/* +** GetString +** +** Called when a string value is needed. +** +*/ +LPCTSTR GetString(UINT id, UINT flags) +{ + MeasureMap::iterator i = g_Values.find(id); + if (i != g_Values.end()) + { + CPlayer* player = (*i).second->player; + static WCHAR buffer[32]; + + switch ((*i).second->measure) + { + case MEASURE_ARTIST: + return player->GetArtist(); + + case MEASURE_TITLE: + return player->GetTitle(); + + case MEASURE_ALBUM: + return player->GetAlbum(); + + case MEASURE_COVER: + return player->GetCoverPath(); + + case MEASURE_RATING: + _itow(player->GetRating(), buffer, 10); + return buffer; + + case MEASURE_STATE: + _itow(player->GetState(), buffer, 10); + return buffer; + + case MEASURE_VOLUME: + _itow(player->GetVolume(), buffer, 10); + return buffer; + + case MEASURE_DURATION: + SecondsToTime(player->GetDuration(), buffer); + return buffer; + + case MEASURE_POSITION: + SecondsToTime(player->GetPosition(), buffer); + return buffer; + + case MEASURE_PROGRESS: + if (player->GetDuration()) + { + UINT res = (player->GetPosition() * 100) / player->GetDuration(); + _itow(res, buffer, 10); + return buffer; + } + return L"0"; + } + } + else + { + // For invalid PlayerName= + return L"0"; + } + + return L""; +} + +/* +** ExecuteBang +** +** Called when a !RainmeterPluginBang is executed. +** +*/ +void ExecuteBang(LPCTSTR bang, UINT id) +{ + MeasureMap::iterator i = g_Values.find(id); + if (i != g_Values.end()) + { + CPlayer* player = (*i).second->player; + + if (_wcsicmp(bang, L"Play") == 0) + { + player->Play(); + } + else if (_wcsicmp(bang, L"PlayPause") == 0) + { + player->PlayPause(); + } + else if (_wcsicmp(bang, L"Stop") == 0) + { + player->Stop(); + } + else if (_wcsicmp(bang, L"Next") == 0) + { + player->Next(); + } + else if (_wcsicmp(bang, L"Previous") == 0) + { + player->Previous(); + } + else if (_wcsicmp(bang, L"ClosePlayer") == 0) + { + player->ClosePlayer(); + } + else if (_wcsicmp(bang, L"OpenPlayer") == 0) + { + player->OpenPlayer(); + } + else if (_wcsicmp(bang, L"TogglePlayer") == 0) + { + player->TogglePlayer(); + } + else + { + LPCTSTR arg = wcschr(bang, L' '); + + if (++arg) // Skip the space + { + if (wcsnicmp(bang, L"SetRating", 9) == 0) + { + player->SetRating(_wtoi(arg)); + } + else if (wcsnicmp(bang, L"SetVolume", 9) == 0) + { + if (arg[0] == L'+' || arg[0] == L'-') + { + player->ChangeVolume(_wtoi(arg)); + } + else + { + player->SetVolume(_wtoi(arg)); + } + } + else + { + LSLog(LOG_WARNING, L"Rainmeter", L"NowPlayingPlugin: Unknown bang!"); + } + } + } + } +} + +/* +** GetPluginVersion +** +** Returns the version number of the plugin. +** +*/ +UINT GetPluginVersion() +{ + // Major * 1000 + Minor + return 1000; +} + +/* +** GetPluginAuthor +** +** Returns the author of the plugin for the About dialog. +** +*/ +LPCTSTR GetPluginAuthor() +{ + return L"Birunthan Mohanathas (www.poiru.net)"; +} diff --git a/Plugins/PluginNowPlaying/NowPlaying.h b/Plugins/PluginNowPlaying/NowPlaying.h new file mode 100644 index 00000000..60fa9f8f --- /dev/null +++ b/Plugins/PluginNowPlaying/NowPlaying.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __NOWPLAYING_H__ +#define __NOWPLAYING_H__ + +#include "Player.h" + +struct MeasureData +{ + std::wstring iniFile; + std::wstring section; + MEASURETYPE measure; + CPlayer* player; + + MeasureData() : + player(NULL) + { + } +}; + +typedef std::map MeasureMap; + +/* The exported functions */ +extern "C" +{ +__declspec( dllexport ) UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id); +__declspec( dllexport ) void Finalize(HMODULE instance, UINT id); +__declspec( dllexport ) UINT Update(UINT id); +__declspec( dllexport ) LPCTSTR GetString(UINT id, UINT flags); +__declspec( dllexport ) LPCTSTR GetPluginAuthor(); +__declspec( dllexport ) UINT GetPluginVersion(); +__declspec( dllexport ) void ExecuteBang(LPCTSTR bang, UINT id); +} + +#endif diff --git a/Plugins/PluginNowPlaying/Player.cpp b/Plugins/PluginNowPlaying/Player.cpp new file mode 100644 index 00000000..0bad3c03 --- /dev/null +++ b/Plugins/PluginNowPlaying/Player.cpp @@ -0,0 +1,390 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +// Common functions for the players + +#include "StdAfx.h" +#include "Player.h" + +extern std::wstring g_CachePath; + +// ======================================================================= +// PlayerData functions +// ======================================================================= + +/* +** CPlayer +** +** Constructor. +** +*/ +CPlayer::CPlayer() : + m_InstanceCount(), + m_State(), + m_Duration(), + m_Position(), + m_Rating(), + m_Volume(), + m_TrackChanged(false) +{ +} + +/* +** ~CPlayer +** +** Destructor. +** +*/ +CPlayer::~CPlayer() +{ +} + +/* +** ExecuteTrackChangeAction +** +** Called from player implementation on track change. +** +*/ +void CPlayer::ExecuteTrackChangeAction() +{ + if (!m_TrackChangeAction.empty()) + { + HWND wnd = FindWindow(L"RainmeterMeterWindow", NULL); + if (wnd != NULL) + { + COPYDATASTRUCT cds; + cds.dwData = 1; + cds.cbData = (DWORD)(m_TrackChangeAction.size() + 1) * sizeof(WCHAR); + cds.lpData = (void*)m_TrackChangeAction.c_str(); + + // Send the bang to the Rainmeter window + SendMessage(wnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds); + } + } +} +/* +** ClearInfo +** +** Clear track information. +** +*/ +void CPlayer::ClearInfo() +{ + m_Duration = 0; + m_Position = 0; + m_Rating = 0; + m_State = PLAYER_STOPPED; + m_Artist.clear(); + m_Album.clear(); + m_Title.clear(); + m_CoverPath.clear(); +} + +/* +** CreateCoverArtPath +** +** Determines the path to save cover art. +** +*/ +std::wstring CPlayer::CreateCoverArtPath() +{ + std::wstring targetPath = g_CachePath; + if (m_Artist.empty() || m_Title.empty()) + { + targetPath += L"temp.art"; + } + else + { + // Otherwise, save it as "Artist - Title.art" + std::wstring name = m_Artist; + name += L" - "; + name += m_Title; + + // Replace reserved chars with _ + std::wstring::size_type pos = 0; + while ((pos = name.find_first_of(L"\\/:*?\"<>|", pos)) != std::wstring::npos) name[pos] = L'_'; + + targetPath += name; + targetPath += L".art"; + } + + return targetPath; +} + +/* +** GetArtLocal +** +** Attemps to find local cover art in various formats. +** +*/ +bool CPlayer::GetLocalArt(std::wstring& folder, std::wstring filename) +{ + std::wstring testPath = folder; + testPath += filename; + testPath += L"."; + std::wstring::size_type origLen = testPath.length(); + + const int extCount = 4; + LPCTSTR extName[extCount] = { L"jpg", L"jpeg", L"png", L"bmp" }; + + for (int i = 0; i < extCount; ++i) + { + testPath += extName[i]; + if (_waccess(testPath.c_str(), 0) == 0) + { + m_CoverPath = testPath; + return true; + } + else + { + // Get rid of the added extension + testPath.resize(origLen); + } + } + + return false; +} + +/* +** GetEmbeddedCover +** +** Attempts to extract cover art from audio files. +** +*/ +bool CPlayer::GetEmbeddedArt(const TagLib::FileRef& fr, std::wstring& path) +{ + bool found = false; + + if (TagLib::MPEG::File* file = dynamic_cast(fr.file())) + { + if (file->ID3v2Tag()) + { + found = GetArtID3(file->ID3v2Tag(), path); + } + if (!found && file->APETag()) + { + found = GetArtAPE(file->APETag(), path); + } + } + else if (TagLib::MP4::File* file = dynamic_cast(fr.file())) + { + if (file->tag()) + { + found = GetArtMP4(file, path); + } + } + else if (TagLib::FLAC::File* file = dynamic_cast(fr.file())) + { + found = GetArtFLAC(file, path); + + if (!found && file->ID3v2Tag()) + { + found = GetArtID3(file->ID3v2Tag(), path); + } + } + else if (TagLib::ASF::File* file = dynamic_cast(fr.file())) + { + found = GetArtASF(file, path); + } + else if (TagLib::APE::File* file = dynamic_cast(fr.file())) + { + if (file->APETag()) + { + found = GetArtAPE(file->APETag(), path); + } + } + else if (TagLib::MPC::File* file = dynamic_cast(fr.file())) + { + if (file->APETag()) + { + found = GetArtAPE(file->APETag(), path); + } + } + else if (TagLib::WavPack::File* file = dynamic_cast(fr.file())) + { + if (file->APETag()) + { + found = GetArtAPE(file->APETag(), path); + } + } + + if (found) + { + m_CoverPath = path; + } + + return found; +} + +/* +** GetArtAPE +** +** Extracts cover art embedded in APE tags. +** +*/ +bool CPlayer::GetArtAPE(TagLib::APE::Tag* tag, std::wstring& path) +{ + bool ret = false; + const TagLib::APE::ItemListMap& listMap = tag->itemListMap(); + + if (listMap.contains("COVER ART (FRONT)")) + { + const TagLib::ByteVector nullStringTerminator(1, 0); + + TagLib::ByteVector item = listMap["COVER ART (FRONT)"].value(); + int pos = item.find(nullStringTerminator); // Skip the filename + + if (++pos > 0) + { + const TagLib::ByteVector& pic = item.mid(pos); + + FILE* f = _wfopen(path.c_str(), L"wb"); + if (f) + { + ret = (fwrite(pic.data(), 1, pic.size(), f) == pic.size()); + fclose(f); + } + } + } + + return ret; +} + +/* +** GetArtAPE +** +** Extracts cover art embedded in ID3v2 tags. +** +*/ +bool CPlayer::GetArtID3(TagLib::ID3v2::Tag* tag, std::wstring& path) +{ + bool ret = false; + + const TagLib::ID3v2::FrameList& frameList = tag->frameList("APIC"); + if (!frameList.isEmpty()) + { + // Grab the first image + TagLib::ID3v2::AttachedPictureFrame* frame = static_cast(frameList.front()); + TagLib::uint size = frame->picture().size(); + + if (size > 0) + { + FILE* f = _wfopen(path.c_str(), L"wb"); + if (f) + { + ret = (fwrite(frame->picture().data(), 1, size, f) == size); + fclose(f); + } + } + } + + return ret; +} + +/* +** GetArtASF +** +** Extracts cover art embedded in ASF/WMA files. +** +*/ +bool CPlayer::GetArtASF(TagLib::ASF::File* file, std::wstring& path) +{ + bool ret = false; + + const TagLib::ASF::AttributeListMap& attrListMap = file->tag()->attributeListMap(); + + if (attrListMap.contains("WM/Picture")) + { + const TagLib::ASF::AttributeList& attrList = attrListMap["WM/Picture"]; + + if (!attrList.isEmpty()) + { + // Let's grab the first cover. TODO: Check/loop for correct type + TagLib::ASF::Picture wmpic = attrList[0].toPicture(); + + if (wmpic.isValid()) + { + FILE* f = _wfopen(path.c_str(), L"wb"); + if (f) + { + ret = (fwrite(wmpic.picture().data(), 1, wmpic.picture().size(), f) == wmpic.picture().size()); + fclose(f); + } + } + } + } + + return ret; +} + +/* +** GetArtFLAC +** +** Extracts cover art embedded in FLAC files. +** +*/ +bool CPlayer::GetArtFLAC(TagLib::FLAC::File* file, std::wstring& path) +{ + bool ret = false; + + const TagLib::List& picList = file->pictureList(); + if (!picList.isEmpty()) + { + // Let's grab the first image + TagLib::FLAC::Picture* pic = picList[0]; + + FILE* f = _wfopen(path.c_str(), L"wb"); + if (f) + { + ret = (fwrite(pic->data().data(), 1, pic->data().size(), f) == pic->data().size()); + fclose(f); + } + } + + return ret; +} + +/* +** GetArtMP4 +** +** Extracts cover art embedded in MP4-like files. +** +*/ +bool CPlayer::GetArtMP4(TagLib::MP4::File* file, std::wstring& path) +{ + bool ret = false; + + TagLib::MP4::Tag* tag = file->tag(); + if (tag->itemListMap().contains("covr")) + { + TagLib::MP4::CoverArtList coverList = tag->itemListMap()["covr"].toCoverArtList(); + TagLib::uint size = coverList[0].data().size(); + + if (size > 0) + { + FILE* f = _wfopen(path.c_str(), L"wb"); + if (f) + { + ret = (fwrite(coverList[0].data().data(), 1, size, f) == size); + fclose(f); + } + } + } + + return ret; +} diff --git a/Plugins/PluginNowPlaying/Player.h b/Plugins/PluginNowPlaying/Player.h new file mode 100644 index 00000000..c89b5e5d --- /dev/null +++ b/Plugins/PluginNowPlaying/Player.h @@ -0,0 +1,135 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYER_H__ +#define __PLAYER_H__ + +// SHA +#include "hmac_sha2.h" +#include "sha2.h" + +// TagLib +#include "apefile.h" +#include "apetag.h" +#include "asffile.h" +#include "attachedpictureframe.h" +#include "commentsframe.h" +#include "flacfile.h" +#include "id3v1genres.h" +#include "id3v2tag.h" +#include "mpcfile.h" +#include "mp4file.h" +#include "mpegfile.h" +#include "tag.h" +#include "taglib.h" +#include "textidentificationframe.h" +#include "tstring.h" +#include "vorbisfile.h" +#include "wavpackfile.h" + +// Amazon keys +#define ACCESSKEY L"AKIAIDIAU7MXWSOJF3PQ" +#define SECRETKEY "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" + +enum PLAYERSTATE +{ + PLAYER_STOPPED, + PLAYER_PLAYING, + PLAYER_PAUSED +}; + +enum MEASURETYPE +{ + MEASURE_ARTIST, + MEASURE_TITLE, + MEASURE_ALBUM, + MEASURE_COVER, + MEASURE_DURATION, + MEASURE_POSITION, + MEASURE_PROGRESS, + MEASURE_RATING, + MEASURE_STATE, + MEASURE_VOLUME +}; + +class CPlayer +{ +public: + CPlayer(); + virtual ~CPlayer(); + + virtual void Play() {} + virtual void PlayPause() {} + virtual void Stop() {} + virtual void Next() {} + virtual void Previous() {} + virtual void SetRating(int rating) {} + virtual void SetVolume(int volume) {} + virtual void ChangeVolume(int volume) {} + virtual void OpenPlayer() {} + virtual void ClosePlayer() {} + virtual void TogglePlayer() {} + + virtual void AddInstance(MEASURETYPE type) = 0; + virtual void RemoveInstance() = 0; + virtual void UpdateData() = 0; + + PLAYERSTATE GetState() { return m_State; } + LPCTSTR GetArtist() { return m_Artist.c_str(); } + LPCTSTR GetAlbum() { return m_Album.c_str(); } + LPCTSTR GetTitle() { return m_Title.c_str(); } + LPCTSTR GetCoverPath() { return m_CoverPath.c_str(); } + LPCTSTR GetPlayerPath() { return m_PlayerPath.c_str(); } + UINT GetDuration() { return m_Duration; } + UINT GetPosition() { return m_Position; } + UINT GetRating() { return m_Rating; } + UINT GetVolume() { return m_Volume; } + + void SetPlayerPath(LPCTSTR path) { m_PlayerPath = path; } + void SetTrackChangeAction(LPCTSTR action) { m_TrackChangeAction = action; } + void ExecuteTrackChangeAction(); + void ClearInfo(); + + std::wstring CreateCoverArtPath(); + bool GetLocalArt(std::wstring& folder, std::wstring filename); + bool GetEmbeddedArt(const TagLib::FileRef& fr, std::wstring& path); + bool GetArtAPE(TagLib::APE::Tag* tag, std::wstring& path); + bool GetArtID3(TagLib::ID3v2::Tag* tag, std::wstring& path); + bool GetArtASF(TagLib::ASF::File* file, std::wstring& path); + bool GetArtFLAC(TagLib::FLAC::File* file, std::wstring& path); + bool GetArtMP4(TagLib::MP4::File* file, std::wstring& path); + +protected: + int m_InstanceCount; + bool m_TrackChanged; + + PLAYERSTATE m_State; + std::wstring m_Artist; + std::wstring m_Album; + std::wstring m_Title; + std::wstring m_CoverPath; // Path to cover art image + std::wstring m_PlayerPath; // Path to player executable + UINT m_Duration; // Track duration in seconds + UINT m_Position; // Current position in seconds + UINT m_Rating; // Track rating from 0 to 100 + UINT m_Volume; // Volume from 0 to 100 + + std::wstring m_TrackChangeAction; +}; + +#endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.cpp b/Plugins/PluginNowPlaying/PlayerAIMP.cpp new file mode 100644 index 00000000..40255dd9 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerAIMP.cpp @@ -0,0 +1,464 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "PlayerAIMP.h" + +/* +** CPlayerAIMP +** +** Constructor. +** +*/ +CPlayerAIMP::CPlayerAIMP() : + m_HasCoverMeasure(false), + m_FileMap(), + m_FileMapHandle(), + m_Window(), + m_WinampWindow() +{ +} + +/* +** ~CPlayerAIMP +** +** Destructor. +** +*/ +CPlayerAIMP::~CPlayerAIMP() +{ + if (m_FileMap) UnmapViewOfFile(m_FileMap); + if (m_FileMapHandle) CloseHandle(m_FileMapHandle); +} + +/* +** AddInstance +** +** Called during initialization of each measure. +** +*/ +void CPlayerAIMP::AddInstance(MEASURETYPE type) +{ + ++m_InstanceCount; + + if (type == MEASURE_COVER) + { + m_HasCoverMeasure = true; + } +} + +/* +** RemoveInstance +** +** Called during destruction of each measure. +** +*/ +void CPlayerAIMP::RemoveInstance() +{ + if (--m_InstanceCount == 0) + { + delete this; + } +} + +bool CPlayerAIMP::Initialize() +{ + m_Window = FindWindow(L"AIMP2_RemoteInfo", L"AIMP2_RemoteInfo"); + m_WinampWindow = FindWindow(L"Winamp v1.x", NULL); + + if (m_Window) + { + m_FileMapHandle = OpenFileMapping(FILE_MAP_READ, FALSE, L"AIMP2_RemoteInfo"); + if (!m_FileMapHandle) + { + LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: AIMP - Unable to access mapping."); + return false; + } + + m_FileMap = (LPVOID)MapViewOfFile(m_FileMapHandle, FILE_MAP_READ, 0, 0, 2048); + if (!m_FileMap) + { + LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: AIMP - Unable to view mapping."); + return false; + } + + return true; + } + + return false; +} + +bool CPlayerAIMP::CheckActive() +{ + if (m_Window) + { + if (!IsWindow(m_Window)) + { + m_Window = NULL; + m_WinampWindow = NULL; + if (m_FileMap) UnmapViewOfFile(m_FileMap); + if (m_FileMapHandle) CloseHandle(m_FileMapHandle); + ClearInfo(); + return false; + } + + return true; + } + else + { + static DWORD oldTime = 0; + DWORD time = GetTickCount(); + + // Try to find AIMP every 5 seconds + if (time - oldTime > 5000) + { + oldTime = time; + return Initialize(); + } + + return false; + } +} + +/* +** UpdateData +** +** Called during each update of the main measure. +** +*/ +void CPlayerAIMP::UpdateData() +{ + static long oldFileSize; + static UINT oldTitleLen; + + if (!CheckActive()) + { + // Make sure AIMP is running + if (oldFileSize != 0) + { + oldFileSize = 0; + oldTitleLen = 0; + } + return; + } + + m_State = (PLAYERSTATE)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_Player); + if (m_State == PLAYER_STOPPED) + { + if (oldFileSize != 0) + { + oldFileSize = 0; + oldTitleLen = 0; + ClearInfo(); + } + return; + } + + if (m_TrackChanged) + { + ExecuteTrackChangeAction(); + m_TrackChanged = false; + } + + m_Position = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_POS); + m_Volume = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_VOLUME); + + AIMP2FileInfo* info = (AIMP2FileInfo*)m_FileMap; + if (info->cbSizeOf > 0 && + info->nFileSize != oldFileSize || // FileSize and TitleLen are probably unique enough + info->nTitleLen != oldTitleLen) + { + m_TrackChanged = true; + oldFileSize = info->nFileSize; + oldTitleLen = info->nTitleLen; + + // 44 is sizeof(AIMP2FileInfo) / 2 (due to WCHAR being 16-bit). + // Written explicitly due to size differences in 32bit/64bit. + LPCTSTR stringData = (LPCTSTR)m_FileMap; + stringData += 44; + + m_Album.assign(stringData, info->nAlbumLen); + + stringData += info->nAlbumLen; + m_Artist.assign(stringData, info->nArtistLen); + + stringData += info->nArtistLen; + stringData += info->nDateLen; + std::wstring filename(stringData, info->nFileNameLen); + + stringData += info->nFileNameLen; + stringData += info->nGenreLen; + m_Title.assign(stringData, info->nTitleLen); + + m_Duration = info->nDuration / 1000; + + if (m_WinampWindow) + { + // Get the rating through the AIMP Winamp API + m_Rating = SendMessage(m_WinampWindow, WM_WA_IPC, 0, IPC_GETRATING); + } + + if (m_HasCoverMeasure) + { + std::wstring cover = CreateCoverArtPath(); + if (_waccess(cover.c_str(), 0) == 0) + { + // Cover is in cache, lets use the that + m_CoverPath = cover; + return; + } + + TagLib::FileRef fr(filename.c_str()); + if (!fr.isNull() && fr.tag() && GetEmbeddedArt(fr, cover)) + { + // Embedded art found + return; + } + + // Get rid of the name and extension from filename + std::wstring trackFolder = filename; + std::wstring::size_type pos = trackFolder.find_last_of(L'\\'); + if (pos == std::wstring::npos) return; + trackFolder.resize(++pos); + + if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder")) + { + // Local art found + return; + } + + // Nothing found + m_CoverPath.clear(); + } + } +} + +/* +** Play +** +** Handles the Play bang. +** +*/ +void CPlayerAIMP::Play() +{ + if (m_Window) + { + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PLAY); + } +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerAIMP::PlayPause() +{ + if (m_Window) + { + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, (m_State == PLAYER_STOPPED) ? AIMP_PLAY : AIMP_PAUSE); + } +} + +/* +** Stop +** +** Handles the Stop bang. +** +*/ +void CPlayerAIMP::Stop() +{ + if (m_Window) + { + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_STOP); + } +} + +/* +** Next +** +** Handles the Next bang. +** +*/ +void CPlayerAIMP::Next() +{ + if (m_Window) + { + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_NEXT); + } +} + +/* +** Previous +** +** Handles the Previous bang. +** +*/ +void CPlayerAIMP::Previous() +{ + if (m_Window) + { + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PREV); + } +} + +/* +** SetRating +** +** Handles the SetRating bang. +** +*/ +void CPlayerAIMP::SetRating(int rating) +{ + // Set rating through the AIMP Winamp API + if (m_WinampWindow && (m_State == PLAYER_PLAYING || m_State == PLAYER_PAUSED)) + { + if (rating < 0) + { + rating = 0; + } + else if (rating > 5) + { + rating = 5; + } + + SendMessage(m_WinampWindow, WM_WA_IPC, rating, IPC_SETRATING); + m_Rating = rating; + } +} + +/* +** Previous +** +** Handles the SetVolume bang. +** +*/ +void CPlayerAIMP::SetVolume(int volume) +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(volume, AIMP_STS_VOLUME)); +} + +/* +** ChangeVolume +** +** Handles the ChangeVolume bang. +** +*/ +void CPlayerAIMP::ChangeVolume(int volume) +{ + volume += m_Volume; + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(volume, AIMP_STS_VOLUME)); +} + +/* +** ClosePlayer +** +** Handles the ClosePlayer bang. +** +*/ +void CPlayerAIMP::ClosePlayer() +{ + if (m_Window) + { + SendMessage(m_Window, WM_CLOSE, 0, 0); + } +} + +/* +** OpenPlayer +** +** Handles the OpenPlayer bang. +** +*/ +void CPlayerAIMP::OpenPlayer() +{ + if (m_PlayerPath.empty()) + { + // Check for AIMP2 first + DWORD size = 512; + WCHAR* data = new WCHAR[size]; + DWORD type = 0; + HKEY hKey; + + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\AIMP2", + 0, + KEY_QUERY_VALUE, + &hKey); + + if (RegQueryValueEx(hKey, + L"DisplayIcon", + NULL, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + ShellExecute(NULL, L"open", data, NULL, NULL, SW_SHOW); + m_PlayerPath = data; + } + } + else + { + // Let's try AIMP3 + RegCloseKey(hKey); + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\AIMP3", + 0, + KEY_QUERY_VALUE, + &hKey); + + if (RegQueryValueEx(hKey, + L"DisplayIcon", + NULL, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + std::wstring path = data; + path.resize(path.find_last_of(L'\\') + 1); + path += L"AIMP3.exe"; + ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW); + m_PlayerPath = data; + } + } + } + + delete [] data; + RegCloseKey(hKey); + } + else + { + ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW); + } +} + +/* +** TogglePlayer +** +** Handles the TogglePlayer bang. +** +*/ +void CPlayerAIMP::TogglePlayer() +{ + m_Window ? ClosePlayer() : OpenPlayer(); +} diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.h b/Plugins/PluginNowPlaying/PlayerAIMP.h new file mode 100644 index 00000000..b2645814 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerAIMP.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYERAIMP_H__ +#define __PLAYERAIMP_H__ + +#include +#include "Player.h" + +#include "AIMP/aimp2_sdk.h" +#include "Winamp/wa_ipc.h" + +class CPlayerAIMP : public CPlayer +{ +public: + CPlayerAIMP(); + ~CPlayerAIMP(); + + virtual void Play(); + virtual void PlayPause(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void ChangeVolume(int volume); + virtual void ClosePlayer(); + virtual void OpenPlayer(); + virtual void TogglePlayer(); + + virtual void AddInstance(MEASURETYPE type); + virtual void RemoveInstance(); + virtual void UpdateData(); + +private: + bool Initialize(); + bool CheckActive(); + + bool m_HasCoverMeasure; + LPVOID m_FileMap; + HANDLE m_FileMapHandle; + HWND m_Window; // AIMP window + HWND m_WinampWindow; // AIMP Winamp API window +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerFoobar.cpp b/Plugins/PluginNowPlaying/PlayerFoobar.cpp new file mode 100644 index 00000000..ce4555e9 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerFoobar.cpp @@ -0,0 +1,502 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "PlayerFoobar.h" + +/* +** CPlayerFoobar +** +** Constructor. +** +*/ +CPlayerFoobar::CPlayerFoobar() : + m_HasCoverMeasure(false), + m_Window(), + m_FooWindow() +{ + Initialize(); +} + +/* +** ~CPlayerFoobar +** +** Constructor. +** +*/ +CPlayerFoobar::~CPlayerFoobar() +{ + Uninitialize(); +} + +/* +** AddInstance +** +** Called during initialization of each measure. +** +*/ +void CPlayerFoobar::AddInstance(MEASURETYPE type) +{ + ++m_InstanceCount; + + if (type == MEASURE_COVER) + { + m_HasCoverMeasure = true; + } +} + +/* +** RemoveInstance +** +** Called during destruction of each measure. +** +*/ +void CPlayerFoobar::RemoveInstance() +{ + if (--m_InstanceCount == 0) + { + delete this; + } +} + +/* +** Initialize +** +** Create receiver window. +** +*/ +void CPlayerFoobar::Initialize() +{ + HINSTANCE hInstance = GetModuleHandle(NULL); + + // Create windows class + WNDCLASS wc = {0}; + wc.hInstance = hInstance; + wc.lpfnWndProc = WndProc; + wc.lpszClassName = L"NowPlayingFoobarClass"; + RegisterClass(&wc); + + // Create dummy window + m_Window = CreateWindow(L"NowPlayingFoobarClass", + L"ReceiverWindow", + WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + this); + + m_FooWindow = FindWindow(L"foo_rainmeter_class", NULL); + if (m_FooWindow) + { + int version = (int)SendMessage(m_FooWindow, WM_USER, 0, FOO_GETVERSION); + if (version < 100) + { + std::wstring error = L"Your copy of the foo_rainmeter.dll plugin is outdated.\n"; + error += L"Please download the latest version and try again."; + MessageBox(NULL, error.c_str(), L"Rainmeter", MB_OK | MB_ICONERROR | MB_TOPMOST); + m_FooWindow = NULL; + } + else + { + SendMessage(m_FooWindow, WM_USER, (WPARAM)m_Window, FOO_SETCALLBACK); + } + } +} + +/* +** Uninitialize +** +** Destroy reciever window. +** +*/ +void CPlayerFoobar::Uninitialize() +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_REMOVECALLBACK); + } + + DestroyWindow(m_Window); + UnregisterClass(L"NowPlayingFoobarClass", GetModuleHandle(NULL)); +} + +/* +** WndProc +** +** Window procedure for the reciever window. +** +*/ +LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static CPlayerFoobar* foobar; + + switch (msg) + { + case WM_CREATE: + { + // Get pointer to the CPlayerFoobar class from the CreateWindow call + LPVOID params = ((CREATESTRUCT*)lParam)->lpCreateParams; + foobar = (CPlayerFoobar*)params; + return 0; + } + + case WM_USER: + switch (lParam) + { + case FOO_GETVERSION: + return 100; + + case FOO_STATECHANGE: + { + PLAYERSTATE ps = (PLAYERSTATE)wParam; + if (ps == PLAYER_STOPPED) + { + foobar->ClearInfo(); + } + else + { + foobar->m_State = ps; + } + } + break; + + case FOO_TIMECHANGE: + foobar->m_Position = (UINT)wParam; + break; + + case FOO_VOLUMECHANGE: + foobar->m_Volume = (UINT)wParam; + break; + + case FOO_PLAYERSTART: + foobar->m_FooWindow = (HWND)wParam; + break; + + case FOO_PLAYERQUIT: + foobar->m_FooWindow = NULL; + foobar->ClearInfo(); + break; + } + return 0; + + case WM_COPYDATA: + { + PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam; + + if (cds->dwData == FOO_TRACKCHANGE) + { + if (foobar->m_State != PLAYER_PLAYING) + { + foobar->m_State = PLAYER_PLAYING; + } + + if (foobar->m_Position != 0) + { + foobar->m_Position = 0; + foobar->m_TrackChanged = true; + } + + // In the format "TITLE ARTIST ALBUM LENGTH RATING" (seperated by \t) + WCHAR buffer[1024]; + MultiByteToWideChar(CP_UTF8, 0, (char*)cds->lpData, cds->cbData, buffer, 1024); + foobar->m_Artist = buffer; + + WCHAR* token = wcstok(buffer, L"\t"); + if (token) + { + foobar->m_Title = token; + } + token = wcstok(NULL, L"\t"); + if (token) + { + foobar->m_Artist = token; + } + token = wcstok(NULL, L"\t"); + if (token) + { + foobar->m_Album = token; + } + token = wcstok(NULL, L"\t"); + if (token) + { + foobar->m_Duration = _wtoi(token); + } + token = wcstok(NULL, L"\t"); + if (token) + { + foobar->m_Rating = _wtoi(token); + } + token = wcstok(NULL, L"\t"); + if (token) + { + foobar->GetCoverArt(token); + } + } + } + return 0; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } +} + +/* +** GetCoverArt +** +** Try to find cover art for file. +** +*/ +void CPlayerFoobar::GetCoverArt(LPTSTR filename) +{ + // TODO: Fix temp solution + if (m_HasCoverMeasure || m_InstanceCount == 0) + { + std::wstring cover = CreateCoverArtPath(); + if (_waccess(cover.c_str(), 0) == 0) + { + // Cover is in cache, lets use the that + m_CoverPath = cover; + return; + } + + TagLib::FileRef fr(filename); + if (!fr.isNull() && fr.tag() && GetEmbeddedArt(fr, cover)) + { + // Embedded art found + return; + } + + // Get rid of the name and extension from filename + std::wstring trackFolder = filename; + std::wstring::size_type pos = trackFolder.find_last_of(L'\\'); + if (pos == std::wstring::npos) return; + trackFolder.resize(++pos); + + if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder")) + { + // Local art found + return; + } + + // Nothing found + m_CoverPath.clear(); + } +} + +/* +** UpdateData +** +** Called during each update of the main measure. +** +*/ +void CPlayerFoobar::UpdateData() +{ + if (m_TrackChanged) + { + ExecuteTrackChangeAction(); + m_TrackChanged = false; + } +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerFoobar::Play() +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_PLAY); + } +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerFoobar::PlayPause() +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_PLAYPAUSE); + } +} + +/* +** Stop +** +** Handles the Stop bang. +** +*/ +void CPlayerFoobar::Stop() +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_STOP); + } +} + +/* +** Next +** +** Handles the Next bang. +** +*/ +void CPlayerFoobar::Next() +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_NEXT); + } +} + +/* +** Previous +** +** Handles the Previous bang. +** +*/ +void CPlayerFoobar::Previous() +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_PREVIOUS); + } +} + +/* +** ChangeVolume +** +** Handles the ChangeVolume bang. +** +*/ +void CPlayerFoobar::ChangeVolume(int volume) +{ + if (m_FooWindow) + { + volume += m_Volume; + SendMessage(m_FooWindow, WM_USER, volume, FOO_SETVOLUME); + } +} + +/* +** SetVolume +** +** Handles the SetVolume bang. +** +*/ +void CPlayerFoobar::SetVolume(int volume) +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, volume, FOO_SETVOLUME); + } +} + +/* +** ClosePlayer +** +** Handles the ClosePlayer bang. +** +*/ +void CPlayerFoobar::ClosePlayer() +{ + if (m_FooWindow) + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_QUITPLAYER); + } +} + +/* +** OpenPlayer +** +** Handles the OpenPlayer bang. +** +*/ +void CPlayerFoobar::OpenPlayer() +{ + if (!m_FooWindow) + { + if (m_PlayerPath.empty()) + { + // Gotta figure out where foobar2000 is located at + HKEY hKey; + RegOpenKeyEx(HKEY_CLASSES_ROOT, + L"Applications\\foobar2000.exe\\shell\\open\\command", + 0, + KEY_QUERY_VALUE, + &hKey); + + DWORD size = 512; + WCHAR* data = new WCHAR[size]; + DWORD type = 0; + + if (RegQueryValueEx(hKey, + NULL, + NULL, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ && data[0] == L'\"') + { + std::wstring path = data; + path.erase(0, 1); // Get rid of the leading quote + std::wstring::size_type pos = path.find_first_of(L'\"'); + + if (pos != std::wstring::npos) + { + path.resize(pos); // Get rid the last quote and everything after it + ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW); + m_PlayerPath = path; + } + } + } + + delete [] data; + RegCloseKey(hKey); + } + else + { + ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW); + } + } + else + { + SendMessage(m_FooWindow, WM_USER, 0, FOO_SHOWPLAYER); + } +} + +/* +** TogglePlayer +** +** Handles the TogglePlayer bang. +** +*/ +void CPlayerFoobar::TogglePlayer() +{ + m_FooWindow ? ClosePlayer() : OpenPlayer(); +} diff --git a/Plugins/PluginNowPlaying/PlayerFoobar.h b/Plugins/PluginNowPlaying/PlayerFoobar.h new file mode 100644 index 00000000..d3f19c9c --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerFoobar.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYERFOOBAR_H__ +#define __PLAYERFOOBAR_H__ + +#include "Player.h" + +class CPlayerFoobar : public CPlayer +{ +public: + CPlayerFoobar(); + ~CPlayerFoobar(); + + virtual void Play(); + virtual void PlayPause(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetRating(int rating) {} + virtual void SetVolume(int volume); + virtual void ChangeVolume(int volume); + virtual void ClosePlayer(); + virtual void OpenPlayer(); + virtual void TogglePlayer(); + + virtual void AddInstance(MEASURETYPE type); + virtual void RemoveInstance(); + virtual void UpdateData(); + +private: + enum FOOMESSAGE + { + FOO_TRACKCHANGE = 100, + FOO_STATECHANGE, + FOO_TIMECHANGE, + FOO_VOLUMECHANGE, + FOO_PLAYERSTART, + FOO_PLAYERQUIT + }; + + enum FOOCOMMAND + { + FOO_GETVERSION, + FOO_PLAY, + FOO_PLAYPAUSE, + FOO_PAUSE, + FOO_STOP, + FOO_NEXT, + FOO_PREVIOUS, + FOO_SETRATING, + FOO_SETVOLUME, + FOO_SHOWPLAYER, + FOO_QUITPLAYER, + FOO_SETCALLBACK, + FOO_REMOVECALLBACK + }; + + void Initialize(); + void Uninitialize(); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + void GetCoverArt(LPTSTR filename); + + bool m_HasCoverMeasure; + HWND m_Window; // Our reciever window + HWND m_FooWindow; // Foobar receiver window +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerGeneric.cpp b/Plugins/PluginNowPlaying/PlayerGeneric.cpp new file mode 100644 index 00000000..ee0b4a53 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerGeneric.cpp @@ -0,0 +1,163 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "PlayerGeneric.h" + +extern std::wstring g_CachePath; + +/* +** CPlayerGeneric +** +** Constructor. +** +*/ +CPlayerGeneric::CPlayerGeneric() +{ +} + +/* +** ~CPlayerGeneric +** +** Destructor. +** +*/ +CPlayerGeneric::~CPlayerGeneric() +{ +} + +/* +** AddInstance +** +** Called during initialization of each measure. +** +*/ +void CPlayerGeneric::AddInstance(MEASURETYPE type) +{ + ++m_InstanceCount; +} + +/* +** RemoveInstance +** +** Called during destruction of each measure. +** +*/ +void CPlayerGeneric::RemoveInstance() +{ + if (--m_InstanceCount == 0) + { + delete this; + } +} + +/* +** UpdateData +** +** Called during each update of the main measure. +** +*/ +void CPlayerGeneric::UpdateData() +{ + // The main measure is the measure without square brackets in MediaPlayer=. In other words, + // MediaPlayer=SOME_MEDIA_PLAYER is the main measure, whereas MediaPlayer=[MAIN_MEASURE] is not. +} + +/* +** Play +** +** Handles the Play bang. +** +*/ +void CPlayerGeneric::Play() +{ +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerGeneric::PlayPause() +{ +} + +/* +** Stop +** +** Handles the Stop bang. +** +*/ +void CPlayerGeneric::Stop() +{ +} + +/* +** Next +** +** Handles the Next bang. +** +*/ +void CPlayerGeneric::Next() +{ +} + +/* +** Previous +** +** Handles the Previous bang. +** +*/ +void CPlayerGeneric::Previous() +{ +} + +/* +** SetRating +** +** Handles the SetRating bang. +** +*/ +void CPlayerGeneric::SetRating(int rating) +{ + // rating is between 0 - 5 +} + +/* +** ChangeVolume +** +** Handles the ChangeVolume bang. +** +*/ +void CPlayerGeneric::ChangeVolume(int volume) +{ + // volume is either positive or negative (increase/decrease current volume by that many %). + // Remember to handle special cases if necessary (e.g. current volume is 90% and ChangeVolume(50) is called). +} + +/* +** SetVolume +** +** Handles the SetVolume bang. +** +*/ +void CPlayerGeneric::SetVolume(int volume) +{ + // volume is between 0 - 100 +} diff --git a/Plugins/PluginNowPlaying/PlayerGeneric.h b/Plugins/PluginNowPlaying/PlayerGeneric.h new file mode 100644 index 00000000..a30714ac --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerGeneric.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYERGENERIC_H__ +#define __PLAYERGENERIC_H__ + +#include "Player.h" + +class CPlayerGeneric : public CPlayer +{ +public: + CPlayerGeneric(); + ~CPlayerGeneric(); + + virtual void Play(); + virtual void PlayPause(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void ChangeVolume(int volume); + + virtual void SetPlayerPath(LPCTSTR path) { m_PlayerPath = path; } + + virtual void AddInstance(MEASURETYPE type); + virtual void RemoveInstance(); + virtual void UpdateData(); +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerITunes.cpp b/Plugins/PluginNowPlaying/PlayerITunes.cpp new file mode 100644 index 00000000..87ebcc97 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerITunes.cpp @@ -0,0 +1,587 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "PlayerITunes.h" + +extern std::wstring g_CachePath; + +/* +** CEventHandler +** +** Constructor. +** +*/ +CPlayerITunes::CEventHandler::CEventHandler(CPlayerITunes* player) : + m_iTunes(player), + m_TypeInfo(), + m_RefCount() +{ + ITypeLib* pITypeLib = NULL; + HRESULT hr = LoadRegTypeLib(LIBID_iTunesLib, 1, 5, 0x00, &pITypeLib); + + // Get type information for the interface of the object. + hr = pITypeLib->GetTypeInfoOfGuid(DIID__IiTunesEvents, &m_TypeInfo); + pITypeLib->Release(); +} + +/* +** ~CEventHandler +** +** Destructor. +** +*/ +CPlayerITunes::CEventHandler::~CEventHandler() +{ +} + +HRESULT STDMETHODCALLTYPE CPlayerITunes::CEventHandler::QueryInterface(REFIID iid, void** ppvObject) +{ + if (iid == IID_IUnknown || iid == IID_IUnknown || iid == DIID__IiTunesEvents) + { + ++m_RefCount; + *ppvObject = this; + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE CPlayerITunes::CEventHandler::AddRef() +{ + InterlockedIncrement(&m_RefCount); + return m_RefCount; +} + +ULONG STDMETHODCALLTYPE CPlayerITunes::CEventHandler::Release() +{ + InterlockedDecrement(&m_RefCount); + if (m_RefCount == 0) + { + delete this; + return 0; + } + return m_RefCount; +} + +HRESULT STDMETHODCALLTYPE CPlayerITunes::CEventHandler::Invoke(DISPID dispidMember, REFIID, LCID, WORD, DISPPARAMS* dispParams, VARIANT*, EXCEPINFO*, UINT*) +{ + switch (dispidMember) + { + case ITEventPlayerPlay: + m_iTunes->OnStateChange(true); + m_iTunes->OnTrackChange(); + break; + + case ITEventPlayerStop: + m_iTunes->OnStateChange(false); + break; + + case ITEventPlayerPlayingTrackChanged: + m_iTunes->OnTrackChange(); + break; + + case ITEventSoundVolumeChanged: + m_iTunes->OnVolumeChange(dispParams->rgvarg[0].intVal); + break; + + case ITEventAboutToPromptUserToQuit: + m_iTunes->m_UserQuitPrompt = true; + m_iTunes->Uninitialize(); + break; + } + + return S_OK; +} + +/* +** CPlayerITunes +** +** Constructor. +** +*/ +CPlayerITunes::CPlayerITunes() : + m_Initialized(false), + m_UserQuitPrompt(false), + m_HasCoverMeasure(false), + m_Window(), + m_iTunes(), + m_iTunesEvent(), + m_ConnectionPoint(), + m_ConnectionCookie() +{ + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); +} + +/* +** ~CPlayerITunes +** +** Destructor. +** +*/ +CPlayerITunes::~CPlayerITunes() +{ + Uninitialize(); + CoUninitialize(); +} + +/* +** AddInstance +** +** Called during initialization of each measure. +** +*/ +void CPlayerITunes::AddInstance(MEASURETYPE type) +{ + ++m_InstanceCount; + + if (type == MEASURE_COVER) + { + m_HasCoverMeasure = true; + } +} + +/* +** RemoveInstance +** +** Called during destruction of each measure. +** +*/ +void CPlayerITunes::RemoveInstance() +{ + if (--m_InstanceCount == 0) + { + delete this; + } +} + +/* +** Initialize +** +** Initialize iTunes COM interface and event handler. +** +*/ +void CPlayerITunes::Initialize() +{ + while (true) + { + HRESULT hr = CoCreateInstance(CLSID_iTunesApp, NULL, CLSCTX_LOCAL_SERVER, IID_IiTunes, (PVOID*)&m_iTunes); + + if (hr == CO_E_SERVER_EXEC_FAILURE) + { + // This seems to happen if there is a modal dialog being shown in iTunes + // or some other delay has occurred. Retrying should do the trick. + continue; + } + else if (hr != S_OK) + { + // Failed to get hold of iTunes instance via COM + m_iTunes = NULL; + } + + break; + } + + if (m_iTunes) + { + m_Initialized = true; + + // Set up event handler + IConnectionPointContainer* icpc; + m_iTunes->QueryInterface(IID_IConnectionPointContainer, (void **)&icpc); + icpc->FindConnectionPoint(DIID__IiTunesEvents, &m_ConnectionPoint); + icpc->Release(); + m_iTunesEvent = new CEventHandler(this); + m_ConnectionPoint->Advise(m_iTunesEvent, &m_ConnectionCookie); + + // Try getting track info and player state + ITPlayerState state; + if (SUCCEEDED(m_iTunes->get_PlayerState(&state))) + { + if (state == ITPlayerStateStopped) + { + // Determine if paused of stopped + long position; + m_iTunes->get_PlayerPosition(&position); + + if (position != 0) + { + m_State = PLAYER_PAUSED; + } + } + else if (state == ITPlayerStatePlaying) + { + m_State = PLAYER_PLAYING; + } + + if (m_State != PLAYER_STOPPED) + { + OnTrackChange(); + } + + long volume; + m_iTunes->get_SoundVolume(&volume); + m_Volume = (UINT)volume; + } + } + else + { + m_Initialized = false; + LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to get hold of iTunes instance via COM."); + } +} + +/* +** Uninitialize +** +** Close iTunes COM interface. +** +*/ +void CPlayerITunes::Uninitialize() +{ + if (m_Initialized) + { + m_Initialized = false; + + if (m_iTunes) + { + m_iTunes->Release(); + m_iTunesEvent->Release(); + } + + if (m_ConnectionPoint) + { + m_ConnectionPoint->Unadvise(m_ConnectionCookie); + m_ConnectionPoint->Release(); + } + + ClearInfo(); + } +} + +bool CPlayerITunes::CheckActive() +{ + static DWORD oldTime = 0; + DWORD time = GetTickCount(); + + if (time - oldTime > 5000) + { + oldTime = time; + m_Window = FindWindow(L"iTunes", L"iTunes"); + return m_Window ? true : false; + } + + return false; +} + +/* +** UpdateData +** +** Called during each update of the main measure. +** +*/ +void CPlayerITunes::UpdateData() +{ + if (m_Initialized) + { + if (m_TrackChanged) + { + ExecuteTrackChangeAction(); + m_TrackChanged = false; + } + + long position; + m_iTunes->get_PlayerPosition(&position); + m_Position = (UINT)position; + } + else + { + if (CheckActive()) + { + if (!m_UserQuitPrompt) + { + Initialize(); + } + } + else if (m_UserQuitPrompt) + { + m_UserQuitPrompt = false; + } + } +} + +/* +** OnTrackChange +** +** Called by iTunes event handler on track change. +** +*/ +void CPlayerITunes::OnTrackChange() +{ + IITTrack* track; + HRESULT hr = m_iTunes->get_CurrentTrack(&track); + + if (SUCCEEDED(hr)) + { + m_TrackChanged = true; + CComBSTR tmpStr; + long tmpVal; + + // Get metadata + track->get_Artist(&tmpStr); + tmpStr ? (m_Artist = tmpStr) : m_Artist.clear(); + + track->get_Name(&tmpStr); + tmpStr ? (m_Title = tmpStr) : m_Title.clear(); + + track->get_Album(&tmpStr); + tmpStr ? (m_Album = tmpStr) : m_Album.clear(); + + track->get_Duration(&tmpVal); + m_Duration = (UINT)tmpVal; + + track->get_Rating(&tmpVal); + tmpVal /= 20L; + m_Rating = (UINT)tmpVal; + + if (m_HasCoverMeasure) + { + // Check if MP3 file contains embedded art + std::wstring cover = CreateCoverArtPath(); + if (_waccess(cover.c_str(), 0) == 0) + { + // Cover is in cache, lets use the that + m_CoverPath = cover; + } + else + { + IITArtworkCollection* artworkCollection; + hr = track->get_Artwork(&artworkCollection); + + if (SUCCEEDED(hr)) + { + long count; + artworkCollection->get_Count(&count); + + if (count > 0) + { + IITArtwork* artwork; + hr = artworkCollection->get_Item(1, &artwork); + + if (SUCCEEDED(hr)) + { + tmpStr = cover.c_str(); + hr = artwork->SaveArtworkToFile(tmpStr); + SUCCEEDED(hr) ? m_CoverPath = cover : m_CoverPath.clear(); + + artwork->Release(); + } + } + else + { + m_CoverPath.clear(); + } + + artworkCollection->Release(); + } + } + } + + track->Release(); + } + else + { + ClearInfo(); + } +} + +/* +** OnStateChange +** +** Called by iTunes event handler on player state change. +** +*/ +void CPlayerITunes::OnStateChange(bool playing) +{ + if (playing) + { + m_State = PLAYER_PLAYING; + } + else + { + // Guess if paused or stopped from track time + m_State = (m_Position == 0) ? PLAYER_STOPPED : PLAYER_PAUSED; + } +} + +/* +** OnVolumeChange +** +** Called by iTunes event handler on volume change. +** +*/ +void CPlayerITunes::OnVolumeChange(int volume) +{ + m_Volume = volume; +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerITunes::PlayPause() +{ + if (m_Initialized) + { + m_iTunes->PlayPause(); + } +} + +/* +** Stop +** +** Handles the Stop bang. +** +*/ +void CPlayerITunes::Stop() +{ + if (m_Initialized) + { + m_iTunes->Stop(); + } +} + +/* +** Next +** +** Handles the Next bang. +** +*/ +void CPlayerITunes::Next() +{ + if (m_Initialized) + { + m_iTunes->NextTrack(); + } +} + +/* +** Previous +** +** Handles the Previous bang. +** +*/ +void CPlayerITunes::Previous() +{ + if (m_Initialized) + { + m_iTunes->PreviousTrack(); + } +} + +/* +** SetRating +** +** Handles the SetRating bang. +** +*/ +void CPlayerITunes::SetRating(int rating) +{ + if (m_Initialized) + { + rating *= 20; + IITTrack* track; + HRESULT hr = m_iTunes->get_CurrentTrack(&track); + + if (SUCCEEDED(hr)) + { + track->put_Rating((long)rating); + track->Release(); + } + } +} + +/* +** SetVolume +** +** Handles the SetVolume bang. +** +*/ +void CPlayerITunes::SetVolume(int volume) +{ + if (m_Initialized) + { + m_iTunes->put_SoundVolume((long)volume); + } +} + +/* +** ChangeVolume +** +** Handles the ChangeVolume bang. +** +*/ +void CPlayerITunes::ChangeVolume(int volume) +{ + if (m_Initialized) + { + int newVolume = m_Volume; + newVolume += volume; + m_iTunes->put_SoundVolume(newVolume); + } +} + +/* +** ClosePlayer +** +** Handles the ClosePlayer bang. +** +*/ +void CPlayerITunes::ClosePlayer() +{ + if (m_Initialized) + { + m_Initialized = false; + m_iTunes->Quit(); + ClearInfo(); + } +} + +/* +** OpenPlayer +** +** Handles the OpenPlayer bang. +** +*/ +void CPlayerITunes::OpenPlayer() +{ + ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"iTunes.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW); +} + +/* +** TogglePlayer +** +** Handles the TogglePlayer bang. +** +*/ +void CPlayerITunes::TogglePlayer() +{ + m_Initialized ? ClosePlayer() : OpenPlayer(); +} diff --git a/Plugins/PluginNowPlaying/PlayerITunes.h b/Plugins/PluginNowPlaying/PlayerITunes.h new file mode 100644 index 00000000..e5f2b677 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerITunes.h @@ -0,0 +1,99 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYERITUNES_H__ +#define __PLAYERITUNES_H__ + +#include "Player.h" +#include "iTunes/iTunesCOMInterface.h" + +#ifndef _ATL_DLL + #define _ATL_DLL + #define _ATL_APARTMENT_THREADED +#endif + +#include +#include +#include +#include + +class CPlayerITunes : public CPlayer +{ +public: + CPlayerITunes(); + ~CPlayerITunes(); + + virtual void Play() { return PlayPause(); } + virtual void PlayPause(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void ChangeVolume(int volume); + virtual void ClosePlayer(); + virtual void OpenPlayer(); + virtual void TogglePlayer(); + + virtual void AddInstance(MEASURETYPE type); + virtual void RemoveInstance(); + virtual void UpdateData(); + +private: + class CEventHandler : public _IiTunesEvents + { + public: + CEventHandler(CPlayerITunes* player); + ~CEventHandler(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IDispatch + HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT*) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT, LCID, ITypeInfo**) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetIDsOfNames(const IID&, LPOLESTR*, UINT, LCID, DISPID*) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE Invoke(DISPID dispidMember, REFIID, LCID, WORD, DISPPARAMS* pDispParams, VARIANT*, EXCEPINFO*, UINT*); + + private: + ULONG m_RefCount; + ITypeInfo* m_TypeInfo; // Pointer to type information + CPlayerITunes* m_iTunes; + }; + + void Initialize(); + void Uninitialize(); + void OnTrackChange(); + void OnStateChange(bool playing); + void OnVolumeChange(int volume); + bool CheckActive(); + + bool m_Initialized; + bool m_UserQuitPrompt; + bool m_HasCoverMeasure; + HWND m_Window; + + IiTunes* m_iTunes; + CEventHandler* m_iTunesEvent; + IConnectionPoint* m_ConnectionPoint; + DWORD m_ConnectionCookie; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.cpp b/Plugins/PluginNowPlaying/PlayerSpotify.cpp new file mode 100644 index 00000000..60928b89 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerSpotify.cpp @@ -0,0 +1,263 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "PlayerSpotify.h" + +/* +** CPlayerSpotify +** +** Constructor. +** +*/ +CPlayerSpotify::CPlayerSpotify() : + m_Window() +{ + GetWindow(); +} + +/* +** ~CPlayerSpotify +** +** Destructor. +** +*/ +CPlayerSpotify::~CPlayerSpotify() +{ +} + +/* +** AddInstance +** +** Called during initialization of each measure. +** +*/ +void CPlayerSpotify::AddInstance(MEASURETYPE type) +{ + ++m_InstanceCount; +} + +/* +** RemoveInstance +** +** Called during destruction of each measure. +** +*/ +void CPlayerSpotify::RemoveInstance() +{ + if (--m_InstanceCount == 0) + { + delete this; + } +} + +/* +** UpdateData +** +** Called during each update of the main measure. +** +*/ +void CPlayerSpotify::UpdateData() +{ + if (GetWindow()) + { + if (m_TrackChanged) + { + ExecuteTrackChangeAction(); + m_TrackChanged = false; + } + + // Get window text + WCHAR buffer[256]; + buffer[0] = 0; + GetWindowText(m_Window, buffer, 256); + std::wstring title = buffer; + + title.erase(0, 10); // Get rid of "Spotify - " + std::wstring::size_type pos = title.find(L" – "); + if (pos != std::wstring::npos) + { + std::wstring artist = title.substr(0, pos); + std::wstring track = title.substr(pos + 3); + + if (track != m_Title && artist != m_Artist) + { + m_Title = track; + m_Artist = artist; + m_TrackChanged = true; + } + return; + } + } + + ClearInfo(); +} + +bool CPlayerSpotify::GetWindow() +{ + m_Window = FindWindow(L"SpotifyMainWindow", NULL); + + return m_Window ? true : false; +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerSpotify::PlayPause() +{ + if (m_Window) + { + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PLAYPAUSE); + } +} + +/* +** Stop +** +** Handles the Stop bang. +** +*/ +void CPlayerSpotify::Stop() +{ + if (m_Window) + { + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_STOP); + } +} + +/* +** Next +** +** Handles the Next bang. +** +*/ +void CPlayerSpotify::Next() +{ + if (m_Window) + { + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_NEXT); + } +} + +/* +** Previous +** +** Handles the Previous bang. +** +*/ +void CPlayerSpotify::Previous() +{ + if (m_Window) + { + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PREV); + } +} + + +/* +** ClosePlayer +** +** Handles the ClosePlayer bang. +** +*/ +void CPlayerSpotify::ClosePlayer() +{ + if (m_Window) + { + // A little harsh... + DWORD pID; + GetWindowThreadProcessId(m_Window, &pID); + HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pID); + if (hProcess) + { + TerminateProcess(hProcess, 0); + CloseHandle(hProcess); + } + } +} + +/* +** OpenPlayer +** +** Handles the OpenPlayer bang. +** +*/ +void CPlayerSpotify::OpenPlayer() +{ + if (!m_Window) + { + if (m_PlayerPath.empty()) + { + // Gotta figure out where Winamp is located at + HKEY hKey; + RegOpenKeyEx(HKEY_CLASSES_ROOT, + L"spotify\\DefaultIcon", + 0, + KEY_QUERY_VALUE, + &hKey); + + DWORD size = 512; + WCHAR* data = new WCHAR[size]; + DWORD type = 0; + + if (RegQueryValueEx(hKey, + NULL, + NULL, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + std::wstring path = data; + path.erase(0, 1); // Get rid of the leading quote + path.resize(path.length() - 3); // And the ",0 at the end + ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW); + m_PlayerPath = path; + } + } + + delete [] data; + RegCloseKey(hKey); + } + else + { + ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW); + } + } + else + { + // Already active, restore the window + ShowWindow(m_Window, SW_SHOWNORMAL); + BringWindowToTop(m_Window); + } +} + +/* +** TogglePlayer +** +** Handles the TogglePlayer bang. +** +*/ +void CPlayerSpotify::TogglePlayer() +{ + m_Window ? ClosePlayer() : OpenPlayer(); +} diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.h b/Plugins/PluginNowPlaying/PlayerSpotify.h new file mode 100644 index 00000000..ea1baac7 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerSpotify.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYERSPOTIFY_H__ +#define __PLAYERSPOTIFY_H__ + +#include "Player.h" + +#define SPOTIFY_PLAYPAUSE 917504 +#define SPOTIFY_NEXT 720896 +#define SPOTIFY_PREV 786432 +#define SPOTIFY_STOP 851968 +#define SPOTIFY_MUTE 524288 +#define SPOTIFY_VOLUMEDOWN 589824 +#define SPOTIFY_VOLUMEUP 655360 + +class CPlayerSpotify : public CPlayer +{ +public: + CPlayerSpotify(); + ~CPlayerSpotify(); + + virtual void Play() { return PlayPause(); } + virtual void PlayPause(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void ClosePlayer(); + virtual void OpenPlayer(); + virtual void TogglePlayer(); + + virtual void AddInstance(MEASURETYPE type); + virtual void RemoveInstance(); + virtual void UpdateData(); + +private: + bool GetWindow(); + + HWND m_Window; // Spotify window +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerWMP.cpp b/Plugins/PluginNowPlaying/PlayerWMP.cpp new file mode 100644 index 00000000..fdb987c5 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerWMP.cpp @@ -0,0 +1,723 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "PlayerWMP.h" + +/* +** CRemoteHost +** +** Constructor. +** +*/ +CPlayerWMP::CRemoteHost::CRemoteHost() : + m_WMP() +{ +} + +/* +** ~CRemoteHost +** +** Destructor. +** +*/ +CPlayerWMP::CRemoteHost::~CRemoteHost() +{ +} + +HRESULT CPlayerWMP::CRemoteHost::QueryService(REFGUID guidService, REFIID riid, void** ppv) +{ + return ppv ? QueryInterface(riid, ppv) : E_POINTER; +} + +HRESULT CPlayerWMP::CRemoteHost::GetServiceType(BSTR* pbstrType) +{ + HRESULT hr = E_POINTER; + if (pbstrType) + { + *pbstrType = SysAllocString(L"Remote"); + hr = *pbstrType? S_OK : E_POINTER; + } + return hr; +} + +HRESULT CPlayerWMP::CRemoteHost::GetApplicationName(BSTR* pbstrName) +{ + HRESULT hr = E_POINTER; + if (pbstrName) + { + CComBSTR bstrAppName = L"Rainmeter NowPlaying"; + *pbstrName = bstrAppName.Detach(); + hr = *pbstrName? S_OK : E_POINTER; + } + return hr; +} + +HRESULT CPlayerWMP::CRemoteHost::GetScriptableObject(BSTR* pbstrName, IDispatch** ppDispatch) +{ + if (pbstrName) + { + *pbstrName = NULL; + } + if (ppDispatch) + { + *ppDispatch = NULL; + } + return E_NOTIMPL; +} + +HRESULT CPlayerWMP::CRemoteHost::GetCustomUIMode(BSTR* pbstrFile) +{ + return E_POINTER; +} + +/* +** CurrentItemChange +** +** Called when playing track changes. +** +*/ +void CPlayerWMP::CRemoteHost::CurrentItemChange(IDispatch* pdispMedia) +{ + m_WMP->m_TrackChanged = true; +} + +/* +** PlayStateChange +** +** Called when play state changes. +** +*/ +void CPlayerWMP::CRemoteHost::PlayStateChange(long NewState) +{ + switch (NewState) + { + case wmppsStopped: + case wmppsMediaEnded: + m_WMP->ClearInfo(); + break; + + case wmppsPaused: + m_WMP->m_State = PLAYER_PAUSED; + break; + + case wmppsPlaying: + if (m_WMP->m_State == PLAYER_STOPPED) + { + m_WMP->m_TrackChanged = true; + } + m_WMP->m_State = PLAYER_PLAYING; + break; + + default: + break; + } +} + +/* +** SwitchedToControl +** +** Called when WMP quits. +** +*/ +void CPlayerWMP::CRemoteHost::SwitchedToControl() +{ + m_WMP->ClearInfo(); + m_WMP->Uninitialize(); +} + +/* +** CPlayerWMP +** +** Constructor. +** +*/ +CPlayerWMP::CPlayerWMP() : + m_Initialized(false), + m_HasCoverMeasure(false), + m_ComModule(), + m_AxWindow(), + m_IPlayer(), + m_IControls(), + m_ISettings(), + m_IConnectionPoint() +{ + m_ComModule.Init(NULL, NULL, &LIBID_ATLLib); +} + +/* +** ~CPlayerWMP +** +** Destructor. +** +*/ +CPlayerWMP::~CPlayerWMP() +{ + Uninitialize(); + m_ComModule.Term(); +} + +/* +** AddInstance +** +** Called during initialization of each measure. +** +*/ +void CPlayerWMP::AddInstance(MEASURETYPE type) +{ + ++m_InstanceCount; + + if (type == MEASURE_COVER) + { + m_HasCoverMeasure = true; + } +} + +/* +** RemoveInstance +** +** Called during destruction of each measure. +** +*/ +void CPlayerWMP::RemoveInstance() +{ + if (--m_InstanceCount == 0) + { + delete this; + } +} + +/* +** Initialize +** +** Set up the COM interface with WMP. +** +*/ +void CPlayerWMP::Initialize() +{ + HINSTANCE hInstance = GetModuleHandle(NULL); + + // Create windows class + WNDCLASS wc = {0}; + wc.hInstance = hInstance; + wc.lpfnWndProc = DefWindowProc; + wc.lpszClassName = L"NowPlayingWMPClass"; + RegisterClass(&wc); + + // Create dummy window + m_Window = CreateWindow(L"NowPlayingWMPClass", + L"DummyWindow", + WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + NULL); + + if (!m_Window) + { + LSLog(LOG_DEBUG, L"Rainmeter", L"NowPlayingPlugin: Unable to create window (WMP)."); + return; + } + + CComPtr spHostObject; + CComPtr spHost; + CComObject* pRemoteHost; + + m_AxWindow = new CAxWindow(); + HRESULT hr = m_AxWindow ? S_OK : E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + m_AxWindow->Create(m_Window, NULL, NULL, WS_CHILD | WS_DISABLED); + if(IsWindow(m_AxWindow->m_hWnd)) + { + hr = m_AxWindow->QueryHost(IID_IObjectWithSite, (void **)&spHostObject); + if(!spHostObject.p) + { + hr = E_POINTER; + } + } + } + else + { + LSLog(LOG_DEBUG, L"Rainmeter", L"NowPlayingPlugin: Failed to initialize COM (WMP)."); + return; + } + + // Create remote host which implements IServiceProvider and IWMPRemoteMediaServices + if (SUCCEEDED(hr)) + { + hr = CComObject::CreateInstance(&pRemoteHost); + if (pRemoteHost) + { + pRemoteHost->AddRef(); + pRemoteHost->m_WMP = this; + } + else + { + hr = E_POINTER; + } + } + + // Set site to the remote host + if (SUCCEEDED(hr)) + { + hr = spHostObject->SetSite((IWMPRemoteMediaServices*)pRemoteHost); + } + + if (SUCCEEDED(hr)) + { + hr = m_AxWindow->QueryHost(&spHost); + if (!spHost) + { + hr = E_NOINTERFACE; + } + } + + // Create WMP control + if (SUCCEEDED(hr)) + { + hr = spHost->CreateControl(CComBSTR(L"{6BF52A52-394A-11D3-B153-00C04F79FAA6}"), m_AxWindow->m_hWnd, NULL); + } + + if (SUCCEEDED(hr)) + { + hr = m_AxWindow->QueryControl(&m_IPlayer); + if (!m_IPlayer.p) + { + hr = E_NOINTERFACE; + } + } + + // Connect the event interface + CComPtr spConnectionContainer; + hr = m_IPlayer->QueryInterface(&spConnectionContainer); + + if (SUCCEEDED(hr)) + { + hr = spConnectionContainer->FindConnectionPoint( __uuidof(IWMPEvents), &m_IConnectionPoint); + } + + if (SUCCEEDED(hr)) + { + DWORD adviseCookie; + hr = m_IConnectionPoint->Advise(pRemoteHost->GetUnknown(), &adviseCookie); + + if ((FAILED(hr)) || !adviseCookie) + { + m_IConnectionPoint = NULL; + } + } + + // Release remote host object + if (pRemoteHost) + { + pRemoteHost->Release(); + } + + + hr = m_IPlayer->get_controls(&m_IControls); + if (FAILED(hr)) return; + + hr = m_IPlayer->get_settings(&m_ISettings); + if (FAILED(hr)) return; + + // Get player state + WMPPlayState state; + m_IPlayer->get_playState(&state); + if (state == wmppsPlaying) + { + m_State = PLAYER_PLAYING; + } + else if (state == wmppsPaused) + { + m_State = PLAYER_PAUSED; + } + + m_TrackChanged = true; + m_Initialized = true; +} + +/* +** Uninitialize +** +** Close the interface with WMP. +** +*/ +void CPlayerWMP::Uninitialize() +{ + if (m_Initialized) + { + m_Initialized = false; + m_IControls.Release(); + m_ISettings.Release(); + m_IPlayer.Release(); + m_AxWindow->DestroyWindow(); + delete m_AxWindow; + DestroyWindow(m_Window); + UnregisterClass(L"NowPlayingWMPClass", GetModuleHandle(NULL)); + } +} + +/* +** UpdateData +** +** Called during each update of the main measure. +** +*/ +void CPlayerWMP::UpdateData() +{ + static bool clear = false; + + if (m_Initialized) + { + // Get the volume + long volume; + m_ISettings->get_volume(&volume); + m_Volume = (UINT)volume; + + if (m_State != PLAYER_STOPPED) + { + double position; + m_IControls->get_currentPosition(&position); + m_Position = (UINT)position; + } + + if (m_TrackChanged) + { + m_TrackChanged = false; + CComPtr spMedia; + m_IPlayer->get_currentMedia(&spMedia); + + if (spMedia) + { + CComBSTR val; + spMedia->getItemInfo(CComBSTR("Artist"), &val); + m_Artist = val; + + spMedia->getItemInfo(CComBSTR("Title"), &val); + m_Title = val; + + spMedia->getItemInfo(CComBSTR("Album"), &val); + m_Album = val; + + spMedia->getItemInfo(CComBSTR("UserRating"), &val); + int rating = _wtoi(val); + + if (rating > 75) + { + m_Rating = 5; + } + else if (rating > 50) + { + m_Rating = 4; + } + else if (rating > 25) + { + m_Rating = 3; + } + else if (rating > 1) + { + m_Rating = 2; + } + else + { + m_Rating = rating; + } + + double duration; + spMedia->get_duration(&duration); + m_Duration = (UINT)duration; + + // TODO: Better solution for this + if (m_HasCoverMeasure || m_InstanceCount == 0) + { + CComBSTR url; + spMedia->get_sourceURL(&url); + spMedia->getItemInfo(CComBSTR("WM/WMCollectionID"), &val); + std::wstring targetPath = url; + + targetPath.resize(targetPath.find_last_of(L'\\') + 1); + targetPath += L"AlbumArt_"; + targetPath += val; + targetPath += L"_Large.jpg"; + + if (_waccess(targetPath.c_str(), 0) == 0) + { + m_CoverPath = targetPath; + } + else + { + std::wstring cover = CreateCoverArtPath(); + if (_waccess(cover.c_str(), 0) == 0) + { + // Cover is in cache, lets use the that + m_CoverPath = cover; + return; + } + + TagLib::FileRef fr(url.m_str); + if (!fr.isNull() && fr.tag() && GetEmbeddedArt(fr, cover)) + { + // Embedded art found + return; + } + + // Get rid of the name and extension from filename + std::wstring trackFolder = url; + std::wstring::size_type pos = trackFolder.find_last_of(L'\\'); + if (pos == std::wstring::npos) return; + trackFolder.resize(++pos); + + if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder")) + { + // Local art found + return; + } + + // Nothing found + m_CoverPath.clear(); + } + } + + ExecuteTrackChangeAction(); + } + } + } + else + { + static DWORD oldTime = 0; + DWORD time = GetTickCount(); + + // Try to find WMP window every 5 seconds + if (oldTime = 0 || time - oldTime > 5000) + { + oldTime = time; + + if (FindWindow(L"WMPlayerApp", NULL)) + { + Initialize(); + } + } + } +} + +/* +** Play +** +** Handles the Play bang. +** +*/ +void CPlayerWMP::Play() +{ + if (m_IPlayer) + { + m_IControls->play(); + } +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerWMP::PlayPause() +{ + if (m_IPlayer) + { + WMPPlayState state; + m_IPlayer->get_playState(&state); + + if (state == wmppsPlaying) + { + m_IControls->pause(); + } + else + { + m_IControls->play(); + } + } +} + +/* +** Stop +** +** Handles the Stop bang. +** +*/ +void CPlayerWMP::Stop() +{ + if (m_IPlayer) + { + m_IControls->stop(); + m_State = PLAYER_STOPPED; + } +} + +/* +** Next +** +** Handles the Next bang. +** +*/ +void CPlayerWMP::Next() +{ + if (m_IPlayer) + { + m_IControls->next(); + } +} + +/* +** Previous +** +** Handles the Previous bang. +** +*/ +void CPlayerWMP::Previous() +{ + if (m_IPlayer) + { + m_IControls->previous(); + } +} + +/* +** SetRating +** +** Handles the SetRating bang. +** +*/ +void CPlayerWMP::SetRating(int rating) +{ + if (m_IPlayer && (m_State == PLAYER_PLAYING || m_State == PLAYER_PAUSED)) + { + CComPtr spMedia; + m_IPlayer->get_currentMedia(&spMedia); + + if (spMedia) + { + CComBSTR val; + if (rating <= 0) + { + rating = 0; + val = L"0"; + } + else if (rating == 1) + { + val = L"1"; + } + else if (rating == 2) + { + val = L"25"; + } + else if (rating == 3) + { + val = L"50"; + } + else if (rating == 4) + { + val = L"75"; + } + else if (rating >= 5) + { + rating = 5; + val = L"99"; + } + + spMedia->setItemInfo(CComBSTR("UserRating"), val); + m_Rating = rating; + } + } +} + +/* +** SetVolume +** +** Handles the SetVolume bang. +** +*/ +void CPlayerWMP::SetVolume(int volume) +{ + if (m_IPlayer) + { + m_ISettings->put_volume(volume); + } +} + +/* +** ClosePlayer +** +** Handles the ClosePlayer bang. +** +*/ +void CPlayerWMP::ChangeVolume(int volume) +{ + if (m_IPlayer) + { + int newVolume = m_Volume; + newVolume += volume; + m_ISettings->put_volume(newVolume); + } +} + +/* +** ClosePlayer +** +** Handles the ClosePlayer bang. +** +*/ +void CPlayerWMP::ClosePlayer() +{ + if (m_IPlayer) + { + HWND wmp = FindWindow(L"WMPlayerApp", NULL); + + if (wmp) + { + SendMessage(wmp, WM_CLOSE, 0, 0); + } + } +} + +/* +** OpenPlayer +** +** Handles the OpenPlayer bang. +** +*/ +void CPlayerWMP::OpenPlayer() +{ + ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"wmplayer.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW); +} + +/* +** TogglePlayer +** +** Handles the TogglePlayer bang. +** +*/ +void CPlayerWMP::TogglePlayer() +{ + m_IPlayer ? ClosePlayer() : OpenPlayer(); +} diff --git a/Plugins/PluginNowPlaying/PlayerWMP.h b/Plugins/PluginNowPlaying/PlayerWMP.h new file mode 100644 index 00000000..4fc45d94 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerWMP.h @@ -0,0 +1,146 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYERWMP_H__ +#define __PLAYERWMP_H__ + +#ifndef _ATL_DLL + #define _ATL_DLL + #define _ATL_APARTMENT_THREADED +#endif + +#include "Player.h" +#include +#include +#include +#include +#include + +class CPlayerWMP : public CPlayer +{ +public: + CPlayerWMP(); + ~CPlayerWMP(); + + virtual void Play(); + virtual void PlayPause(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void ChangeVolume(int volume); + virtual void OpenPlayer(); + virtual void ClosePlayer(); + virtual void TogglePlayer(); + + virtual void AddInstance(MEASURETYPE type); + virtual void RemoveInstance(); + virtual void UpdateData(); + +private: + class CRemoteHost : + public CComObjectRootEx, + public IServiceProvider, + public IWMPRemoteMediaServices, + public IWMPEvents + { + public: + CRemoteHost(); + ~CRemoteHost(); + + CPlayerWMP* m_WMP; + + BEGIN_COM_MAP(CRemoteHost) + COM_INTERFACE_ENTRY(IServiceProvider) + COM_INTERFACE_ENTRY(IWMPRemoteMediaServices) + COM_INTERFACE_ENTRY(IWMPEvents) + END_COM_MAP() + + // IServiceProvider + STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppv); + + // IWMPRemoteMediaServices + STDMETHOD(GetServiceType)(BSTR* pbstrType); + STDMETHOD(GetApplicationName)(BSTR* pbstrName); + STDMETHOD(GetScriptableObject)(BSTR* pbstrName, IDispatch** ppDispatch); + STDMETHOD(GetCustomUIMode)(BSTR* pbstrFile); + + // IWMPEvents + void STDMETHODCALLTYPE OpenStateChange(long NewState) {} + void STDMETHODCALLTYPE PlayStateChange(long NewState); + void STDMETHODCALLTYPE AudioLanguageChange(long LangID) {} + void STDMETHODCALLTYPE StatusChange() {} + void STDMETHODCALLTYPE ScriptCommand(BSTR scType, BSTR Param) {} + void STDMETHODCALLTYPE NewStream() {} + void STDMETHODCALLTYPE Disconnect(long Result) {} + void STDMETHODCALLTYPE Buffering(VARIANT_BOOL Start) {} + void STDMETHODCALLTYPE Error() {} + void STDMETHODCALLTYPE Warning(long WarningType, long Param, BSTR Description) {} + void STDMETHODCALLTYPE EndOfStream(long Result) {} + void STDMETHODCALLTYPE PositionChange(double oldPosition, double newPosition) {} + void STDMETHODCALLTYPE MarkerHit(long MarkerNum) {} + void STDMETHODCALLTYPE DurationUnitChange(long NewDurationUnit) {} + void STDMETHODCALLTYPE CdromMediaChange(long CdromNum) {} + void STDMETHODCALLTYPE PlaylistChange(IDispatch* Playlist, WMPPlaylistChangeEventType change) {} + void STDMETHODCALLTYPE CurrentPlaylistChange(WMPPlaylistChangeEventType change) {} + void STDMETHODCALLTYPE CurrentPlaylistItemAvailable(BSTR bstrItemName) {} + void STDMETHODCALLTYPE MediaChange(IDispatch* pdispMedia) {} + void STDMETHODCALLTYPE CurrentMediaItemAvailable(BSTR bstrItemName) {} + void STDMETHODCALLTYPE CurrentItemChange(IDispatch* pdispMedia); + void STDMETHODCALLTYPE MediaCollectionChange() {} + void STDMETHODCALLTYPE MediaCollectionAttributeStringAdded(BSTR bstrAttribName, BSTR bstrAttribVal) {} + void STDMETHODCALLTYPE MediaCollectionAttributeStringRemoved(BSTR bstrAttribName, BSTR bstrAttribVal) {} + void STDMETHODCALLTYPE MediaCollectionAttributeStringChanged(BSTR bstrAttribName, BSTR bstrOldAttribVal, BSTR bstrNewAttribVal) {} + void STDMETHODCALLTYPE PlaylistCollectionChange() {} + void STDMETHODCALLTYPE PlaylistCollectionPlaylistAdded(BSTR bstrPlaylistName) {} + void STDMETHODCALLTYPE PlaylistCollectionPlaylistRemoved(BSTR bstrPlaylistName) {} + void STDMETHODCALLTYPE PlaylistCollectionPlaylistSetAsDeleted(BSTR bstrPlaylistName, VARIANT_BOOL varfIsDeleted) {} + void STDMETHODCALLTYPE ModeChange(BSTR ModeName, VARIANT_BOOL NewValue) {} + void STDMETHODCALLTYPE MediaError(IDispatch* pMediaObject) {} + void STDMETHODCALLTYPE OpenPlaylistSwitch(IDispatch* pItem) {} + void STDMETHODCALLTYPE DomainChange(BSTR strDomain) {} + void STDMETHODCALLTYPE SwitchedToPlayerApplication() {} + void STDMETHODCALLTYPE SwitchedToControl(); + void STDMETHODCALLTYPE PlayerDockedStateChange() {} + void STDMETHODCALLTYPE PlayerReconnect() {} + void STDMETHODCALLTYPE Click(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE DoubleClick(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE KeyDown(short nKeyCode, short nShiftState) {} + void STDMETHODCALLTYPE KeyPress(short nKeyAscii) {} + void STDMETHODCALLTYPE KeyUp(short nKeyCode, short nShiftState) {} + void STDMETHODCALLTYPE MouseDown(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE MouseMove(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE MouseUp(short nButton, short nShiftState, long fX, long fY) {} + }; + + void Initialize(); + void Uninitialize(); + + bool m_Initialized; + bool m_HasCoverMeasure; + HWND m_Window; + CComModule m_ComModule; + CAxWindow* m_AxWindow; + CComPtr m_IPlayer; + CComPtr m_IControls; + CComPtr m_ISettings; + CComPtr m_IConnectionPoint; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.cpp b/Plugins/PluginNowPlaying/PlayerWinamp.cpp new file mode 100644 index 00000000..79afa0d9 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerWinamp.cpp @@ -0,0 +1,481 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "PlayerWinamp.h" + +/* +** CPlayerWinamp +** +** Constructor. +** +*/ +CPlayerWinamp::CPlayerWinamp() : + m_HasCoverMeasure(false), + m_Window() +{ + Initialize(); +} + +/* +** ~CPlayerWinamp +** +** Destructor. +** +*/ +CPlayerWinamp::~CPlayerWinamp() +{ + if (m_WinampHandle) CloseHandle(m_WinampHandle); +} + +/* +** AddInstance +** +** Called during initialization of each measure. +** +*/ +void CPlayerWinamp::AddInstance(MEASURETYPE type) +{ + ++m_InstanceCount; + + if (type == MEASURE_COVER) + { + m_HasCoverMeasure = true; + } +} + +/* +** RemoveInstance +** +** Called during destruction of each measure. +** +*/ +void CPlayerWinamp::RemoveInstance() +{ + if (--m_InstanceCount == 0) + { + delete this; + } +} + +/* +** Initialize +** +** Get things ready with Winamp. +** +*/ +bool CPlayerWinamp::Initialize() +{ + m_Window = FindWindow(L"Winamp v1.x", NULL); + + if (m_Window) + { + DWORD pID; + GetWindowThreadProcessId(m_Window, &pID); + m_WinampHandle = OpenProcess(PROCESS_VM_READ, false, pID); + m_WinampAddress = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_FILENAME); + + if (m_WinampHandle) + { + return true; + } + } + + return false; +} + +/* +** CheckActive +** +** Check if Winamp is active. +** +*/ +bool CPlayerWinamp::CheckActive() +{ + if (m_Window) + { + if (!IsWindow(m_Window)) + { + m_Window = NULL; + CloseHandle(m_WinampHandle); + ClearInfo(); + + return false; + } + + return true; + } + else + { + static DWORD oldTime = 0; + DWORD time = GetTickCount(); + + // Try to find Winamp window every 5 seconds + if (time - oldTime > 5000) + { + oldTime = time; + return Initialize(); + } + + return false; + } +} + +/* +** UpdateData +** +** Called during each update of the main measure. +** +*/ +void CPlayerWinamp::UpdateData() +{ + if (!CheckActive()) return; // Make sure Winamp is running + + if (m_TrackChanged) + { + ExecuteTrackChangeAction(); + m_TrackChanged = false; + } + + int playing = SendMessage(m_Window, WM_WA_IPC, 0, IPC_ISPLAYING); + if (playing == 0) + { + if (!m_Path.empty()) + { + ClearInfo(); + m_State = PLAYER_STOPPED; + m_Path.clear(); + } + return; // Don't continue if stopped + } + else + { + m_State = (playing == 1) ? PLAYER_PLAYING : PLAYER_PAUSED; + m_Position = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000; // Returns ms, make seconds + + float volume = SendMessage(m_Window, WM_WA_IPC, -666, IPC_SETVOLUME); + volume /= 2.55f; + m_Volume = (UINT)volume; + } + + WCHAR buffer[MAX_PATH]; + if (!ReadProcessMemory(m_WinampHandle, m_WinampAddress, &buffer, MAX_PATH, NULL)) + { + LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to read Winamp memory"); + } + else if (wcscmp(buffer, m_Path.c_str()) != 0) + { + m_TrackChanged = true; + m_Path = buffer; + m_Rating = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING); + m_Duration = SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); + + TagLib::FileRef fr(buffer); + if (!fr.isNull() && fr.tag()) + { + TagLib::Tag* tag = fr.tag(); + m_Artist = tag->artist().toWString(); + m_Album = tag->album().toWString(); + m_Title = tag->title().toWString(); + } + else + { + ClearInfo(); + + /*LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETPLAYLISTTITLEW); + if (ReadProcessMemory(m_WinampHandle, m_WinampAddress, &buffer, MAX_PATH, NULL)) + { + std::wstring title = buffer; + std::wstring::size_type pos = title.find(L" - "); + if (pos != std::wstring::npos) + { + std::wstring artist = title.substr(0, pos); + std::wstring track = title.substr(pos + 3); + + if (track != m_Title && artist != m_Artist) + { + m_Title = track; + m_Artist = artist; + m_Album.clear(); + } + } + }*/ + + return; + } + + if (m_HasCoverMeasure) + { + std::wstring cover = CreateCoverArtPath(); + if (_waccess(cover.c_str(), 0) == 0) + { + // Cover is in cache, lets use the that + m_CoverPath = cover; + return; + } + + if (GetEmbeddedArt(fr, cover)) + { + // Embedded art found + return; + } + + // Get rid of the name and extension from filename + std::wstring trackFolder = m_Path; + std::wstring::size_type pos = trackFolder.find_last_of(L'\\'); + if (pos == std::wstring::npos) return; + trackFolder.resize(++pos); + + if (!m_Album.empty()) + { + std::wstring file = m_Album; + std::wstring::size_type end = file.length(); + for (pos = 0; pos < end; ++pos) + { + // Replace reserved chars according to Winamp specs + switch (file[pos]) + { + case L'?': + case L'*': + case L'|': + file[pos] = L'_'; + break; + + case L'/': + case L'\\': + case L':': + file[pos] = L'-'; + break; + + case L'\"': + file[pos] = L'\''; + break; + + case L'<': + file[pos] = L'('; + break; + + case L'>': + file[pos] = L')'; + break; + } + } + + if (GetLocalArt(trackFolder, file)) + { + // %album% art file found + return; + } + } + + if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder")) + { + // Local art found + return; + } + + // Nothing found + m_CoverPath.clear(); + } + } +} + +/* +** Play +** +** Handles the Play bang. +** +*/ +void CPlayerWinamp::Play() +{ + if (m_Window) + { + SendMessage(m_Window, WM_COMMAND, WINAMP_PLAY, 0); + } +} + +/* +** PlayPause +** +** Handles the PlayPause bang. +** +*/ +void CPlayerWinamp::PlayPause() +{ + if (m_Window) + { + SendMessage(m_Window, WM_COMMAND, (m_State == PLAYER_STOPPED) ? WINAMP_PLAY : WINAMP_PAUSE, 0); + } +} + +/* +** Stop +** +** Handles the Stop bang. +** +*/ +void CPlayerWinamp::Stop() +{ + if (m_Window) + { + SendMessage(m_Window, WM_COMMAND, WINAMP_STOP, 0); + } +} + +/* +** Next +** +** Handles the Next bang. +** +*/ +void CPlayerWinamp::Next() +{ + if (m_Window) + { + SendMessage(m_Window, WM_COMMAND, WINAMP_FASTFWD, 0); + } +} + +/* +** Previous +** +** Handles the Previous bang. +** +*/ +void CPlayerWinamp::Previous() +{ + if (m_Window) + { + SendMessage(m_Window, WM_COMMAND, WINAMP_REWIND, 0); + } +} + +/* +** SetRating +** +** Handles the SetRating bang. +** +*/ +void CPlayerWinamp::SetRating(int rating) +{ + if (m_Window && (m_State != PLAYER_STOPPED)) + { + if (rating < 0) + { + rating = 0; + } + else if (rating > 5) + { + rating = 5; + } + + SendMessage(m_Window, WM_WA_IPC, rating, IPC_SETRATING); + m_Rating = rating; + } +} + +/* +** SetVolume +** +** Handles the SetVolume bang. +** +*/ +void CPlayerWinamp::SetVolume(int volume) +{ + if (m_Window) + { + ++volume; // For proper scaling + if (volume > 100) + { + volume = 100; + } + + // Winamp accepts volume in 0 - 255 range + float fVolume = (float)volume; + fVolume *= 2.55f; + volume = (UINT)fVolume; + + SendMessage(m_Window, WM_WA_IPC, volume, IPC_SETVOLUME); + } +} + +/* +** ChangeVolume +** +** Handles the ChangeVolume bang. +** +*/ +void CPlayerWinamp::ChangeVolume(int volume) +{ + if (m_Window) + { + ++volume; // For proper scaling + volume += m_Volume; + + if (volume < 0) + { + volume = 0; + } + else if (volume > 100) + { + volume = 100; + } + + float fVolume = (float)volume; + fVolume *= 2.55f; + volume = (UINT)fVolume; + + SendMessage(m_Window, WM_WA_IPC, volume, IPC_SETVOLUME); + } +} + +/* +** ClosePlayer +** +** Handles the ClosePlayer bang. +** +*/ +void CPlayerWinamp::ClosePlayer() +{ + if (m_Window) + { + SendMessage(m_Window, WM_CLOSE, 0, 0); + } +} + +/* +** OpenPlayer +** +** Handles the OpenPlayer bang. +** +*/ +void CPlayerWinamp::OpenPlayer() +{ + ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"winamp.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW); +} + +/* +** TogglePlayer +** +** Handles the TogglePlayer bang. +** +*/ +void CPlayerWinamp::TogglePlayer() +{ + m_Window ? ClosePlayer() : OpenPlayer(); +} diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.h b/Plugins/PluginNowPlaying/PlayerWinamp.h new file mode 100644 index 00000000..49b67828 --- /dev/null +++ b/Plugins/PluginNowPlaying/PlayerWinamp.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __PLAYERWINAMP_H__ +#define __PLAYERWINAMP_H__ + +#include "Player.h" +#include "Winamp/wa_cmd.h" +#include "Winamp/wa_dlg.h" +#include "Winamp/wa_hotkeys.h" +#include "Winamp/wa_ipc.h" + +class CPlayerWinamp : public CPlayer +{ +public: + CPlayerWinamp(); + ~CPlayerWinamp(); + + virtual void Play(); + virtual void PlayPause(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void ChangeVolume(int volume); + virtual void ClosePlayer(); + virtual void OpenPlayer(); + virtual void TogglePlayer(); + + virtual void AddInstance(MEASURETYPE type); + virtual void RemoveInstance(); + virtual void UpdateData(); + +private: + bool Initialize(); + bool CheckActive(); + + std::wstring m_Path; + bool m_HasCoverMeasure; + HWND m_Window; // Winamp window + HANDLE m_WinampHandle; // Handle to Winamp process + LPCVOID m_WinampAddress; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.rc b/Plugins/PluginNowPlaying/PluginNowPlaying.rc new file mode 100644 index 00000000..8fe88c4c --- /dev/null +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.rc @@ -0,0 +1,48 @@ +// Microsoft Developer Studio generated resource script. +// + +#include "../../Version.h" +#define APSTUDIO_READONLY_SYMBOLS +#include "windows.h" +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileDescription", "NowPlaying Plugin for Rainmeter" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "NowPlaying" + VALUE "LegalCopyright", "Copyright (C) 2011 - Birunthan Mohanathas" + VALUE "OriginalFilename", "NowPlaying.dll" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj new file mode 100644 index 00000000..350b619c --- /dev/null +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj @@ -0,0 +1,367 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969} + PluginNowPlaying + + + + + DynamicLibrary + false + Unicode + true + + + DynamicLibrary + false + Unicode + + + DynamicLibrary + false + Unicode + $(COMPILER64) + true + + + DynamicLibrary + false + Unicode + $(COMPILER64) + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)TestBench\x32\$(Configuration)\Plugins\ + .\x32\$(Configuration)\ + false + $(SolutionDir)TestBench\x64\$(Configuration)\Plugins\ + .\x64\$(Configuration)\ + false + $(SolutionDir)TestBench\x32\$(Configuration)\Plugins\ + .\x32\$(Configuration)\ + false + $(SolutionDir)TestBench\x64\$(Configuration)\Plugins\ + .\x64\$(Configuration)\ + false + NowPlaying + NowPlaying + NowPlaying + NowPlaying + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\x32/Debug/NowPlaying.tlb + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;PluginNowPlaying_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + .\x32/Debug/PluginNowPlaying.pch + .\x32/Debug/ + .\x32/Debug/ + .\x32/Debug/ + Level3 + true + EditAndContinue + 4018;4090;4114;4351;4786;4800;4996 + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + ../../TestBench/x32/Debug/Plugins/NowPlaying.dll + true + %(AdditionalLibraryDirectories) + true + .\x32/Debug/NowPlaying.pdb + .\x32/Debug/NowPlaying.lib + MachineX86 + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\x64/Debug/NowPlaying.tlb + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;NowPlaying_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + .\x64/Debug/NowPlaying.pch + .\x64/Debug/ + .\x64/Debug/ + .\x64/Debug/ + Level3 + true + ProgramDatabase + 4018;4090;4114;4351;4786;4800;4996 + + + _DEBUG;_WIN64;%(PreprocessorDefinitions) + 0x0409 + + + ../../TestBench/x64/Debug/Plugins/NowPlaying.dll + true + true + .\x64/Debug/NowPlaying.pdb + .\x64/Debug/NowPlaying.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\x32/Release/NowPlaying.tlb + + + + + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;_WINDOWS;_USRDLL;TAGLIB_WITH_MP4;WITH_MP4;TAGLIB_WITH_ASF;WITH_ASF;PluginNowPlaying_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + + + .\x32/Release/PluginNowPlaying.pch + .\x32/Release/ + .\x32/Release/ + .\x32/Release/ + Level3 + true + ProgramDatabase + 4018;4090;4099;4114;4244;4267;4309;4351;4390;4786;4800;4996 + .\sha2;.\taglib;.\taglib\toolkit;.\taglib\mpeg\id3v2\frames;.\taglib\ogg;.\taglib\asf;.\taglib\mp4;.\taglib\ogg\vorbis;.\taglib\ogg\flac;.\taglib\ogg\speex;.\taglib\riff;.\taglib\riff\wav;.\taglib\riff\aiff;.\taglib\flac;.\taglib\mpeg;.\taglib\mpeg\id3v1;.\taglib\mpeg\id3v2;.\taglib\mpc;.\taglib\ape;.\taglib\trueaudio;.\taglib\wavpack;.\SDKs\;%(AdditionalIncludeDirectories) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Rainmeter.lib;Wininet.lib;%(AdditionalDependencies) + ../../TestBench/x32/Release/Plugins/NowPlaying.dll + true + ..\..\Library\x32\Release;%(AdditionalLibraryDirectories) + true + .\x32/Release/NowPlaying.pdb + .\x32/Release/NowPlaying.lib + MachineX86 + .rdata=.text + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\x64/Release/NowPlaying.tlb + + + + + /GL %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;_WINDOWS;_USRDLL;HAVE_CONFIG_H;PluginNowPlaying_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + .\x64/Release/NowPlaying.pch + .\x64/Release/ + .\x64/Release/ + .\x64/Release/ + Level3 + true + ProgramDatabase + 4018;4090;4099;4114;4244;4267;4309;4351;4390;4786;4800;4996 + .\sha2;.\taglib;.\taglib\toolkit;.\taglib\mpeg\id3v2\frames;.\taglib\ogg;.\taglib\asf;.\taglib\mp4;.\taglib\ogg\vorbis;.\taglib\ogg\flac;.\taglib\ogg\speex;.\taglib\riff;.\taglib\riff\wav;.\taglib\riff\aiff;.\taglib\flac;.\taglib\mpeg;.\taglib\mpeg\id3v1;.\taglib\mpeg\id3v2;.\taglib\mpc;.\taglib\ape;.\taglib\trueaudio;.\taglib\wavpack;.\SDKs\;%(AdditionalIncludeDirectories) + + + NDEBUG;_WIN64;%(PreprocessorDefinitions) + 0x0409 + + + /LTCG %(AdditionalOptions) + Rainmeter.lib;%(AdditionalDependencies) + ../../TestBench/x64/Release/Plugins/NowPlaying.dll + true + ..\..\Library\x64\Release;%(AdditionalLibraryDirectories) + false + .\x64/Release/NowPlaying.pdb + .\x64/Release/NowPlaying.lib + MachineX64 + .rdata=.text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {be9d2400-7f1c-49d6-8498-5ce495491ad6} + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters new file mode 100644 index 00000000..8378e806 --- /dev/null +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters @@ -0,0 +1,313 @@ + + + + + {1f50024f-4311-4946-b0a5-91dc7fb60453} + + + {068012df-e981-4223-a90f-e0cc39dc46bb} + + + {1dbf5fab-83a1-45ab-8ab6-e5ae7b7b0516} + + + {3ba19b2c-1c00-4093-a1b8-184aeaae6cc8} + + + {18242178-1d8d-435b-8676-c5a0eb8c1f1b} + + + {f632b821-b18a-445e-b7a2-2844b6633beb} + + + {8be2f033-c29f-41d2-affd-c7721f0df88b} + + + + + SDKs\iTunes + + + Players + + + Players + + + Players + + + Players + + + Players + + + Players + + + Players + + + + + sha2 + + + sha2 + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + taglib + + + + + SDKs\AIMP + + + SDKs\iTunes + + + SDKs\Winamp + + + SDKs\Winamp + + + SDKs\Winamp + + + SDKs\Winamp + + + Players + + + Players + + + Players + + + Players + + + Players + + + Players + + + Players + + + + + sha2 + + + sha2 + + + + + + \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h b/Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h new file mode 100644 index 00000000..b7afebea --- /dev/null +++ b/Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h @@ -0,0 +1,726 @@ +// Translated by Vitaliy Diatlov +// AIMP2: SDK (02.07.2009), v2.60 + +#ifndef AIMP2_SDK_H +#define AIMP2_SDK_H + +#include +#include + +const char AIMP2_RemoteClass[] = "AIMP2_RemoteInfo"; +const int AIMP2_RemoteFileSize = 2048; + +const int WM_AIMP_COMMAND = WM_USER + 0x75; // WParam = One of Command, LPARAM - Parameter + +const int WM_AIMP_STATUS_GET = 1; +const int WM_AIMP_STATUS_SET = 2;//HiWord of LParam - Command, LoWord of LParam - Parameter +const int WM_AIMP_CALLFUNC = 3;// LPARAM - Func ID (see below Func ID for Addons) +const int WM_AIMP_GET_VERSION = 4; +const int WM_AIMP_STATUS_CHANGE = 5; + +const int WM_LANG = WM_USER + 101; + + // CallBack types +const int AIMP_STATUS_CHANGE = 1; +const int AIMP_PLAY_FILE = 2; +const int AIMP_INFO_UPDATE = 5; // Update Info for current track +const int AIMP_PLAYER_STATE = 11; // Play/Pause/Stop +const int AIMP_EFFECT_CHANGED = 12; // Balance, Speed, Tempo, Pitch, Flanger and etc. +const int AIMP_EQ_CHANGED = 13; // Sliders changed +const int AIMP_TRACK_POS_CHANGED = 14; + + // AIMP_Status_Set / AIMP_Status_Get +const int AIMP_STS_VOLUME = 1; +const int AIMP_STS_BALANCE = 2; +const int AIMP_STS_SPEED = 3; +const int AIMP_STS_Player = 4; +const int AIMP_STS_MUTE = 5; +const int AIMP_STS_REVERB = 6; +const int AIMP_STS_ECHO = 7; +const int AIMP_STS_CHORUS = 8; +const int AIMP_STS_Flanger = 9; + +const int AIMP_STS_EQ_STS = 10; +const int AIMP_STS_EQ_SLDR01 = 11; +const int AIMP_STS_EQ_SLDR02 = 12; +const int AIMP_STS_EQ_SLDR03 = 13; +const int AIMP_STS_EQ_SLDR04 = 14; +const int AIMP_STS_EQ_SLDR05 = 15; +const int AIMP_STS_EQ_SLDR06 = 16; +const int AIMP_STS_EQ_SLDR07 = 17; +const int AIMP_STS_EQ_SLDR08 = 18; +const int AIMP_STS_EQ_SLDR09 = 19; +const int AIMP_STS_EQ_SLDR10 = 20; +const int AIMP_STS_EQ_SLDR11 = 21; +const int AIMP_STS_EQ_SLDR12 = 22; +const int AIMP_STS_EQ_SLDR13 = 23; +const int AIMP_STS_EQ_SLDR14 = 24; +const int AIMP_STS_EQ_SLDR15 = 25; +const int AIMP_STS_EQ_SLDR16 = 26; +const int AIMP_STS_EQ_SLDR17 = 27; +const int AIMP_STS_EQ_SLDR18 = 28; + +const int AIMP_STS_REPEAT = 29; +const int AIMP_STS_ON_STOP = 30; +const int AIMP_STS_POS = 31; +const int AIMP_STS_LENGTH = 32; +const int AIMP_STS_REPEATPLS = 33; +const int AIMP_STS_REP_PLS_1 = 34; +const int AIMP_STS_KBPS = 35; +const int AIMP_STS_KHZ = 36; +const int AIMP_STS_MODE = 37; +const int AIMP_STS_RADIO = 38; +const int AIMP_STS_STREAM_TYPE = 39; // Music / CDA / Radio +const int AIMP_STS_TIMER = 40; // Reverse / Normal +const int AIMP_STS_SHUFFLE = 41; + +const int AIMP_STS_MAIN_HWND = 42; +const int AIMP_STS_TC_HWND = 43; +const int AIMP_STS_APP_HWND = 44; +const int AIMP_STS_PL_HWND = 45; +const int AIMP_STS_EQ_HWND = 46; + +const int AIMP_STS_TRAY = 47; + + // Support Exts Flags +const int AIMP_PLS_EXTS = 1; +const int AIMP_AUDIO_EXTS = 2; + + // Menu IDs +const int AIMP_MAIN_MENU_OPN = 0; +const int AIMP_MAIN_MENU_UTILS = 1; +const int AIMP_MAIN_MENU_FNC = 2; +const int AIMP_MAIN_MENU_CFG = 3; +const int AIMP_UTILS_MENU = 4; +const int AIMP_PLS_MENU_ADD = 5; +const int AIMP_PLS_MENU_JUMP = 6; +const int AIMP_PLS_MENU_FNC = 7; +const int AIMP_PLS_MENU_SEND = 8; +const int AIMP_PLS_MENU_DEL = 9; +const int AIMP_ADD_MENU = 10; +const int AIMP_DEL_MENU = 11; +const int AIMP_FND_MENU = 12; +const int AIMP_SRT_MENU = 13; +const int AIMP_MSC_MENU = 14; +const int AIMP_PLS_MENU = 15; +const int AIMP_TRAY_UTILS = 16; +const int AIMP_TRAY = 17; +const int AIMP_EQ_LIB = 18; +// use AIMP_UTILS_MENU overthis: +// + AIMP_MAIN_MENU_UTILS = 1; +// + AIMP_TRAY_UTILS = 16; + + // AIMP_CallFunction +const int AIMP_OPEN_FILES = 0; +const int AIMP_OPEN_DIR = 1; +const int AIMP_ABOUT = 2; +const int AIMP_SLEEP_TIMER = 3; +const int AIMP_UTILS_AC = 4; +const int AIMP_UTILS_SR = 5; +const int AIMP_UTILS_TE = 6; +const int AIMP_UTILS_CDB = 7; +const int AIMP_OPTIONS = 8; +const int AIMP_PLUGINS = 9; +const int AIMP_QUIT = 10; +const int AIMP_NEXT_VIS = 11; +const int AIMP_PREV_VIS = 12; +const int AIMP_EQ_ANALOG = 13; +const int AIMP_TO_TRAY = 14; +const int AIMP_PLAY = 15; +const int AIMP_PAUSE = 16; +const int AIMP_STOP = 17; +const int AIMP_NEXT = 18; +const int AIMP_PREV = 19; +const int AIMP_ADD_FILES = 20; +const int AIMP_ADD_DIR = 21; +const int AIMP_ADD_PLS = 22; +const int AIMP_ADD_URL = 23; +const int AIMP_DEL_FILES = 24; +const int AIMP_DEL_BAD = 25; +const int AIMP_DEL_FROMHDD = 26; +const int AIMP_DEL_OFF = 27; +const int AIMP_DEL_OFF_HDD = 28; +const int AIMP_RESCAN_PLS = 29; +const int AIMP_SHOW_CURFILE = 30; +const int AIMP_SORT_INVERT = 31; +const int AIMP_SORT_RANDOM = 32; +const int AIMP_SORT_TITLE = 33; +const int AIMP_SORT_ARTIST = 34; +const int AIMP_SORT_FOLDER = 35; +const int AIMP_SORT_LENGTH = 36; +const int AIMP_SORT_RATING = 37; +const int AIMP_SEARCH = 38; +const int AIMP_OPEN_PLS = 39; +const int AIMP_SAVE_PLS = 40; +const int AIMP_PLAY_LAST = 41; +const int AIMP_OFF_SELECTED = 42; +const int AIMP_ON_SELECTED = 43; +const int AIMP_ADD2BOOKMARK = 44; +const int AIMP_EDITBOOKMARK = 45; + + + // For AIMP_GetPath +const int AIMP_CFG_DATA = 0; +const int AIMP_CFG_PLS = 1; +const int AIMP_CFG_LNG = 2; +const int AIMP_CFG_SKINS = 3; +const int AIMP_CFG_PLUGINS = 4; +const int AIMP_CFG_ICONS = 5; +const int AIMP_CFG_ML = 6; + + + // For AIMP_QueryObject +const int IAIMP2PlayerID = 0x0001; +const int IAIMP2PlaylistManagerID = 0x0003; +const int IAIMP2ExtendedID = 0x0004; +const int IAIMP2CoverArtManagerID = 0x0005; +const int IAIMP2PlaylistManager2ID = 0x0006; +const int IAIMPConfigFileID = 0x0010; +const int IAIMPLanguageFileID = 0x0011; + + + + // For AIMP_ObjectClass +const int AIMP_EXT_LC_MESSAGE = 100; +const int AIMP_EXT_ML_MESSAGE = 101; + + + // Option Frame Position Flags +const int AIMP_FRAME_POS_PLAY = 1; +const int AIMP_FRAME_POS_PLAYLIST = 2; +const int AIMP_FRAME_POS_PLAYER = 3; +const int AIMP_FRAME_POS_TEMPLATE = 4; +const int AIMP_FRAME_POS_SYSTEM = 5; +const int AIMP_FRAME_POS_SKINS = 6; +const int AIMP_FRAME_POS_LANGS = 7; + + // AIMP_PLS_SORT_TYPE_XXX +const int AIMP_PLS_SORT_TYPE_TITLE = 1; +const int AIMP_PLS_SORT_TYPE_FILENAME = 2; +const int AIMP_PLS_SORT_TYPE_DURATION = 3; +const int AIMP_PLS_SORT_TYPE_ARTIST = 4; +const int AIMP_PLS_SORT_TYPE_INVERSE = 5; +const int AIMP_PLS_SORT_TYPE_RANDOMIZE = 6; + +#pragma pack(push, 1) +struct AIMP2FileInfo +{ + DWORD cbSizeOf; + // + BOOL nActive; + DWORD nBitRate; + DWORD nChannels; + DWORD nDuration; + INT64 nFileSize; + DWORD nRating; + DWORD nSampleRate; + DWORD nTrackID; + // + DWORD nAlbumLen; + DWORD nArtistLen; + DWORD nDateLen; + DWORD nFileNameLen; + DWORD nGenreLen; + DWORD nTitleLen; + // + PWCHAR sAlbum; + PWCHAR sArtist; + PWCHAR sDate; + PWCHAR sFileName; + PWCHAR sGenre; + PWCHAR sTitle; +}; +#pragma pack(pop) +typedef boolean (WINAPI *AIMPPlaylistDeleteProc)(AIMP2FileInfo AFileInfo, DWORD AUserData); +typedef int (WINAPI *AIMPPlaylistSortProc)(AIMP2FileInfo AFileInfo1, AIMP2FileInfo AFileInfo2, DWORD AUserData); + +typedef void (WINAPI *AIMPMenuProc)(DWORD User, void *Handle); + +typedef void (WINAPI *AIMPStatusChange)(DWORD User, DWORD CallBackType); + +typedef void (WINAPI *CallBackFunc)(DWORD User, DWORD dwCBType); + +#pragma pack(push, 1) +struct PLSInfo +{ + PCHAR PLSName; + DWORD FileCount; + DWORD PLSDuration; + INT64 PLSSize; + int PlaylistID; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct AIMPMenuInfo +{ + boolean Checkbox; + boolean RadioItem; + boolean Checked; + boolean Enabled; + int ProcPtr; // TAIMPMenuProc; + HBITMAP Bitmap; // 0 - no bmp + PWCHAR Caption; + DWORD User; +}; +#pragma pack(pop) + +class IPLSStrings + : public IUnknown +{ +public: + virtual boolean WINAPI AddFile( + PWCHAR FileName, + AIMP2FileInfo *FileInfo + ); + virtual boolean WINAPI DelFile( + int ID + ); + virtual PWCHAR WINAPI GetFileName( + int ID + ); + virtual boolean WINAPI GetFileInfo( + int ID, + AIMP2FileInfo *FileInfo + ); + virtual DWORD WINAPI GetFileObj( + int ID + ); + virtual int WINAPI GetCount(); +}; + +class IAIMP2Controller + :public IUnknown +{ +public: + virtual boolean WINAPI IsUnicodeVersion(); + virtual boolean WINAPI AIMP_CallBack_Set( + DWORD dwCBType, + CallBackFunc CallBackFuncPtr, + DWORD User + ); + virtual boolean WINAPI AIMP_CallBack_Remove( + DWORD dwCBType, + int ProcPtr + ); + // Status + virtual DWORD WINAPI AIMP_Status_Get( + DWORD StatusType + ); + virtual boolean WINAPI AIMP_Status_Set( + DWORD StatusType, + DWORD Value + ); + // Playlist + virtual boolean WINAPI AIMP_PLS_Clear( + int ID + ); + virtual boolean WINAPI AIMP_PLS_Delete( + int ID + ); + virtual boolean WINAPI AIMP_PLS_New( + PWCHAR Name + ); + virtual boolean WINAPI AIMP_PLS_Info( + int Index, + PLSInfo *info + ); + virtual short WINAPI AIMP_PLS_Count(); + virtual boolean WINAPI AIMP_PLS_GetFiles( + int ID, + IPLSStrings **Strings + ); + virtual boolean WINAPI AIMP_PLS_GetSelFiles( + int ID, + IPLSStrings **Strings + ); + virtual boolean WINAPI AIMP_PLS_AddFiles( + int ID, + IPLSStrings *Strings + ); + virtual boolean WINAPI AIMP_PLS_SetPLS( + int ID + ); + // System + virtual boolean WINAPI AIMP_NewStrings( + IPLSStrings **Strings + ); + virtual boolean WINAPI AIMP_GetCurrentTrack( + AIMP2FileInfo *AInfo + ); + virtual boolean WINAPI AIMP_QueryInfo( + PWCHAR Filename, + AIMP2FileInfo *AInfo + ); + virtual DWORD WINAPI AIMP_GetSystemVersion(); + virtual boolean WINAPI AIMP_CallFunction( + DWORD FuncID + ); + virtual int WINAPI AIMP_GetLanguage( + PWCHAR Str, + int ACount + ); + virtual int WINAPI AIMP_GetCfgPath( + PWCHAR Str, + int ACount + ); + virtual int WINAPI AIMP_GetSupportExts( + DWORD Flags, + PWCHAR Str, + int BufSize + ); + // Menu + virtual DWORD WINAPI AIMP_GetSupportExts( + DWORD Parent, + AIMPMenuInfo *MenuInfo + ); + virtual DWORD WINAPI AIMP_Menu_Create( + DWORD MenuID, + AIMPMenuInfo *MenuInfo + ); + virtual boolean WINAPI AIMP_Menu_Update( + int Handle, + AIMPMenuInfo *MenuInfo + ); + virtual boolean WINAPI AIMP_Menu_Remove( + int Handle + ); + // extention + virtual boolean WINAPI AIMP_QueryObject( + DWORD ObjectID, + void *Obj + ); +}; + +class IAIMPAddonHeader + :public IUnknown +{ +public: + virtual BOOL WINAPI GetHasSettingsDialog() = 0; + virtual PWCHAR WINAPI GetPluginAuthor() = 0; + virtual PWCHAR WINAPI GetPluginName() = 0; + virtual void WINAPI Finalize() = 0; + virtual void WINAPI Initialize(IAIMP2Controller *AController) = 0; + virtual void WINAPI ShowSettingsDialog(HWND AParentWindow) = 0; +}; + +typedef IAIMPAddonHeader *(WINAPI *AddonProc)(); + +typedef BOOL (WINAPI *AIMPAddonHeaderProc)(IAIMPAddonHeader *AHeader); +// Export function name: AIMP_QueryAddonEx + +//============================================================================== +// Old Style Addon struct - don't use for new plugins +//============================================================================== + +typedef PCHAR (WINAPI *GetPlgNameFunc)(); +typedef PCHAR (WINAPI *GetAutorFunc)(); +typedef void (WINAPI *InitFunc)(IAIMP2Controller *AIMP); +typedef void (WINAPI *ConfigFunc)(DWORD Handle, DWORD Win); +typedef void (WINAPI *FreeFunc)(); + +#pragma pack(push, 1) +struct AIMPAddonHeader +{ + DWORD version; + DWORD DllInstance; + GetPlgNameFunc PlgNameFuncPtr; + GetAutorFunc AutorFuncPtr; + InitFunc InitFuncPtr; + ConfigFunc ConfigFuncPtr; + FreeFunc FreeFuncPtr; +}; +#pragma pack(pop) + +//============================================================================== + +class IAIMP2OptionFrame + :public IUnknown +{ +public: + virtual HWND WINAPI FrameCreate( + HWND AParent + ); + virtual void *WINAPI FrameData( + ); // reserved + virtual int WINAPI FrameFlags( + ); // See FramePositionFlags + virtual PWCHAR WINAPI FrameName( + ); + virtual HWND WINAPI FrameFree( + HWND AWindow + ); + virtual void WINAPI FrameLoadConfigNotify( + ); + virtual void WINAPI FrameSaveConfigNotify( + ); +}; + +class IAIMP2Player + : public IUnknown +{ +public: + virtual int WINAPI Version(); + virtual boolean WINAPI PlayTrack( + int ID, + int ATrackIndex + ); + virtual void WINAPI PlayOrResume(); + virtual void WINAPI Pause(); + virtual void WINAPI Stop(); + virtual void WINAPI NextTrack(); + virtual void WINAPI PrevTrack(); +}; + +class IAIMP2PlaylistManager + : public IUnknown +{ +public: + virtual int WINAPI AIMP_PLS_CreateFromFile( + PWCHAR AFile, + boolean AActivate, + boolean AStartPlay + ); + virtual int WINAPI AIMP_PLS_ID_ActiveGet(); + virtual boolean WINAPI AIMP_PLS_ID_ActiveSet( + int ID + ); + virtual int WINAPI AIMP_PLS_ID_PlayingGet(); + virtual int WINAPI AIMP_PLS_ID_PlayingGetTrackIndex( + int ID + ); + virtual int WINAPI AIMP_PLS_NewEx( + PWCHAR AName, + boolean AActivate + ); + virtual boolean WINAPI AIMP_PLS_PlayFile( + PWCHAR AFileName, + boolean AFailIfNotExists + ); + // Playlist Processing + virtual boolean WINAPI AIMP_PLS_DeleteByFilter( + int ID, + DWORD AFilterProc, + DWORD AUserData + ); + virtual boolean WINAPI AIMP_PLS_SortByFilter( + int ID, + DWORD AFilterProc, + DWORD AUserData + ); + // Entries + virtual boolean WINAPI AIMP_PLS_Entry_Delete( + int ID, + int AEntryIndex + ); + virtual boolean WINAPI AIMP_PLS_Entry_DeleteAll( + int ID + ); + virtual boolean WINAPI AIMP_PLS_Entry_FileNameGet( + int ID, + int AEntryIndex, + PWCHAR PBuf, + DWORD ABufLen + ); + virtual boolean WINAPI AIMP_PLS_Entry_FileNameSet( + int ID, + int AEntryIndex, + PWCHAR PBuf + ); + virtual int WINAPI AIMP_PLS_Entry_FocusedGet( + int ID + ); + virtual boolean WINAPI AIMP_PLS_Entry_FocusedSet( + int ID, + int AEntryIndex + ); + virtual boolean WINAPI AIMP_PLS_Entry_InfoGet( + int ID, + int AEntryIndex, + AIMP2FileInfo *PFileInfo + ); + virtual boolean WINAPI AIMP_PLS_Entry_InfoSet( + int ID, + int AEntryIndex, + AIMP2FileInfo *PFileInfo + ); + virtual boolean WINAPI AIMP_PLS_Entry_PlayingSwitchGet( + int ID, + int AEntryIndex + ); + virtual boolean WINAPI AIMP_PLS_Entry_PlayingSwitchSet( + int ID, + int AEntryIndex, + boolean ASwitch + ); + virtual boolean WINAPI AIMP_PLS_Entry_ReloadInfo( + int ID, + int AEntryIndex + ); + // Load/Save Playlists + virtual boolean WINAPI AIMP_PM_DestroyStream( + DWORD AHandle + ); + virtual DWORD WINAPI AIMP_PM_ReadItem( + DWORD AHandle, + AIMP2FileInfo *PItem + ); + virtual DWORD WINAPI AIMP_PM_ReadStream( + PWCHAR AFileName, + int *Count + ); + virtual DWORD WINAPI AIMP_PM_SaveStream( + PWCHAR AFileName + ); + virtual DWORD WINAPI AIMP_PM_WriteItem( + DWORD AHandle, + AIMP2FileInfo *PItem + ); + // added in 2.50 B295 + virtual boolean WINAPI AIMP_PLS_ID_PlayingSetTrackIndex( + int ID, + int AEntryIndex + ); +}; + +class IAIMP2PlaylistManager2 + : public IAIMP2PlaylistManager +{ +public: + // Count of loaded playlists + virtual unsigned short WINAPI AIMP_PLS_Count(); + // Return = -1 - ID is not valid, otherthis - count of files in playlist + virtual int WINAPI AIMP_PLS_GetFilesCount(int ID); + virtual HRESULT WINAPI AIMP_PLS_GetInfo(int ID, INT64 *ADuration, INT64 *ASize); + virtual HRESULT WINAPI AIMP_PLS_GetName(int ID, PWCHAR ABuffer, int ABufferSizeInChars); + // Custom Sorting, see AIMP_PLS_SORT_TYPE_XXX + virtual HRESULT WINAPI AIMP_PLS_Sort(int ID, int ASortType); + virtual HRESULT WINAPI AIMP_PLS_SortByTemplate(int ID, PWCHAR ABuffer, int ABufferSizeInChars); + // if Index = -1 returned ID of current playlist. + virtual HRESULT WINAPI AIMP_PLS_ID_By_Index(int Index, int *ID); + // Get Formated title for Entry + virtual HRESULT WINAPI AIMP_PLS_Entry_GetTitle(int ID, int AEntryIndex, + PWCHAR ABuffer, int ABufferSizeInChars); + // Set Entry to playback queue + virtual HRESULT WINAPI AIMP_PLS_Entry_QueueRemove(int ID, int AEntryIndex); + virtual HRESULT WINAPI AIMP_PLS_Entry_QueueSet(int ID, int AEntryIndex, BOOL AInsertAtQueueBegining); + // Moving Entry + virtual HRESULT WINAPI AIMP_PLS_Entry_SetPosition(int ID, int AEntryIndex, int ANewEntryIndex); +}; + +// See IAIMP2ExtendedID +class IAIMP2Extended + :public IUnknown +{ +public: + virtual int WINAPI AIMP_GetPath( + int ID, + PWCHAR buffer, + int bufSize + ); + virtual boolean WINAPI AIMP_ObjectClass( + int ID, + void *AData, + boolean ARegister + ); + // User Option Dialogs + virtual DWORD WINAPI AIMP_Options_FrameAdd( + IAIMP2OptionFrame *AFrame + ); + virtual DWORD WINAPI AIMP_Options_FrameRemove( + IAIMP2OptionFrame *AFrame + ); + virtual DWORD WINAPI AIMP_Options_ModifiedChanged( + IAIMP2OptionFrame *AFrame + ); +}; + +class IAIMP2CoverArtManager + :public IUnknown +{ +public: + // Return picture will be proportional stretched to ADisplaySize value + virtual HBITMAP WINAPI GetCoverArtForFile(PWCHAR AFile, const SIZE *ADisplaySize); + // Draw CoverArt of playing file, Return - cover art drawing successfuly + // CoverArt will be proportional stretched to R value + virtual HRESULT WINAPI CurrentCoverArtDraw(HDC DC, const RECT *R); + // Return <> S_OK, CoverArt is empty or file are not playing + virtual HRESULT WINAPI CurrentCoverArtGetSize(SIZE *ASize); + // W, H - destination display sizes, function will correct sizes for proportional drawing + // Return <> S_OK, CoverArt is empty or file are not playing + virtual HRESULT WINAPI CurrentCoverArtCorrectSizes(int *W, int *H); +}; + + // See IAIMPLanguageFileID +class IAIMPLanguageFile + :public IUnknown +{ +public: + virtual int AIMP_Lang_Version(); + virtual int AIMP_Lang_CurrentFile(PWCHAR ABuffer, int ABufferSizeInChars); + virtual HRESULT AIMP_Lang_IsSectionExists(PWCHAR ASectionName, int ASectionNameSizeInChars); + virtual HRESULT AIMP_Lang_ReadString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); + // When Language changed AIMP will send to window handle "WM_LANG" message + virtual HRESULT AIMP_Lang_Notification(HWND AWndHandle, BOOL ARegister); +}; + +// See IAIMPConfigFileID +class IAIMPConfigFile + :public IUnknown +{ + // functions return null value, if value don't exists in configuration file + virtual HRESULT AIMP_Config_ReadString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); + virtual HRESULT AIMP_Config_ReadInteger(PWCHAR ASectionName, PWCHAR AItemName, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int * AValue); + // + virtual HRESULT AIMP_Config_WriteString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); + virtual HRESULT AIMP_Config_WriteInteger(PWCHAR ASectionName, PWCHAR AItemName, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValue); + // + virtual HRESULT AIMP_Config_IsSectionExists(PWCHAR ASectionName, int ASectionNameSizeInChars); + virtual HRESULT AIMP_Config_RemoveSection(PWCHAR ASectionName, int ASectionNameSizeInChars); +}; + +//============================================================================== +// V I S U A L S +//============================================================================== + +const int VIS_RQD_DATA_WAVE = 1; +const int VIS_RQD_DATA_SPECTRUM = 2; +const int VIS_RQD_NOT_SUSPEND = 4; + +typedef short WaveForm[2][512]; +typedef short Spectrum[2][256]; + +struct AIMPVisualData +{ + int LevelR; + int LevelL; + Spectrum spectrum; + WaveForm waveForm; +}; + +typedef AIMPVisualData *PAIMPVisualData; + +class IAIMP2VisualPlugin + :public IUnknown +{ +public: + virtual PWCHAR WINAPI AuthorName(); + virtual PWCHAR WINAPI PluginName(); + virtual PWCHAR WINAPI PluginInfo(); + virtual DWORD WINAPI PluginFlags(); + virtual BOOL WINAPI Initialize(); + virtual void WINAPI Deinitialize(); + virtual void WINAPI DisplayClick(int X, int Y); + virtual void WINAPI DisplayRender(HDC DC, PAIMPVisualData AData); + virtual void WINAPI DisplayResize(int AWidth, int AHeight); +}; + +// Export function name: AIMP_QueryVisual +typedef IAIMP2VisualPlugin *(WINAPI *AIMPVisualProc)(); + +#endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h new file mode 100644 index 00000000..0791df2a --- /dev/null +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h @@ -0,0 +1,97 @@ +#define WINAMP_STOPPED 0 +#define WINAMP_PLAYING 1 +#define WINAMP_PAUSED 3 + +#define WINAMP_FILE_QUIT 40001 +#define WINAMP_OPTIONS_PREFS 40012 +#define WINAMP_OPTIONS_AOT 40019 +#define WINAMP_FILE_REPEAT 40022 +#define WINAMP_FILE_SHUFFLE 40023 +#define WINAMP_HIGH_PRIORITY 40025 +#define WINAMP_FILE_PLAY 40029 +#define WINAMP_OPTIONS_EQ 40036 +#define WINAMP_OPTIONS_ELAPSED 40037 +#define WINAMP_OPTIONS_REMAINING 40038 +#define WINAMP_OPTIONS_PLEDIT 40040 +#define WINAMP_HELP_ABOUT 40041 +#define WINAMP_MAINMENU 40043 +#define WINAMP_REWIND 40044 +#define WINAMP_PLAY 40045 +#define WINAMP_PAUSE 40046 +#define WINAMP_STOP 40047 +#define WINAMP_FASTFWD 40048 +#define WINAMP_VOLUMEUP 40058 +#define WINAMP_VOLUMEDOWN 40059 +#define WINAMP_FFWD5S 40060 +#define WINAMP_REW5S 40061 +#define WINAMP_NEXT_WINDOW 40063 +#define WINAMP_OPTIONS_WINDOWSHADE 40064 +#define WINAMP_REWIND_SHIFT 40144 +#define WINAMP_PLAY_SHIFT 40145 +#define WINAMP_PAUSE_SHIFT 40146 +#define WINAMP_STOP_SHIFT 40147 +#define WINAMP_FASTFWD_SHIFT 40148 +#define WINAMP_REWIND_CTRL 40154 +#define WINAMP_PLAY_CTRL 40155 +#define WINAMP_PAUSE_CTRL 40156 +#define WINAMP_STOP_CTRL 40157 +#define WINAMP_FASTFWD_CTRL 40158 +#define WINAMP_OPTIONS_DSIZE 40165 +#define IDC_SORT_FILENAME 40166 +#define IDC_SORT_FILETITLE 40167 +#define IDC_SORT_ENTIREFILENAME 40168 +#define IDC_SELECTALL 40169 +#define IDC_SELECTNONE 40170 +#define IDC_SELECTINV 40171 +#define IDM_EQ_LOADPRE 40172 +#define IDM_EQ_LOADMP3 40173 +#define IDM_EQ_LOADDEFAULT 40174 +#define IDM_EQ_SAVEPRE 40175 +#define IDM_EQ_SAVEMP3 40176 +#define IDM_EQ_SAVEDEFAULT 40177 +#define IDM_EQ_DELPRE 40178 +#define IDM_EQ_DELMP3 40180 +#define IDC_PLAYLIST_PLAY 40184 +#define WINAMP_FILE_LOC 40185 +#define WINAMP_OPTIONS_EASYMOVE 40186 +#define WINAMP_FILE_DIR 40187 +#define WINAMP_EDIT_ID3 40188 +#define WINAMP_TOGGLE_AUTOSCROLL 40189 +#define WINAMP_VISSETUP 40190 +#define WINAMP_PLGSETUP 40191 +#define WINAMP_VISPLUGIN 40192 +#define WINAMP_JUMP 40193 +#define WINAMP_JUMPFILE 40194 +#define WINAMP_JUMP10FWD 40195 +#define WINAMP_JUMP10BACK 40197 + +#define WINAMP_OPTIONS_EQ 40036 // toggles the EQ window +#define WINAMP_OPTIONS_PLEDIT 40040 // toggles the playlist window +#define WINAMP_VOLUMEUP 40058 // turns the volume up a little +#define WINAMP_VOLUMEDOWN 40059 // turns the volume down a little +#define WINAMP_FFWD5S 40060 // fast forwards 5 seconds +#define WINAMP_REW5S 40061 // rewinds 5 seconds + +// the following are the five main control buttons, with optionally shift +// or control pressed +// (for the exact functions of each, just try it out) +#define WINAMP_BUTTON1 40044 +#define WINAMP_BUTTON2 40045 +#define WINAMP_BUTTON3 40046 +#define WINAMP_BUTTON4 40047 +#define WINAMP_BUTTON5 40048 +#define WINAMP_BUTTON1_SHIFT 40144 +#define WINAMP_BUTTON2_SHIFT 40145 +#define WINAMP_BUTTON3_SHIFT 40146 +#define WINAMP_BUTTON4_SHIFT 40147 +#define WINAMP_BUTTON5_SHIFT 40148 +#define WINAMP_BUTTON1_CTRL 40154 +#define WINAMP_BUTTON2_CTRL 40155 +#define WINAMP_BUTTON3_CTRL 40156 +#define WINAMP_BUTTON4_CTRL 40157 +#define WINAMP_BUTTON5_CTRL 40158 + +#define WINAMP_FILE_PLAY 40029 // pops up the load file(s) box +#define WINAMP_OPTIONS_PREFS 40012 // pops up the preferences +#define WINAMP_OPTIONS_AOT 40019 // toggles always on top +#define WINAMP_HELP_ABOUT 40041 // pops up the about box :) diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h new file mode 100644 index 00000000..a4922668 --- /dev/null +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h @@ -0,0 +1,353 @@ +/* +** Copyright (C) 2003 Nullsoft, Inc. +** +** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held +** liable for any damages arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to +** alter it and redistribute it freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +** +** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +** +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#ifndef _WA_DLG_H_ +#define _WA_DLG_H_ + +#include "wa_ipc.h" + +/* + + dont know where to put this yet :) + 1) gen.bmp has a generic window frame for plugins to use. + its format is similar to the minibrowser's. + In addition gen.bmp includes a font for the titlebar, in both + highlight and no-highlight modes. The font is variable width, + and it uses the first color before the letter A as the delimiter. + The no-highlight form of letter must be the same width as the + highlight form. + 2) genex.bmp has button and scrollbar images, as well as some individual + pixels that describe the colors for the dialog. The button and + scrollbar images should be self explanatory (note that the buttons + have 4 pixel sized edges that are not stretched, and the center is + stretched), and the scrollbars do something similar. + The colors start at (48,0) and run every other pixel. The meaning + of each pixel is: + x=48: item background (background to edits, listviews etc) + x=50: item foreground (text color of edit/listview, etc) + x=52: window background (used to set the bg color for the dialog) + x=54: button text color + x=56: window text color + x=58: color of dividers and sunken borders + x=60: selection color for listviews/playlists/etc + x=62: listview header background color + x=64: listview header text color + x=66: listview header frame top color + x=68: listview header frame middle color + x=70: listview header frame bottom color + x=72: listview header empty color + x=74: scrollbar foreground color + x=76: scrollbar background color + x=78: inverse scrollbar foreground color + x=80: inverse scrollbar background color + x=82: scrollbar dead area color +*/ + + +#define DCW_SUNKENBORDER 0x00010000 +#define DCW_DIVIDER 0x00020000 + +enum +{ + WADLG_ITEMBG, + WADLG_ITEMFG, + WADLG_WNDBG, + WADLG_BUTTONFG, + WADLG_WNDFG, + WADLG_HILITE, + WADLG_SELCOLOR, + WADLG_LISTHEADER_BGCOLOR, + WADLG_LISTHEADER_FONTCOLOR, + WADLG_LISTHEADER_FRAME_TOPCOLOR, + WADLG_LISTHEADER_FRAME_MIDDLECOLOR, + WADLG_LISTHEADER_FRAME_BOTTOMCOLOR, + WADLG_LISTHEADER_EMPTY_BGCOLOR, + WADLG_SCROLLBAR_FGCOLOR, + WADLG_SCROLLBAR_BGCOLOR, + WADLG_SCROLLBAR_INV_FGCOLOR, + WADLG_SCROLLBAR_INV_BGCOLOR, + WADLG_SCROLLBAR_DEADAREA_COLOR, + WADLG_NUM_COLORS +}; + + + +void WADlg_init(HWND hwndWinamp); // call this on init, or on WM_DISPLAYCHANGE +void WADlg_close(); + +int WADlg_getColor(int idx); + +int WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); // +void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize); // each entry in tab would be the id | DCW_* + +HBITMAP WADlg_getBitmap(); + + +/// define WA_DLG_IMPLEMENT in one of your source files before including this .h +// if you are making a media library plugin, you dont need to do this, look at view_ex for +// an example of how to get the function *'s via an IPC message. + +#ifdef WA_DLG_IMPLEMENT + +static HBRUSH wadlg_lastbrush; +static HBITMAP wadlg_bitmap; // load this manually +static int wadlg_colors[WADLG_NUM_COLORS]; +static int wadlg_defcolors[WADLG_NUM_COLORS]= +{ +RGB(0,0,0), +RGB(0,255,0), +RGB(36,36,60), +RGB(57,56,66), +RGB(255,255,255), +RGB(132,148,165), +RGB(0,0,198), +RGB(36*2,36*2,60*2), +RGB(255,255,255), +RGB(36*3,36*3,60*3), +RGB(36,36,60), +RGB(36*0.5,36*0.5,60*0.5), +RGB(36,36,60), +RGB(36*1,36*1,60*1), +RGB(36*1,36*1,60*1), +RGB(121,130,150), +RGB(78,88,110), +RGB(36*1,36*1,60*1), +}; + +int WADlg_getColor(int idx) +{ + if (idx < 0 || idx >= WADLG_NUM_COLORS) return 0; + return wadlg_colors[idx]; +} + +HBITMAP WADlg_getBitmap() +{ + return wadlg_bitmap; +} + +void WADlg_init(HWND hwndWinamp) // call this on init, or on WM_DISPLAYCHANGE +{ + if (wadlg_bitmap) DeleteObject(wadlg_bitmap); + wadlg_bitmap = (HBITMAP) SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_GENSKINBITMAP); + if (wadlg_bitmap) + { + HDC tmpDC=CreateCompatibleDC(NULL); + HGDIOBJ o=SelectObject(tmpDC,(HGDIOBJ)wadlg_bitmap); + int x; + for (x = 0; x < WADLG_NUM_COLORS; x ++) + { + int a=GetPixel(tmpDC,48+x*2,0); + if (a == CLR_INVALID || a == RGB(0,198,255)) a=wadlg_defcolors[x]; + wadlg_colors[x]=a; + } + + SelectObject(tmpDC,o); + DeleteDC(tmpDC); + } +} + +void WADlg_close() +{ + if (wadlg_bitmap) DeleteObject(wadlg_bitmap); + wadlg_bitmap=0; + if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); + wadlg_lastbrush=0; +} + +void WADlg_dotLine(HDC hdc, int left, int top, int len, int vert) +{ + for(int i=(top&1);iCtlType == ODT_BUTTON) { + char wt[256]; + RECT r; + GetDlgItemText(hwndDlg,wParam,wt,sizeof(wt)); + + HDC hdc = CreateCompatibleDC(di->hDC); + SelectObject(hdc,wadlg_bitmap); + + r=di->rcItem; + SetStretchBltMode(di->hDC,COLORONCOLOR); + + + int yoffs = (di->itemState & ODS_SELECTED) ? 15 : 0; + + BitBlt(di->hDC,r.left,r.top,4,4,hdc,0,yoffs,SRCCOPY); // top left + StretchBlt(di->hDC,r.left+4,r.top,r.right-r.left-4-4,4,hdc,4,yoffs,47-4-4,4,SRCCOPY); // top center + BitBlt(di->hDC,r.right-4,r.top,4,4,hdc,47-4,yoffs,SRCCOPY); // top right + + StretchBlt(di->hDC,r.left,r.top+4,4,r.bottom-r.top-4-4,hdc,0,4+yoffs,4,15-4-4,SRCCOPY); // left edge + StretchBlt(di->hDC,r.right-4,r.top+4,4,r.bottom-r.top-4-4,hdc,47-4,4+yoffs,4,15-4-4,SRCCOPY); // right edge + + // center + StretchBlt(di->hDC,r.left+4,r.top+4,r.right-r.left-4-4,r.bottom-r.top-4-4,hdc,4,4+yoffs,47-4-4,15-4-4,SRCCOPY); + + + BitBlt(di->hDC,r.left,r.bottom-4,4,4,hdc,0,15-4+yoffs,SRCCOPY); // bottom left + StretchBlt(di->hDC,r.left+4,r.bottom-4,r.right-r.left-4-4,4,hdc,4,15-4+yoffs,47-4-4,4,SRCCOPY); // bottom center + BitBlt(di->hDC,r.right-4,r.bottom-4,4,4,hdc,47-4,15-4+yoffs,SRCCOPY); // bottom right + + + // draw text + SetBkMode(di->hDC,TRANSPARENT); + SetTextColor(di->hDC,wadlg_colors[WADLG_BUTTONFG]); + if (di->itemState & ODS_SELECTED) {r.left+=2; r.top+=2;} + DrawText(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER); + DeleteDC(hdc); + + if(GetFocus()==di->hwndItem) { + HPEN pen=CreatePen(PS_SOLID,0,RGB(0,0,0)); + SelectObject(di->hDC,pen); + WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.right-r.left-3,0); + WADlg_dotLine(di->hDC,r.right-3,r.top+2,r.bottom-r.top-3,1); + WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.bottom-r.top-3,1); + WADlg_dotLine(di->hDC,r.left+2,r.bottom-3,r.right-r.left-3,0); + DeleteObject(pen); + } + } + } + switch(uMsg) + { + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORDLG: + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLOREDIT: + { + int bgcolor=(uMsg == WM_CTLCOLOREDIT || uMsg == WM_CTLCOLORLISTBOX) ? wadlg_colors[WADLG_ITEMBG] : (uMsg == WM_CTLCOLORBTN ? wadlg_colors[WADLG_ITEMBG] : wadlg_colors[WADLG_WNDBG]); + LOGBRUSH lb={BS_SOLID,GetNearestColor((HDC)wParam,bgcolor)}; + if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); + wadlg_lastbrush=CreateBrushIndirect(&lb); + SetTextColor((HDC)wParam,uMsg == WM_CTLCOLORSTATIC ? wadlg_colors[WADLG_WNDFG] : wadlg_colors[WADLG_ITEMFG]); + SetBkColor((HDC)wParam,lb.lbColor); + return (int)wadlg_lastbrush; + } + } + return 0; +} + +static int RectInRect(RECT *rect1, RECT *rect2) +{ + // this has a bias towards true + + // this could probably be optimized a lot + return ((rect1->top >= rect2->top && rect1->top <= rect2->bottom) || + (rect1->bottom >= rect2->top && rect1->bottom <= rect2->bottom) || + (rect2->top >= rect1->top && rect2->top <= rect1->bottom) || + (rect2->bottom >= rect1->top && rect2->bottom <= rect1->bottom)) // vertical intersect + && + ((rect1->left >= rect2->left && rect1->left <= rect2->right) || + (rect1->right >= rect2->left && rect1->right <= rect2->right) || + (rect2->left >= rect1->left && rect2->left <= rect1->right) || + (rect2->right >= rect1->left && rect2->right <= rect1->right)) // horiz intersect + ; +} + +static void WADlg_removeFromRgn(HRGN hrgn, int left, int top, int right, int bottom) +{ + HRGN rgn2=CreateRectRgn(left,top,right,bottom); + CombineRgn(hrgn,hrgn,rgn2,RGN_DIFF); + DeleteObject(rgn2); +} + +void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize) +{ + PAINTSTRUCT ps; + BeginPaint(hwndDlg,&ps); + + HRGN hrgn=NULL; + if(ps.fErase) + { + RECT r=ps.rcPaint; + hrgn=CreateRectRgn(r.left,r.top,r.right,r.bottom); + } + + HPEN pen=CreatePen(PS_SOLID,0,wadlg_colors[WADLG_HILITE]); + HGDIOBJ o=SelectObject(ps.hdc,pen); + + while (tabsize--) + { + RECT r; + int a=*tab++; + GetWindowRect(GetDlgItem(hwndDlg,a&0xffff),&r); + ScreenToClient(hwndDlg,(LPPOINT)&r); + ScreenToClient(hwndDlg,((LPPOINT)&r)+1); + + if (RectInRect(&ps.rcPaint,&r)) + { + if ((a & 0xffff0000) == DCW_SUNKENBORDER) + { + MoveToEx(ps.hdc,r.left,r.bottom,NULL); + LineTo(ps.hdc,r.right,r.bottom); + LineTo(ps.hdc,r.right,r.top-1); + if(hrgn) + { + WADlg_removeFromRgn(hrgn,r.left,r.bottom,r.right,r.bottom+1); + WADlg_removeFromRgn(hrgn,r.right,r.top,r.right+1,r.bottom); + } + } + else if ((a & 0xffff0000) == DCW_DIVIDER) + { + if (r.right - r.left < r.bottom - r.top) // vertical + { + int left=(r.left+r.right)/2; + MoveToEx(ps.hdc,left,r.top,NULL); + LineTo(ps.hdc,left,r.bottom+1); + if(hrgn) WADlg_removeFromRgn(hrgn,left,r.top,left+1,r.bottom); + } + else // horiz + { + int top=(r.top+r.bottom)/2; + MoveToEx(ps.hdc,r.left,top,NULL); + LineTo(ps.hdc,r.right+1,top); + if(hrgn) WADlg_removeFromRgn(hrgn,r.left,top,r.right,top+1); + } + } + } + } + + SelectObject(ps.hdc,o); + DeleteObject(pen); + + if(hrgn) { + //erase bkgnd while clipping out our own drawn stuff (for flickerless display) + HBRUSH b=CreateSolidBrush(wadlg_colors[WADLG_WNDBG]); + FillRgn(ps.hdc,hrgn,b); + DeleteObject(b); + DeleteObject(hrgn); + } + EndPaint(hwndDlg,&ps); +} +#endif + +#endif//_WA_DLG_H_ \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h new file mode 100644 index 00000000..c4cbf8da --- /dev/null +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h @@ -0,0 +1,39 @@ +#ifndef WA_HOTKEYS +#define WA_HOTKEYS + +//#define IPC_GEN_HOTKEYS_ADD xxxx //pass a genHotkeysAddStruct * struct in data +// +//To get the IPC_GEN_HOTKEYS_ADD IPC number, do this: +// +// genhotkeys_add_ipc=SendMessage(winampWindow,WM_WA_IPC,(WPARAM)&"GenHotkeysAdd",IPC_REGISTER_WINAMP_IPCMESSAGE); +// +//Then you can use: +// +// PostMessage(winampWindow,WM_WA_IPC,(WPARAM)&myGenHotkeysAddStruct,genhotkeys_add_ipc); +// + +//flags for the genHotkeysAddStruct struct +#define HKF_BRING_TO_FRONT 0x1 // calls SetForegroundWindow before sending the message +#define HKF_HWND_WPARAM 0x2 // sets wParam with Winamp's window handle +#define HKF_COPY 0x4 // copies returned text to the clipboard +#define HKF_PLPOS_WPARAM 0x8 // sets wParam with current pledit position +#define HKF_ISPLAYING_WL 0x10 // sets wParam to genHotkeysAddStruct's wParam if playing, lParam if not + // uses IPC_ISPLAYING to check if playing +#define HKF_SHOWHIDE 0x20 // brings Winamp to front or minimizes Winamp if already at front +#define HKF_NOSENDMSG 0x40 // don't send any message to the winamp window + +#define HKF_DISABLED 0x80000000 + +typedef struct { + char *name; //name that will appear in the Global Hotkeys preferences panel + DWORD flags; //one or more flags from above + UINT uMsg; //message that will be sent to winamp's main window (must always be !=NULL) + WPARAM wParam; //wParam that will be sent to winamp's main window + LPARAM lParam; //lParam that will be sent to winamp's main window + char *id; //unique string to identify this command - case insensitive + HWND wnd; //set the HWND to send message (or 0 for main winamp window) + + int extended[6]; //for future extension - always set to zero! +} genHotkeysAddStruct; + +#endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h new file mode 100644 index 00000000..cb82f23d --- /dev/null +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h @@ -0,0 +1,1601 @@ +/* +** Copyright (C) 2006 Nullsoft, Inc. +** +** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held +** liable for any damages arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to +** alter it and redistribute it freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +** +** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +** +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#ifndef _WA_IPC_H_ +#define _WA_IPC_H_ + +#include +#include +#if (_MSC_VER <= 1200) +typedef int intptr_t; +#endif +/* +** This is the modern replacement for the classic 'frontend.h'. Most of these +** updates are designed for in-process use, i.e. from a plugin. +** +*/ + +/* message used to sent many messages to winamp's main window. +** most all of the IPC_* messages involve sending the message in the form of: +** result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*); +** +** When you use SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*) and specify a IPC_* +** which is not currently implemented/supported by the Winamp version being used then it +** will return 1 for 'result'. This is a good way of helping to check if an api being +** used which returns a function pointer, etc is even going to be valid. +*/ +#define WM_WA_IPC WM_USER +/* but some of them use WM_COPYDATA. be afraid. +*/ + +#define WINAMP_VERSION_MAJOR(winampVersion) ((winampVersion & 0x0000FF00) >> 12) +#define WINAMP_VERSION_MINOR(winampVersion) (winampVersion & 0x000000FF) // returns, i.e. 0x12 for 5.12 and 0x10 for 5.1... + +#define IPC_GETVERSION 0 +/* int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION); +** +** The version returned will be 0x20yx for Winamp 2.yx. +** Versions previous to Winamp 2.0 typically (but not always) use 0x1zyx for 1.zx. +** Just a bit weird but that's the way it goes. +** +** For Winamp 5.x it uses the format 0x50yx for Winamp 5.yx +** e.g. 5.01 -> 0x5001 +** 5.09 -> 0x5009 +** 5.1 -> 0x5010 +** +** Notes: For 5.02 this api will return the same value as for a 5.01 build. +** For 5.07 this api will return the same value as for a 5.06 build. +*/ +#define IPC_GETVERSIONSTRING 1 + +#define IPC_GETREGISTEREDVERSION 770 + + +typedef struct { + const char *filename; + const char *title; + int length; +} enqueueFileWithMetaStruct; // send this to a IPC_PLAYFILE in a non WM_COPYDATA, +// and you get the nice desired result. if title is NULL, it is treated as a "thing", +// otherwise it's assumed to be a file (for speed) + +typedef struct { + const wchar_t *filename; + const wchar_t *title; + int length; +} enqueueFileWithMetaStructW; + +#define IPC_PLAYFILE 100 // dont be fooled, this is really the same as enqueufile +#define IPC_ENQUEUEFILE 100 +#define IPC_PLAYFILEW 1100 +/* This is sent as a WM_COPYDATA with IPC_PLAYFILE as the dwData member and the string +** of the file / playlist to be enqueued into the playlist editor as the lpData member. +** This will just enqueue the file or files since you can use this to enqueue a playlist. +** It will not clear the current playlist or change the playback state. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ENQUEUEFILE; +** cds.lpData = (void*)"c:\\test\\folder\\test.mp3"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** With 2.9+ and all of the 5.x versions you can send this as a normal WM_WA_IPC +** (non WM_COPYDATA) with an enqueueFileWithMetaStruct as the param. +** If the title member is null then it is treated as a "thing" otherwise it will be +** assumed to be a file (for speed). +** +** enqueueFileWithMetaStruct eFWMS = {0}; +** eFWMS.filename = "c:\\test\\folder\\test.mp3"; +** eFWMS.title = "Whipping Good"; +** eFWMS.length = 300; // this is the number of seconds for the track +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&eFWMS,IPC_ENQUEUEFILE); +*/ + + +#define IPC_DELETE 101 +#define IPC_DELETE_INT 1101 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_DELETE); +** Use this api to clear Winamp's internal playlist. +** You should not need to use IPC_DELETE_INT since it is used internally by Winamp when +** it is dealing with some lame Windows Explorer issues (hard to believe that!). +*/ + + +#define IPC_STARTPLAY 102 +#define IPC_STARTPLAY_INT 1102 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_STARTPLAY); +** Sending this will start playback and is almost the same as hitting the play button. +** The IPC_STARTPLAY_INT version is used internally and you should not need to use it +** since it won't be any fun. +*/ + +#define IPC_CHDIR 103 +/* This is sent as a WM_COPYDATA type message with IPC_CHDIR as the dwData value and the +** directory you want to change to as the lpData member. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_CHDIR; +** cds.lpData = (void*)"c:\\download"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** The above example will make Winamp change to the directory 'C:\download'. +*/ + + +#define IPC_ISPLAYING 104 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING); +** This is sent to retrieve the current playback state of Winamp. +** If it returns 1, Winamp is playing. +** If it returns 3, Winamp is paused. +** If it returns 0, Winamp is not playing. +*/ + + +#define IPC_GETOUTPUTTIME 105 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME); +** This api can return two different sets of information about current playback status. +** +** If mode = 0 then it will return the position (in ms) of the currently playing track. +** Will return -1 if Winamp is not playing. +** +** If mode = 1 then it will return the current track length (in seconds). +** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). +*/ + + + +#define IPC_JUMPTOTIME 106 +/* (requires Winamp 1.60+) +** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME); +** This api sets the current position (in milliseconds) for the currently playing song. +** The resulting playback position may only be an approximate time since some playback +** formats do not provide exact seeking e.g. mp3 +** This returns -1 if Winamp is not playing, 1 on end of file, or 0 if it was successful. +*/ + +#define IPC_GETMODULENAME 109 +#define IPC_EX_ISRIGHTEXE 666 +/* usually shouldnt bother using these, but here goes: +** send a WM_COPYDATA with IPC_GETMODULENAME, and an internal +** flag gets set, which if you send a normal WM_WA_IPC message with +** IPC_EX_ISRIGHTEXE, it returns whether or not that filename +** matches. lame, I know. +*/ + +#define IPC_WRITEPLAYLIST 120 +/* (requires Winamp 1.666+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_WRITEPLAYLIST); +** +** IPC_WRITEPLAYLIST will write the current playlist to '\\Winamp.m3u' and +** will also return the current playlist position (see IPC_GETLISTPOS). +** +** This is kinda obsoleted by some of the newer 2.x api items but it still is good for +** use with a front-end program (instead of a plug-in) and you want to see what is in the +** current playlist. +** +** This api will only save out extended file information in the #EXTINF entry if Winamp +** has already read the data such as if the file was played of scrolled into view. If +** Winamp has not read the data then you will only find the file with its filepath entry +** (as is the base requirements for a m3u playlist). +*/ + + +#define IPC_SETPLAYLISTPOS 121 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS) +** IPC_SETPLAYLISTPOS sets the playlist position to the specified 'position'. +** It will not change playback status or anything else. It will just set the current +** position in the playlist and will update the playlist view if necessary. +** +** If you use SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_BUTTON2,0),0); +** after using IPC_SETPLAYLISTPOS then Winamp will start playing the file at 'position'. +*/ + + +#define IPC_SETVOLUME 122 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME); +** IPC_SETVOLUME sets the volume of Winamp (between the range of 0 to 255). +** +** If you pass 'volume' as -666 then the message will return the current volume. +** int curvol = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME); +*/ + + +#define IPC_SETPANNING 123 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,panning,IPC_SETPANNING); +** IPC_SETPANNING sets the panning of Winamp from 0 (left) to 255 (right). +** +** At least in 5.x+ this works from -127 (left) to 127 (right). +** +** If you pass 'panning' as -666 to this api then it will return the current panning. +** int curpan = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETPANNING); +*/ + + +#define IPC_GETLISTLENGTH 124 +/* (requires Winamp 2.0+) +** int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH); +** IPC_GETLISTLENGTH returns the length of the current playlist as the number of tracks. +*/ + + +#define IPC_GETLISTPOS 125 +/* (requires Winamp 2.05+) +** int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); +** IPC_GETLISTPOS returns the current playlist position (which is shown in the playlist +** editor as a differently coloured text entry e.g is yellow for the classic skin). +** +** This api is a lot like IPC_WRITEPLAYLIST but a lot faster since it does not have to +** write out the whole of the current playlist first. +*/ + + +#define IPC_GETINFO 126 +/* (requires Winamp 2.05+) +** int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO); +** IPC_GETINFO returns info about the current playing song. The value +** it returns depends on the value of 'mode'. +** Mode Meaning +** ------------------ +** 0 Samplerate, in kilohertz (i.e. 44) +** 1 Bitrate (i.e. 128) +** 2 Channels (i.e. 2) +** 3 (5+) Video LOWORD=w HIWORD=h +** 4 (5+) > 65536, string (video description) +** 5 (5.25+) Samplerate, in hertz (i.e. 44100) +*/ + + +#define IPC_GETEQDATA 127 +/* (requires Winamp 2.05+) +** int data=SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** IPC_GETEQDATA queries the status of the EQ. +** The value returned depends on what 'pos' is set to: +** Value Meaning +** ------------------ +** 0-9 The 10 bands of EQ data. 0-63 (+20db - -20db) +** 10 The preamp value. 0-63 (+20db - -20db) +** 11 Enabled. zero if disabled, nonzero if enabled. +** 12 Autoload. zero if disabled, nonzero if enabled. +*/ + + +#define IPC_SETEQDATA 128 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA); +** IPC_SETEQDATA sets the value of the last position retrieved +** by IPC_GETEQDATA. This is pretty lame, and we should provide +** an extended version that lets you do a MAKELPARAM(pos,value). +** someday... + + new (2.92+): + if the high byte is set to 0xDB, then the third byte specifies + which band, and the bottom word specifies the value. +*/ + +#define IPC_ADDBOOKMARK 129 +#define IPC_ADDBOOKMARKW 131 +/* (requires Winamp 2.4+) +** This is sent as a WM_COPYDATA using IPC_ADDBOOKMARK as the dwData value and the +** directory you want to change to as the lpData member. This will add the specified +** file / url to the Winamp bookmark list. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ADDBOOKMARK; +** cds.lpData = (void*)"http://www.blah.com/listen.pls"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** In Winamp 5.0+ we use this as a normal WM_WA_IPC and the string is null separated as +** the filename and then the title of the entry. +** +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)"filename\0title\0",IPC_ADDBOOKMARK); +** +** This will notify the library / bookmark editor that a bookmark was added. +** Note that using this message in this context does not actually add the bookmark. +** Do not use, it is essentially just a notification type message :) +*/ + + +#define IPC_INSTALLPLUGIN 130 +/* This is not implemented (and is very unlikely to be done due to safety concerns). +** If it was then you could do a WM_COPYDATA with a path to a .wpz and it would then +** install the plugin for you. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_INSTALLPLUGIN; +** cds.lpData = (void*)"c:\\path\\to\\file.wpz"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +*/ + + +#define IPC_RESTARTWINAMP 135 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_RESTARTWINAMP); +** IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :) ) +** If this fails to make Winamp start after closing then there is a good chance one (or +** more) of the currently installed plugins caused Winamp to crash on exit (either as a +** silent crash or a full crash log report before it could call itself start again. +*/ + + +#define IPC_ISFULLSTOP 400 +/* (requires winamp 2.7+ I think) +** int ret=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISFULLSTOP); +** This is useful for when you're an output plugin and you want to see if the stop/close +** happening is a full stop or if you are just between tracks. This returns non zero if +** it is a full stop or zero if it is just a new track. +*/ + + +#define IPC_INETAVAILABLE 242 +/* (requires Winamp 2.05+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INETAVAILABLE); +** IPC_INETAVAILABLE will return 1 if an Internet connection is available for Winamp and +** relates to the internet connection type setting on the main general preferences page +** in the Winamp preferences. +*/ + + +#define IPC_UPDTITLE 243 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_UPDTITLE); +** IPC_UPDTITLE will ask Winamp to update the information about the current title and +** causes GetFileInfo(..) in the input plugin associated with the current playlist entry +** to be called. This can be called such as when an input plugin is buffering a file so +** that it can cause the buffer percentage to appear in the playlist. +*/ + + +#define IPC_REFRESHPLCACHE 247 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REFRESHPLCACHE); +** IPC_REFRESHPLCACHE will flush the playlist cache buffer and you send this if you want +** Winamp to go refetch the titles for all of the entries in the current playlist. + +5.3+: pass a wchar_t * string in wParam, and it'll do a strnicmp() before clearing the cache +*/ + + +#define IPC_GET_SHUFFLE 250 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE); +** IPC_GET_SHUFFLE returns the status of the shuffle option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_GET_REPEAT 251 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT); +** IPC_GET_REPEAT returns the status of the repeat option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_SET_SHUFFLE 252 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE); +** IPC_SET_SHUFFLE sets the status of the shuffle option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_SET_REPEAT 253 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT); +** IPC_SET_REPEAT sets the status of the repeat option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_ENABLEDISABLE_ALL_WINDOWS 259 // 0xdeadbeef to disable +/* (requires Winamp 2.9+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(enable?0:0xdeadbeef),IPC_ENABLEDISABLE_ALL_WINDOWS); +** Sending this message with 0xdeadbeef as the param will disable all winamp windows and +** any other values will enable all of the Winamp windows again. When disabled you won't +** get any response on clicking or trying to do anything to the Winamp windows. If the +** taskbar icon is shown then you may still have control ;) +*/ + + +#define IPC_GETWND 260 +/* (requires Winamp 2.9+) +** HWND h=SendMessage(hwnd_winamp,WM_WA_IPC,IPC_GETWND_xxx,IPC_GETWND); +** returns the HWND of the window specified. +*/ + #define IPC_GETWND_EQ 0 // use one of these for the param + #define IPC_GETWND_PE 1 + #define IPC_GETWND_MB 2 + #define IPC_GETWND_VIDEO 3 +#define IPC_ISWNDVISIBLE 261 // same param as IPC_GETWND + + + + +/************************************************************************ +***************** in-process only (WE LOVE PLUGINS) +************************************************************************/ + +#define IPC_SETSKINW 199 +#define IPC_SETSKIN 200 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"skinname",IPC_SETSKIN); +** IPC_SETSKIN sets the current skin to "skinname". Note that skinname +** can be the name of a skin, a skin .zip file, with or without path. +** If path isn't specified, the default search path is the winamp skins +** directory. +*/ + + +#define IPC_GETSKIN 201 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)skinname_buffer,IPC_GETSKIN); +** IPC_GETSKIN puts the directory where skin bitmaps can be found +** into skinname_buffer. +** skinname_buffer must be MAX_PATH characters in length. +** When using a .zip'd skin file, it'll return a temporary directory +** where the ZIP was decompressed. +*/ + + +#define IPC_EXECPLUG 202 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"vis_file.dll",IPC_EXECPLUG); +** IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM. +** the format of this string can be: +** "vis_whatever.dll" +** "vis_whatever.dll,0" // (first mod, file in winamp plug-in dir) +** "C:\\dir\\vis_whatever.dll,1" +*/ + + +#define IPC_GETPLAYLISTFILE 211 +#define IPC_GETPLAYLISTFILEW 214 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE); +** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETPLAYLISTTITLE 212 +#define IPC_GETPLAYLISTTITLEW 213 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE); +** +** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETHTTPGETTER 240 +/* retrieves a function pointer to a HTTP retrieval function. +** if this is unsupported, returns 1 or 0. +** the function should be: +** int (*httpRetrieveFile)(HWND hwnd, char *url, char *file, char *dlgtitle); +** if you call this function, with a parent window, a URL, an output file, and a dialog title, +** it will return 0 on successful download, 1 on error. +*/ + + +#define IPC_MBOPEN 241 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_MBOPEN); +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPEN); +** IPC_MBOPEN will open a new URL in the minibrowser. if url is NULL, it will open the Minibrowser window. +*/ + + + +#define IPC_CHANGECURRENTFILE 245 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILE); +** IPC_CHANGECURRENTFILE will set the current playlist item. +*/ + +#define IPC_CHANGECURRENTFILEW 1245 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILEW); +** IPC_CHANGECURRENTFILEW will set the current playlist item. +*/ + + +#define IPC_GETMBURL 246 +/* (requires Winamp 2.2+) +** char buffer[4096]; // Urls can be VERY long +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)buffer,IPC_GETMBURL); +** IPC_GETMBURL will retrieve the current Minibrowser URL into buffer. +** buffer must be at least 4096 bytes long. +*/ + + +#define IPC_MBBLOCK 248 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_MBBLOCK); +** +** IPC_MBBLOCK will block the Minibrowser from updates if value is set to 1 +*/ + +#define IPC_MBOPENREAL 249 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPENREAL); +** +** IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works even if +** IPC_MBBLOCK has been set to 1 +*/ + +#define IPC_ADJUST_OPTIONSMENUPOS 280 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_OPTIONSMENUPOS); +** moves where winamp expects the Options menu in the main menu. Useful if you wish to insert a +** menu item above the options/skins/vis menus. +*/ + +#define IPC_GET_HMENU 281 +/* (requires Winamp 2.9+) +** HMENU hMenu=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0,IPC_GET_HMENU); +** values for data: +** 0 : main popup menu +** 1 : main menubar file menu +** 2 : main menubar options menu +** 3 : main menubar windows menu +** 4 : main menubar help menu +** other values will return NULL. +*/ + +#define IPC_GET_EXTENDED_FILE_INFO 290 //pass a pointer to the following struct in wParam +#define IPC_GET_EXTENDED_FILE_INFO_HOOKABLE 296 +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to query, and ret to a buffer, with retlen to the +** length of that buffer, and then SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_GET_EXTENDED_FILE_INFO); +** the results should be in the buffer pointed to by ret. +** returns 1 if the decoder supports a getExtendedFileInfo method +*/ +typedef struct { + const char *filename; + const char *metadata; + char *ret; + int retlen; +} extendedFileInfoStruct; + + +#define IPC_GET_BASIC_FILE_INFO 291 //pass a pointer to the following struct in wParam +typedef struct { + const char *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + char *title; + int titlelen; +} basicFileInfoStruct; + +#define IPC_GET_BASIC_FILE_INFOW 1291 //pass a pointer to the following struct in wParam +typedef struct { + const wchar_t *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + wchar_t *title; + int titlelen; +} basicFileInfoStructW; + + +#define IPC_GET_EXTLIST 292 //returns doublenull delimited. GlobalFree() it when done. if data is 0, returns raw extlist, if 1, returns something suitable for getopenfilename +#define IPC_GET_EXTLISTW 1292 // wide char version of above + +#define IPC_INFOBOX 293 +typedef struct { + HWND parent; + char *filename; +} infoBoxParam; + +#define IPC_INFOBOXW 1293 +typedef struct { + HWND parent; + const wchar_t *filename; +} infoBoxParamW; + +#define IPC_SET_EXTENDED_FILE_INFO 294 //pass a pointer to the a extendedFileInfoStruct in wParam +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to write in ret. (retlen is not used). and then +** SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_SET_EXTENDED_FILE_INFO); +** returns 1 if the metadata is supported +** Call IPC_WRITE_EXTENDED_FILE_INFO once you're done setting all the metadata you want to update +*/ + +#define IPC_WRITE_EXTENDED_FILE_INFO 295 +/* (requires Winamp 2.9+) +** writes all the metadata set thru IPC_SET_EXTENDED_FILE_INFO to the file +** returns 1 if the file has been successfully updated, 0 if error +*/ + +#define IPC_FORMAT_TITLE 297 +typedef struct +{ + char *spec; // NULL=default winamp spec + void *p; + + char *out; + int out_len; + + char * (*TAGFUNC)(const char * tag, void * p); //return 0 if not found + void (*TAGFREEFUNC)(char * tag,void * p); +} waFormatTitle; + +#define IPC_FORMAT_TITLE_EXTENDED 298 // similiar to IPC_FORMAT_TITLE, but falls back to Winamp's %tags% if your passed tag function doesn't handle it +typedef struct +{ + const wchar_t *filename; + int useExtendedInfo; // set to 1 if you want the Title Formatter to query the input plugins for any tags that your tag function fails on + const wchar_t *spec; // NULL=default winamp spec + void *p; + + wchar_t *out; + int out_len; + + wchar_t * (*TAGFUNC)(const wchar_t * tag, void * p); //return 0 if not found, -1 for empty tag + void (*TAGFREEFUNC)(wchar_t *tag, void *p); +} waFormatTitleExtended; + +#define IPC_GETUNCOMPRESSINTERFACE 331 +/* returns a function pointer to uncompress(). +** int (*uncompress)(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); +** right out of zlib, useful for decompressing zlibbed data. +** if you pass the parm of 0x10100000, it will return a wa_inflate_struct * to an inflate API. +*/ + +typedef struct { + int (*inflateReset)(void *strm); + int (*inflateInit_)(void *strm,const char *version, int stream_size); + int (*inflate)(void *strm, int flush); + int (*inflateEnd)(void *strm); + unsigned long (*crc32)(unsigned long crc, const unsigned char *buf, unsigned int len); +} wa_inflate_struct; + + +#define IPC_ADD_PREFS_DLG 332 +#define IPC_REMOVE_PREFS_DLG 333 +/* (requires Winamp 2.9+) +** to use, allocate a prefsDlgRec structure (either on the heap or some global +** data, but NOT on the stack), initialze the members: +** hInst to the DLL instance where the resource is located +** dlgID to the ID of the dialog, +** proc to the window procedure for the dialog +** name to the name of the prefs page in the prefs. +** where to 0 (eventually we may add more options) +** then, SendMessage(hwnd_winamp,WM_WA_IPC,&prefsRec,IPC_ADD_PREFS_DLG); +** +** you can also IPC_REMOVE_PREFS_DLG with the address of the same prefsRec, +** but you shouldn't really ever have to. +** +*/ +#define IPC_OPENPREFSTOPAGE 380 // pass an id of a builtin page, or a &prefsDlgRec of prefs page to open + +typedef struct _prefsDlgRec { + HINSTANCE hInst; + int dlgID; + void *proc; + + char *name; + intptr_t where; // 0 for options, 1 for plugins, 2 for skins, 3 for bookmarks, 4 for prefs + + intptr_t _id; + struct _prefsDlgRec *next; +} prefsDlgRec; + + +#define IPC_GETINIFILE 334 // returns a pointer to winamp.ini +#define IPC_GETINIDIRECTORY 335 // returns a pointer to the directory to put config files in (if you dont want to use winamp.ini) +#define IPC_GETPLUGINDIRECTORY 336 +#define IPC_GETM3UDIRECTORY 337 // returns a char pointer to the directory where winamp.m3u is stored in. +#define IPC_GETM3UDIRECTORYW 338 // returns a wchar_t pointer to the directory where winamp.m3u is stored in. + +#define IPC_SPAWNBUTTONPOPUP 361 // param = +// 0 = eject +// 1 = previous +// 2 = next +// 3 = pause +// 4 = play +// 5 = stop + +#define IPC_OPENURLBOX 360 // pass a HWND to a parent, returns a HGLOBAL that needs to be freed with GlobalFree(), if successful +#define IPC_OPENFILEBOX 362 // pass a HWND to a parent +#define IPC_OPENDIRBOX 363 // pass a HWND to a parent + +// pass an HWND to a parent. call this if you take over the whole UI so that the dialogs are not appearing on the +// bottom right of the screen since the main winamp window is at 3000x3000, call again with NULL to reset +#define IPC_SETDIALOGBOXPARENT 364 + + + +#define IPC_DRO_MIN 401 // reserved for DrO +#define IPC_SET_JTF_COMPARATOR 409 +/* pass me an int (__cdecl *)(const char *, const char *) in wParam */ +#define IPC_SET_JTF_COMPARATOR_W 410 +/* pass me an int (__cdecl *)(const wchar_t *, const wchar_t *) in wParam ... maybe someday :) */ +#define IPC_SET_JTF_DRAWTEXT 416 + +#define IPC_DRO_MAX 499 + + +// pass 0 for a copy of the skin HBITMAP +// pass 1 for name of font to use for playlist editor likeness +// pass 2 for font charset +// pass 3 for font size +#define IPC_GET_GENSKINBITMAP 503 + + +#define IPC_GET_EMBEDIF 505 // pass an embedWindowState +// returns an HWND embedWindow(embedWindowState *); if the data is NULL, otherwise returns the HWND directly +typedef struct +{ + HWND me; //hwnd of the window + + int flags; + + RECT r; + + void *user_ptr; // for application use + + intptr_t extra_data[64]; // for internal winamp use +} embedWindowState; + +#define EMBED_FLAGS_NORESIZE 0x1 // set this bit in embedWindowState.flags to keep window from being resizable +#define EMBED_FLAGS_NOTRANSPARENCY 0x2 // set this bit in embedWindowState.flags to make gen_ff turn transparency off for this wnd +#define EMBED_FLAGS_NOWINDOWMENU 0x4 // set this bit to prevent gen_ff from automatically adding your window to the right-click menu +#define EMBED_FLAGS_GUID 0x8 // call SET_EMBED_GUID(yourEmbedWindowStateStruct, GUID) to define a GUID for this window + +#define SET_EMBED_GUID(windowState, windowGUID) { windowState->flags |= EMBED_FLAGS_GUID; *((GUID *)&windowState->extra_data[4])=windowGUID; } +#define GET_EMBED_GUID(windowState) (*((GUID *)&windowState->extra_data[4])) + +#define IPC_EMBED_ENUM 532 +typedef struct embedEnumStruct +{ + int (*enumProc)(embedWindowState *ws, struct embedEnumStruct *param); // return 1 to abort + int user_data; // or more :) +} embedEnumStruct; + // pass + +#define IPC_EMBED_ISVALID 533 + +#define IPC_CONVERTFILE 506 +/* (requires Winamp 2.92+) +** Converts a given file to a different format (PCM, MP3, etc...) +** To use, pass a pointer to a waFileConvertStruct struct +** This struct can be either on the heap or some global +** data, but NOT on the stack. At least, until the conversion is done. +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE); +** +** Return value: +** 0: Can't start the conversion. Look at myConvertStruct->error for details. +** 1: Conversion started. Status messages will be sent to the specified callbackhwnd. +** Be sure to call IPC_CONVERTFILE_END when your callback window receives the +** IPC_CB_CONVERT_DONE message. +*/ +typedef struct +{ + char *sourcefile; // "c:\\source.mp3" + char *destfile; // "c:\\dest.pcm" + int destformat[8]; // like 'PCM ',srate,nch,bps. + //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) + HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages + + //filled in by winamp.exe + char *error; //if IPC_CONVERTFILE returns 0, the reason will be here + + int bytes_done; //you can look at both of these values for speed statistics + int bytes_total; + int bytes_out; + + int killswitch; // don't set it manually, use IPC_CONVERTFILE_END + intptr_t extra_data[64]; // for internal winamp use +} convertFileStruct; + +#define IPC_CONVERTFILE_END 507 +/* (requires Winamp 2.92+) +** Stop/ends a convert process started from IPC_CONVERTFILE +** You need to call this when you receive the IPC_CB_CONVERTDONE message or when you +** want to abort a conversion process +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE_END); +** +** No return value +*/ + +typedef struct { + HWND hwndParent; + int format; + + //filled in by winamp.exe + HWND hwndConfig; + int extra_data[8]; + //hack alert! you can set extra_data[6]=mmioFOURCC('I','N','I',' '); and extra_data[7]=(int)my_ini_file; (where my_ini_file is a char*) +} convertConfigStruct; +#define IPC_CONVERT_CONFIG 508 +#define IPC_CONVERT_CONFIG_END 509 + +typedef struct +{ + void (*enumProc)(intptr_t user_data, const char *desc, int fourcc); + intptr_t user_data; +} converterEnumFmtStruct; +#define IPC_CONVERT_CONFIG_ENUMFMTS 510 +/* (requires Winamp 2.92+) +*/ + +typedef struct +{ + char cdletter; + char *playlist_file; + HWND callback_hwnd; + + //filled in by winamp.exe + char *error; +} burnCDStruct; +#define IPC_BURN_CD 511 +/* (requires Winamp 5.0+) +*/ + +typedef struct +{ + convertFileStruct *cfs; + int priority; +} convertSetPriority; +#define IPC_CONVERT_SET_PRIORITY 512 + +typedef struct +{ + unsigned int format; //fourcc value + char *item; // config item, eg "bitrate" + char *data; // buffer to recieve, or buffer that contains the data + int len; // length of the data buffer (only used when getting a config item) + char *configfile; // config file to read from +} convertConfigItem; + +#define IPC_CONVERT_CONFIG_SET_ITEM 513 // returns TRUE if successful +#define IPC_CONVERT_CONFIG_GET_ITEM 514 // returns TRUE if successful + +typedef struct +{ + const char *filename; + char *title; // 2048 bytes + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStruct; +// return TRUE if you hook this +#define IPC_HOOK_TITLES 850 + +typedef struct +{ + const wchar_t *filename; + wchar_t *title; // 2048 bytes + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStructW; +// return TRUE if you hook this +#define IPC_HOOK_TITLESW 851 + +#define IPC_GETSADATAFUNC 800 +// 0: returns a char *export_sa_get() that returns 150 bytes of data +// 1: returns a export_sa_setreq(int want); + +#define IPC_GETVUDATAFUNC 801 +// 0: returns a int export_vu_get(int channel) that returns 0-255 (or -1 for bad channel) + +#define IPC_ISMAINWNDVISIBLE 900 + + +#define IPC_SETPLEDITCOLORS 920 +typedef struct +{ + int numElems; + int *elems; + HBITMAP bm; // set if you want to override +} waSetPlColorsStruct; + + +// the following IPC use waSpawnMenuParms as parameter +#define IPC_SPAWNEQPRESETMENU 933 +#define IPC_SPAWNFILEMENU 934 //menubar +#define IPC_SPAWNOPTIONSMENU 935 //menubar +#define IPC_SPAWNWINDOWSMENU 936 //menubar +#define IPC_SPAWNHELPMENU 937 //menubar +#define IPC_SPAWNPLAYMENU 938 //menubar +#define IPC_SPAWNPEFILEMENU 939 //menubar +#define IPC_SPAWNPEPLAYLISTMENU 940 //menubar +#define IPC_SPAWNPESORTMENU 941 //menubar +#define IPC_SPAWNPEHELPMENU 942 //menubar +#define IPC_SPAWNMLFILEMENU 943 //menubar +#define IPC_SPAWNMLVIEWMENU 944 //menubar +#define IPC_SPAWNMLHELPMENU 945 //menubar +#define IPC_SPAWNPELISTOFPLAYLISTS 946 + +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; +} waSpawnMenuParms; + +// waSpawnMenuParms2 is used by the menubar submenus +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; + int width; + int height; +} waSpawnMenuParms2; + + +// system tray sends this (you might want to simulate it) +#define WM_WA_SYSTRAY WM_USER+1 + +// input plugins send this when they are done playing back +#define WM_WA_MPEG_EOF WM_USER+2 + + + +//// video stuff + +#define IPC_IS_PLAYING_VIDEO 501 // returns >1 if playing, 0 if not, 1 if old version (so who knows):) +#define IPC_GET_IVIDEOOUTPUT 500 // see below for IVideoOutput interface +#define VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24)) +#define VIDUSER_SET_INFOSTRING 0x1000 +#define VIDUSER_GET_VIDEOHWND 0x1001 +#define VIDUSER_SET_VFLIP 0x1002 +#define VIDUSER_SET_TRACKSELINTERFACE 0x1003 // give your ITrackSelector interface as param2 +#define VIDUSER_OPENVIDEORENDERER 0x1004 +#define VIDUSER_CLOSEVIDEORENDERER 0x1005 +#define VIDUSER_GETPOPUPMENU 0x1006 + +typedef struct +{ + int w; + int h; + int vflip; + double aspectratio; + unsigned int fmt; +} VideoOpenStruct; + +#ifndef NO_IVIDEO_DECLARE +#ifdef __cplusplus + +class VideoOutput; +class SubsItem; + +#ifndef _NSV_DEC_IF_H_ +typedef struct { + unsigned char* baseAddr; + long rowBytes; +} YV12_PLANE; + +typedef struct { + YV12_PLANE y; + YV12_PLANE u; + YV12_PLANE v; +} YV12_PLANES; +#endif + +class IVideoOutput +{ + public: + virtual ~IVideoOutput() { } + virtual int open(int w, int h, int vflip, double aspectratio, unsigned int fmt)=0; + virtual void setcallback(LRESULT (*msgcallback)(void *token, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam), void *token) { (void)token; (void)msgcallback; /* to eliminate warning C4100 */ } + virtual void close()=0; + virtual void draw(void *frame)=0; + virtual void drawSubtitle(SubsItem *item) { } + virtual void showStatusMsg(const char *text) { } + virtual int get_latency() { return 0; } + virtual void notifyBufferState(int bufferstate) { } /* 0-255*/ + + virtual INT_PTR extended(INT_PTR param1, INT_PTR param2, INT_PTR param3) { return 0; } // Dispatchable, eat this! +}; + +class ITrackSelector +{ + public: + virtual int getNumAudioTracks()=0; + virtual void enumAudioTrackName(int n, const char *buf, int size)=0; + virtual int getCurAudioTrack()=0; + virtual int getNumVideoTracks()=0; + virtual void enumVideoTrackName(int n, const char *buf, int size)=0; + virtual int getCurVideoTrack()=0; + + virtual void setAudioTrack(int n)=0; + virtual void setVideoTrack(int n)=0; +}; + +#endif //cplusplus +#endif//NO_IVIDEO_DECLARE + +// these messages are callbacks that you can grab by subclassing the winamp window + +// wParam = +#define IPC_CB_WND_EQ 0 // use one of these for the param +#define IPC_CB_WND_PE 1 +#define IPC_CB_WND_MB 2 +#define IPC_CB_WND_VIDEO 3 +#define IPC_CB_WND_MAIN 4 + +#define IPC_CB_ONSHOWWND 600 +#define IPC_CB_ONHIDEWND 601 + +#define IPC_CB_GETTOOLTIP 602 + +#define IPC_CB_MISC 603 + #define IPC_CB_MISC_TITLE 0 + #define IPC_CB_MISC_VOLUME 1 // volume/pan + #define IPC_CB_MISC_STATUS 2 + #define IPC_CB_MISC_EQ 3 + #define IPC_CB_MISC_INFO 4 + #define IPC_CB_MISC_VIDEOINFO 5 + +#define IPC_CB_CONVERT_STATUS 604 // param value goes from 0 to 100 (percent) +#define IPC_CB_CONVERT_DONE 605 + +#define IPC_ADJUST_FFWINDOWSMENUPOS 606 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFWINDOWSMENUPOS); +** moves where winamp expects the freeform windows in the menubar windows main menu. Useful if you wish to insert a +** menu item above extra freeform windows. +*/ + +#define IPC_ISDOUBLESIZE 608 + +#define IPC_ADJUST_FFOPTIONSMENUPOS 609 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFOPTIONSMENUPOS); +** moves where winamp expects the freeform preferences item in the menubar windows main menu. Useful if you wish to insert a +** menu item above preferences item. +*/ + +#define IPC_GETTIMEDISPLAYMODE 610 // returns 0 if displaying elapsed time or 1 if displaying remaining time + +#define IPC_SETVISWND 611 // param is hwnd, setting this allows you to receive ID_VIS_NEXT/PREVOUS/RANDOM/FS wm_commands +#define ID_VIS_NEXT 40382 +#define ID_VIS_PREV 40383 +#define ID_VIS_RANDOM 40384 +#define ID_VIS_FS 40389 +#define ID_VIS_CFG 40390 +#define ID_VIS_MENU 40391 + +#define IPC_GETVISWND 612 // returns the vis cmd handler hwnd +#define IPC_ISVISRUNNING 613 +#define IPC_CB_VISRANDOM 628 // param is status of random + +#define IPC_SETIDEALVIDEOSIZE 614 // sent by winamp to winamp, trap it if you need it. width=HIWORD(param), height=LOWORD(param) + +#define IPC_GETSTOPONVIDEOCLOSE 615 +#define IPC_SETSTOPONVIDEOCLOSE 616 + +typedef struct { + HWND hwnd; + int uMsg; + WPARAM wParam; + LPARAM lParam; +} transAccelStruct; + +#define IPC_TRANSLATEACCELERATOR 617 + +typedef struct { + int cmd; + int x; + int y; + int align; +} windowCommand; // send this as param to an IPC_PLCMD, IPC_MBCMD, IPC_VIDCMD + +#define IPC_CB_ONTOGGLEAOT 618 + +#define IPC_GETPREFSWND 619 + +#define IPC_SET_PE_WIDTHHEIGHT 620 // data is a pointer to a POINT structure that holds width & height + +#define IPC_GETLANGUAGEPACKINSTANCE 621 + +#define IPC_CB_PEINFOTEXT 622 // data is a string, ie: "04:21/45:02" + +#define IPC_CB_OUTPUTCHANGED 623 // output plugin was changed in config + +#define IPC_GETOUTPUTPLUGIN 625 + +#define IPC_SETDRAWBORDERS 626 +#define IPC_DISABLESKINCURSORS 627 +#define IPC_CB_RESETFONT 629 + +#define IPC_IS_FULLSCREEN 630 // returns 1 if video or vis is in fullscreen mode +#define IPC_SET_VIS_FS_FLAG 631 // a vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode + +#define IPC_SHOW_NOTIFICATION 632 + +#define IPC_GETSKININFO 633 + +#define IPC_GET_MANUALPLADVANCE 634 +/* (requires Winamp 5.03+) +** val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_MANUALPLADVANCE); +** +** IPC_GET_MANUALPLADVANCE returns the status of the Manual Playlist Advance (1 if set) +*/ + +#define IPC_SET_MANUALPLADVANCE 635 +/* (requires Winamp 5.03+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_MANUALPLADVANCE); +** +** IPC_SET_MANUALPLADVANCE sets the status of the Manual Playlist Advance option (1 to turn it on) +*/ + +#define IPC_GET_NEXT_PLITEM 636 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_NEXT_PLITEM); +** +** Sent to Winamp's main window when an item has just finished playback or the next button has been pressed and +** requesting the new playlist item number to go to. +** Mainly used by gen_jumpex. Subclass this message in your application to return the new item number. +** -1 for normal winamp operation (default) or the new item number in the playlist to play. +*/ + +#define IPC_GET_PREVIOUS_PLITEM 637 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_PREVIOUS_PLITEM); +** +** Sent to Winamp's main window when the previous button has been pressed and Winamp is requesting the new playlist item number to go to. +** Mainly used by gen_jumpex. Subclass this message in your application to return the new item number. +** -1 for normal winamp operation (default) or the new item number in the playlist to play. +*/ + +#define IPC_IS_WNDSHADE 638 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,wnd,IPC_IS_WNDSHADE); +** +** 'wnd' is window id as defined for IPC_GETWND, or -1 for main window +** Returns 1 if wnd is set to winshade mode, or 0 if it is not +*/ + +#define IPC_SETRATING 639 +/* (requires Winamp 5.04+ with ML) +** SendMessage(hwnd_winamp,WM_WA_IPC,rating,IPC_SETRATING); +** 'rating' is an int value from 0 (no rating) to 5 +*/ + +#define IPC_GETRATING 640 +/* (requires Winamp 5.04+ with ML) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); +** returns the current item's rating +*/ + +#define IPC_GETNUMAUDIOTRACKS 641 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMAUDIOTRACKS); +** returns the number of audio tracks for the currently playing item +*/ + +#define IPC_GETNUMVIDEOTRACKS 642 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMVIDEOTRACKS); +** returns the number of video tracks for the currently playing item +*/ + +#define IPC_GETAUDIOTRACK 643 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETAUDIOTRACK); +** returns the id of the current audio track for the currently playing item +*/ + +#define IPC_GETVIDEOTRACK 644 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVIDEOTRACK); +** returns the id of the current video track for the currently playing item +*/ + +#define IPC_SETAUDIOTRACK 645 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETAUDIOTRACK); +** switch the currently playing item to a new audio track +*/ + +#define IPC_SETVIDEOTRACK 646 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETVIDEOTRACK); +** switch the currently playing item to a new video track +*/ + +#define IPC_PUSH_DISABLE_EXIT 647 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PUSH_DISABLE_EXIT ); +** lets you disable or re-enable the UI exit functions (close button, +** context menu, alt-f4). +** call IPC_POP_DISABLE_EXIT when you are done doing whatever required +** preventing exit +*/ + +#define IPC_POP_DISABLE_EXIT 648 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_POP_DISABLE_EXIT ); +** see IPC_PUSH_DISABLE_EXIT +*/ + +#define IPC_IS_EXIT_ENABLED 649 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_EXIT_ENABLED); +** returns 0 if exit is disabled, 1 otherwise +*/ + +#define IPC_IS_AOT 650 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_AOT); +** returns status of always on top flag. note: this may not match the actual +** TOPMOST window flag while another fullscreen application is focused +*/ + +#define IPC_USES_RECYCLEBIN 651 +/* +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN); +** returns 1 if deleted files should be sent to the recycle bin. +** returns 0 if deleted files should be deleted permanently. +** +** You should check for this option if your plugin deletes files +** so that your setting matches the winamp setting +*/ + +#define IPC_FLUSHAUDITS 652 +/* +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_FLUSHAUDITS); +** +** Will flush any pending audits in the global audits que +** +*/ + +#define IPC_GETPLAYITEM_START 653 +#define IPC_GETPLAYITEM_END 654 + + +#define IPC_GETVIDEORESIZE 655 +#define IPC_SETVIDEORESIZE 656 + +// >>>>>>>>>>> Next is 657 + +#define IPC_PLCMD 1000 + +#define PLCMD_ADD 0 +#define PLCMD_REM 1 +#define PLCMD_SEL 2 +#define PLCMD_MISC 3 +#define PLCMD_LIST 4 + +//#define IPC_MBCMD 1001 + +#define MBCMD_BACK 0 +#define MBCMD_FORWARD 1 +#define MBCMD_STOP 2 +#define MBCMD_RELOAD 3 +#define MBCMD_MISC 4 + +#define IPC_VIDCMD 1002 + +#define VIDCMD_FULLSCREEN 0 +#define VIDCMD_1X 1 +#define VIDCMD_2X 2 +#define VIDCMD_LIB 3 +#define VIDPOPUP_MISC 4 + +//#define IPC_MBURL 1003 //sets the URL +//#define IPC_MBGETCURURL 1004 //copies the current URL into wParam (have a 4096 buffer ready) +//#define IPC_MBGETDESC 1005 //copies the current URL description into wParam (have a 4096 buffer ready) +//#define IPC_MBCHECKLOCFILE 1006 //checks that the link file is up to date (otherwise updates it). wParam=parent HWND +//#define IPC_MBREFRESH 1007 //refreshes the "now playing" view in the library +//#define IPC_MBGETDEFURL 1008 //copies the default URL into wParam (have a 4096 buffer ready) + +#define IPC_STATS_LIBRARY_ITEMCNT 1300 // updates library count status + +// IPC 2000-3000 reserved for freeform messages, see gen_ff/ff_ipc.h +#define IPC_FF_FIRST 2000 +#define IPC_FF_LAST 3000 + + +/* +** General IPC messages in Winamp +** +** All notification messages appear in the lParam of the main window message proceedure. +*/ + + +#define IPC_GETDROPTARGET 3001 +/* (requires Winamp 5.0+) +** IDropTarget* IDrop = (IDropTarget*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETDROPTARGET); +** +** You call this to retrieve a copy of the IDropTarget interface which Winamp created for +** handling external drag and drop operations on to it's Windows. This is only really +** useful if you're providing an alternate interface and want your Windows to provide the +** same drag and drop support as Winamp normally provides the user. Check out MSDN or +** your prefered search facility for more information about the IDropTarget interface and +** what's needed to handle it in your own instance. +*/ + +#define IPC_PLAYLIST_MODIFIED 3002 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window whenever the playlist is +** modified in any way e.g. the addition/removal of a playlist entry. +** +** It is not a good idea to do large amounts of processing in this notification since it +** will slow down Winamp as playlist entries are modified (especially when you're adding +** in a large playlist). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYLIST_MODIFIED){ +** // do what you need to do here +** } +*/ + +#define IPC_PLAYING_FILE 3003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILE){ +** // do what you need to do here, e.g. +** process_file((char*)wParam); +** } +*/ + +#define IPC_PLAYING_FILEW 13003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILEW){ +** // do what you need to do here, e.g. +** process_file((wchar_t*)wParam); +** } +*/ + +#define IPC_FILE_TAG_MAY_HAVE_UPDATED 3004 // sent to main wnd with the file as parm whenever a file tag might be updated +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when a file's tag +** (e.g. id3) may have been updated. This appears to be sent when the InfoBox(..) function +** of the associated input plugin returns a 1 (which is the file information dialog/editor +** call normally). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_FILE_TAG_MAY_HAVE_UPDATED){ +** // do what you need to do here, e.g. +** update_info_on_file_update((char*)wParam); +** } +*/ + +#define IPC_ALLOW_PLAYTRACKING 3007 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,allow,IPC_ALLOW_PLAYTRACKING); +** Send allow as nonzero to allow play tracking and zero to disable the mode. +*/ + +#define IPC_HOOK_OKTOQUIT 3010 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window asking if it's okay to +** close or not. Return zero to prevent Winamp from closing or return anything non-zero +** to allow Winamp to close. +** +** The best implementation of this option is to let the message pass through to the +** original window proceedure since another plugin may want to have a say in the matter +** with regards to Winamp closing. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_HOOK_OKTOQUIT){ +** // do what you need to do here, e.g. +** if(no_shut_down()){ +** return 1; +** } +** } +*/ + +#define IPC_WRITECONFIG 3011 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,write_type,IPC_WRITECONFIG); +** +** Send write_type as 2 to write all config settings and the current playlist. +** +** Send write_type as 1 to write the playlist and common settings. +** This won't save the following ini settings:: +** +** defext, titlefmt, proxy, visplugin_name, dspplugin_name, check_ft_startup, +** visplugin_num, pe_fontsize, visplugin_priority, visplugin_autoexec, dspplugin_num, +** sticon, splash, taskbar, dropaotfs, ascb_new, ttips, riol, minst, whichicon, +** whichicon2, addtolist, snap, snaplen, parent, hilite, disvis, rofiob, shownumsinpl, +** keeponscreen, eqdsize, usecursors, fixtitles, priority, shuffle_morph_rate, +** useexttitles, bifont, inet_mode, ospb, embedwnd_freesize, no_visseh +** (the above was valid for 5.1) +** +** Send write_type as 0 to write the common and less common settings and no playlist. +*/ + +#define IPC_UPDATE_URL 3012 // pass the URL (char *) in lparam, will be free()'d on done. + +// pass a string to be the name to register, and returns a value > 65536, which is a unique value you can use +// for custom WM_WA_IPC messages. + +#define IPC_GET_RANDFUNC 3015 // returns a function to get a random number +/* (requires Winamp 5.1+) +** int (*randfunc)(void) = (int(*)(void))SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GET_RANDFUNC); +** if(randfunc && randfunc != 1){ +** randfunc(); +** } +** +** This will return a positive 32-bit number (essentially 31-bit). +** The check for a returned value of 1 is because that's the default return value from +** SendMessage(..) when it is not handled so is good to check for it in this situation. +*/ + +#define IPC_METADATA_CHANGED 3017 +/* (requires Winamp 5.1+) +** int changed=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)field,IPC_METADATA_CHANGED); +** a plugin can SendMessage this to winamp if internal metadata has changes. +** wParam should be a char * of what field changed +** +** Currently used for internal actions (and very few at that) the intent of this api is +** to allow a plugin to call it when metadata has changed in the current playlist entry +** e.g.a new id3v2 tag was found in a stream +** +** The wparam value can either be NULL or a pointer to an ansi string for the metadata +** which has changed. This can be thought of as an advanced version of IPC_UPDTITLE and +** could be used to allow for update of the current title when a specific tag changed. +** +** Not recommended to be used since there is not the complete handling implemented in +** Winamp for it at the moment. +*/ + +#define IPC_SKIN_CHANGED 3018 +/* (requires Winamp 5.1+) +** This is a notification message sent to the main Winamp window by itself whenever +** the skin in use is changed. There is no information sent by the wParam for this. +** +** if(message == WM_WA_IPC && lparam == IPC_SKIN_CHANGED){ +** // do what you need to do to handle skin changes, e.g. call WADlg_init(hwnd_winamp); +** } +*/ + +#define IPC_REGISTER_LOWORD_COMMAND 3019 +/* (requires Winamp 5.1+) +** WORD id = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REGISTER_LOWORD_COMMAND); +** This will assign you a unique id for making your own commands such as for extra menu +** entries. The starting value returned by this message will potentially change as and +** when the main resource file of Winamp is updated with extra data so assumptions cannot +** be made on what will be returned and plugin loading order will affect things as well. +*/ + +#define IPC_GET_DISPATCH_OBJECT 3020 // gets winamp main IDispatch * (for embedded webpages) +#define IPC_GET_UNIQUE_DISPATCH_ID 3021 // gives you a unique dispatch ID that won't conflict with anything in winamp's IDispatch * + +#define IPC_ADD_DISPATCH_OBJECT 3022 // add your own dispatch object into winamp's. This lets embedded webpages access your functions +// pass a pointer to DispatchInfo (see below). Winamp makes a copy of all this data so you can safely delete it later +typedef struct +{ + wchar_t *name; // filled in by plugin, make sure it's a unicode string!! (i.e. L"myObject" instead of "myObject). + struct IDispatch *dispatch; // filled in by plugin + DWORD id; // filled in by winamp on return +} DispatchInfo; + +#define IPC_GET_PROXY_STRING 3023 +/* (requires Winamp 5.11+) +** char* proxy_string=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_PROXY_STRING); +** This will return the same string as is shown on the General Preferences page. +*/ + +#define IPC_USE_REGISTRY 3024 +/* (requires Winamp 5.11+) +** int reg_enabled=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USE_REGISTRY); +** This will return 0 if you should leave your grubby hands off the registry (i.e. for +** lockdown mode). This is useful if Winamp is run from a USB drive and you can't alter +** system settings, etc. +*/ + +#define IPC_GET_API_SERVICE 3025 +/* (requires Winamp 5.12+) +** api_service* api_service = (api_service)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_API_SERVICE); +** This api will return Winamp's api_service pointer (which is what Winamp3 used, heh). +** If this api is not supported in the Winamp version that is being used at the time then +** the returned value from this api will be 1 which is a good version check. +** +** As of 5.12 there is support for .w5s plugins which reside in %WinampDir%\System and +** are intended for common code that can be shared amongst other plugins e.g. jnetlib.w5s +** which contains jnetlib in one instance instead of being duplicated multiple times in +** all of the plugins which need internet access. +** +** Details on the .w5s specifications will come at some stage (possibly). +*/ + + + +typedef struct { + const wchar_t *filename; + const wchar_t *metadata; + wchar_t *ret; + int retlen; +} extendedFileInfoStructW; + +#define IPC_GET_EXTENDED_FILE_INFOW 3026 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ +#define IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE 3027 +#define IPC_SET_EXTENDED_FILE_INFOW 3028 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ + +#define IPC_PLAYLIST_GET_NEXT_SELECTED 3029 +/* (requires 5.2+) +** int pl_item = SendMessage(hwnd_winamp,WM_WA_IPC,start,IPC_PLAYLIST_GET_NEXT_SELECTED); +** +** This works just like the ListView_GetNextItem(..) macro for ListView controls. +** 'start' is the index of the playlist item that you want to begin the search after or +** set this as -1 for the search to begin with the first item of the current playlist. +** +** This will return the index of the selected playlist according to the 'start' value or +** it returns -1 if there is no selection or no more selected items according to 'start'. +** +** Quick example: +** +** int sel = -1; +** // keep incrementing the start of the search so we get all of the selected entries +** while((sel = SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_PLAYLIST_GET_NEXT_SELECTED))!=-1){ +** // show the playlist file entry of the selected item(s) if there were any +** MessageBox(hwnd_winamp,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_GETPLAYLISTFILE),0,0); +** } +*/ + +#define IPC_PLAYLIST_GET_SELECTED_COUNT 3030 +/* (requires 5.2+) +** int selcnt = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PLAYLIST_GET_SELECTED_COUNT); +** This will return the number of selected playlist entries. +*/ + +#define IPC_GET_PLAYING_FILENAME 3031 // returns wchar_t * of the currently playing filename + +#define IPC_OPEN_URL 3032 // send either ANSI or Unicode string (it'll figure it out, but it MUST start with "h"!, so don't send ftp:// or anything funny) + +#define IPC_REGISTER_WINAMP_IPCMESSAGE 65536 +/* (requires Winamp 5.0+) +** DWORD id = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)name,IPC_REGISTER_WINAMP_IPCMESSAGE); +** The value 'id' returned is > 65536 and is incremented on subsequent calls for unique +** 'name' values passed to it. By using the same 'name' in different plugins will allow a +** common runtime api to be provided for the currently running instance of Winamp +** e.g. +** PostMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)my_param,registered_ipc); +** Have a look at wa_hotkeys.h for an example on how this api is used in practice for a +** custom WM_WA_IPC message. +** +** if(uMsg == WM_WA_IPC && lParam == id_from_register_winamp_ipcmessage){ +** // do things +** } +*/ + +#endif//_WA_IPC_H_ \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h b/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h new file mode 100644 index 00000000..a07780e1 --- /dev/null +++ b/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h @@ -0,0 +1,14384 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0366 */ +/* at Wed Jun 25 17:02:20 2008 + */ +/* Compiler settings for iTunesCOMInterface.idl: + Oicf, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + + +#ifndef __iTunesCOMInterface_h__ +#define __iTunesCOMInterface_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IITObject_FWD_DEFINED__ +#define __IITObject_FWD_DEFINED__ +typedef interface IITObject IITObject; +#endif /* __IITObject_FWD_DEFINED__ */ + + +#ifndef __IITSource_FWD_DEFINED__ +#define __IITSource_FWD_DEFINED__ +typedef interface IITSource IITSource; +#endif /* __IITSource_FWD_DEFINED__ */ + + +#ifndef __IITSourceCollection_FWD_DEFINED__ +#define __IITSourceCollection_FWD_DEFINED__ +typedef interface IITSourceCollection IITSourceCollection; +#endif /* __IITSourceCollection_FWD_DEFINED__ */ + + +#ifndef __IITEncoder_FWD_DEFINED__ +#define __IITEncoder_FWD_DEFINED__ +typedef interface IITEncoder IITEncoder; +#endif /* __IITEncoder_FWD_DEFINED__ */ + + +#ifndef __IITEncoderCollection_FWD_DEFINED__ +#define __IITEncoderCollection_FWD_DEFINED__ +typedef interface IITEncoderCollection IITEncoderCollection; +#endif /* __IITEncoderCollection_FWD_DEFINED__ */ + + +#ifndef __IITEQPreset_FWD_DEFINED__ +#define __IITEQPreset_FWD_DEFINED__ +typedef interface IITEQPreset IITEQPreset; +#endif /* __IITEQPreset_FWD_DEFINED__ */ + + +#ifndef __IITEQPresetCollection_FWD_DEFINED__ +#define __IITEQPresetCollection_FWD_DEFINED__ +typedef interface IITEQPresetCollection IITEQPresetCollection; +#endif /* __IITEQPresetCollection_FWD_DEFINED__ */ + + +#ifndef __IITPlaylist_FWD_DEFINED__ +#define __IITPlaylist_FWD_DEFINED__ +typedef interface IITPlaylist IITPlaylist; +#endif /* __IITPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITOperationStatus_FWD_DEFINED__ +#define __IITOperationStatus_FWD_DEFINED__ +typedef interface IITOperationStatus IITOperationStatus; +#endif /* __IITOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITConvertOperationStatus_FWD_DEFINED__ +#define __IITConvertOperationStatus_FWD_DEFINED__ +typedef interface IITConvertOperationStatus IITConvertOperationStatus; +#endif /* __IITConvertOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITLibraryPlaylist_FWD_DEFINED__ +#define __IITLibraryPlaylist_FWD_DEFINED__ +typedef interface IITLibraryPlaylist IITLibraryPlaylist; +#endif /* __IITLibraryPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITUserPlaylist_FWD_DEFINED__ +#define __IITUserPlaylist_FWD_DEFINED__ +typedef interface IITUserPlaylist IITUserPlaylist; +#endif /* __IITUserPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITTrack_FWD_DEFINED__ +#define __IITTrack_FWD_DEFINED__ +typedef interface IITTrack IITTrack; +#endif /* __IITTrack_FWD_DEFINED__ */ + + +#ifndef __IITTrackCollection_FWD_DEFINED__ +#define __IITTrackCollection_FWD_DEFINED__ +typedef interface IITTrackCollection IITTrackCollection; +#endif /* __IITTrackCollection_FWD_DEFINED__ */ + + +#ifndef __IITVisual_FWD_DEFINED__ +#define __IITVisual_FWD_DEFINED__ +typedef interface IITVisual IITVisual; +#endif /* __IITVisual_FWD_DEFINED__ */ + + +#ifndef __IITVisualCollection_FWD_DEFINED__ +#define __IITVisualCollection_FWD_DEFINED__ +typedef interface IITVisualCollection IITVisualCollection; +#endif /* __IITVisualCollection_FWD_DEFINED__ */ + + +#ifndef __IITWindow_FWD_DEFINED__ +#define __IITWindow_FWD_DEFINED__ +typedef interface IITWindow IITWindow; +#endif /* __IITWindow_FWD_DEFINED__ */ + + +#ifndef __IITBrowserWindow_FWD_DEFINED__ +#define __IITBrowserWindow_FWD_DEFINED__ +typedef interface IITBrowserWindow IITBrowserWindow; +#endif /* __IITBrowserWindow_FWD_DEFINED__ */ + + +#ifndef __IITWindowCollection_FWD_DEFINED__ +#define __IITWindowCollection_FWD_DEFINED__ +typedef interface IITWindowCollection IITWindowCollection; +#endif /* __IITWindowCollection_FWD_DEFINED__ */ + + +#ifndef __IiTunes_FWD_DEFINED__ +#define __IiTunes_FWD_DEFINED__ +typedef interface IiTunes IiTunes; +#endif /* __IiTunes_FWD_DEFINED__ */ + + +#ifndef ___IiTunesEvents_FWD_DEFINED__ +#define ___IiTunesEvents_FWD_DEFINED__ +typedef interface _IiTunesEvents _IiTunesEvents; +#endif /* ___IiTunesEvents_FWD_DEFINED__ */ + + +#ifndef ___IITConvertOperationStatusEvents_FWD_DEFINED__ +#define ___IITConvertOperationStatusEvents_FWD_DEFINED__ +typedef interface _IITConvertOperationStatusEvents _IITConvertOperationStatusEvents; +#endif /* ___IITConvertOperationStatusEvents_FWD_DEFINED__ */ + + +#ifndef __iTunesApp_FWD_DEFINED__ +#define __iTunesApp_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class iTunesApp iTunesApp; +#else +typedef struct iTunesApp iTunesApp; +#endif /* __cplusplus */ + +#endif /* __iTunesApp_FWD_DEFINED__ */ + + +#ifndef __iTunesConvertOperationStatus_FWD_DEFINED__ +#define __iTunesConvertOperationStatus_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class iTunesConvertOperationStatus iTunesConvertOperationStatus; +#else +typedef struct iTunesConvertOperationStatus iTunesConvertOperationStatus; +#endif /* __cplusplus */ + +#endif /* __iTunesConvertOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITArtwork_FWD_DEFINED__ +#define __IITArtwork_FWD_DEFINED__ +typedef interface IITArtwork IITArtwork; +#endif /* __IITArtwork_FWD_DEFINED__ */ + + +#ifndef __IITArtworkCollection_FWD_DEFINED__ +#define __IITArtworkCollection_FWD_DEFINED__ +typedef interface IITArtworkCollection IITArtworkCollection; +#endif /* __IITArtworkCollection_FWD_DEFINED__ */ + + +#ifndef __IITURLTrack_FWD_DEFINED__ +#define __IITURLTrack_FWD_DEFINED__ +typedef interface IITURLTrack IITURLTrack; +#endif /* __IITURLTrack_FWD_DEFINED__ */ + + +#ifndef __IITAudioCDPlaylist_FWD_DEFINED__ +#define __IITAudioCDPlaylist_FWD_DEFINED__ +typedef interface IITAudioCDPlaylist IITAudioCDPlaylist; +#endif /* __IITAudioCDPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITPlaylistCollection_FWD_DEFINED__ +#define __IITPlaylistCollection_FWD_DEFINED__ +typedef interface IITPlaylistCollection IITPlaylistCollection; +#endif /* __IITPlaylistCollection_FWD_DEFINED__ */ + + +#ifndef __IITIPodSource_FWD_DEFINED__ +#define __IITIPodSource_FWD_DEFINED__ +typedef interface IITIPodSource IITIPodSource; +#endif /* __IITIPodSource_FWD_DEFINED__ */ + + +#ifndef __IITFileOrCDTrack_FWD_DEFINED__ +#define __IITFileOrCDTrack_FWD_DEFINED__ +typedef interface IITFileOrCDTrack IITFileOrCDTrack; +#endif /* __IITFileOrCDTrack_FWD_DEFINED__ */ + + +#ifndef __IITPlaylistWindow_FWD_DEFINED__ +#define __IITPlaylistWindow_FWD_DEFINED__ +typedef interface IITPlaylistWindow IITPlaylistWindow; +#endif /* __IITPlaylistWindow_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "oaidl.h" +#include "ocidl.h" +#include "DispEx.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +/* interface __MIDL_itf_iTunesCOMInterface_0000 */ +/* [local] */ + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4B73428D-2F56-4833-8E5D-65590E45FEAD") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0001 + { kITTypeLibrary_MajorVersion = 1, + kITTypeLibrary_MinorVersion = 11 + } ITVersion; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4C25623B-F990-4ebd-8970-F29A70084B8C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0002 + { ITUNES_E_USERCANCEL = 0xa0040201, + ITUNES_E_OBJECTDELETED = 0xa0040202, + ITUNES_E_OBJECTLOCKED = 0xa0040203, + ITUNES_E_CONVERSIONINPROGRESS = 0xa0040204, + ITUNES_E_MUSICSTOREDISABLED = 0xa0040205, + ITUNES_E_OBJECTEXISTS = 0xa0040206, + ITUNES_E_PODCASTSDISABLED = 0xa0040207 + } ITErrors; + + + +extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_s_ifspec; + + +#ifndef __iTunesLib_LIBRARY_DEFINED__ +#define __iTunesLib_LIBRARY_DEFINED__ + +/* library iTunesLib */ +/* [helpstring][uuid][version] */ + + + + + + + + + + + + + + + + + + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("3D502ACA-B474-4640-A2A4-C149538345EC") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0001 + { ITPlayerStateStopped = 0, + ITPlayerStatePlaying = ITPlayerStateStopped + 1, + ITPlayerStateFastForward = ITPlayerStatePlaying + 1, + ITPlayerStateRewind = ITPlayerStateFastForward + 1 + } ITPlayerState; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5319FADA-0F39-4015-82A0-48B8B871C63C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0002 + { ITVisualSizeSmall = 0, + ITVisualSizeMedium = ITVisualSizeSmall + 1, + ITVisualSizeLarge = ITVisualSizeMedium + 1 + } ITVisualSize; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C8128C8D-EDE0-4f0e-AEB1-08D24A91C551") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0003 + { ITCOMDisabledReasonOther = 0, + ITCOMDisabledReasonDialog = ITCOMDisabledReasonOther + 1, + ITCOMDisabledReasonQuitting = ITCOMDisabledReasonDialog + 1 + } ITCOMDisabledReason; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("6B1BD814-CA6E-4063-9EDA-4128D31068C1") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0004 + { ITPlayButtonStatePlayDisabled = 0, + ITPlayButtonStatePlayEnabled = ITPlayButtonStatePlayDisabled + 1, + ITPlayButtonStatePauseEnabled = ITPlayButtonStatePlayEnabled + 1, + ITPlayButtonStatePauseDisabled = ITPlayButtonStatePauseEnabled + 1, + ITPlayButtonStateStopEnabled = ITPlayButtonStatePauseDisabled + 1, + ITPlayButtonStateStopDisabled = ITPlayButtonStateStopEnabled + 1 + } ITPlayButtonState; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("8AF85488-2154-4e46-B65B-1972A43493EF") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0005 + { ITPlayerButtonPrevious = 0, + ITPlayerButtonPlay = ITPlayerButtonPrevious + 1, + ITPlayerButtonNext = ITPlayerButtonPlay + 1 + } ITPlayerButton; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2129AB11-F23F-485e-B15A-3F8573294F9A") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0006 + { ITPlayerButtonModifierKeyNone = 0, + ITPlayerButtonModifierKeyShift = 1, + ITPlayerButtonModifierKeyControl = 2, + ITPlayerButtonModifierKeyAlt = 4, + ITPlayerButtonModifierKeyCapsLock = 8 + } ITPlayerButtonModifierKey; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("3194F5F4-8F52-41e6-AB8E-4221CFE29550") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0275_0001 + { ITEventDatabaseChanged = 1, + ITEventPlayerPlay = 2, + ITEventPlayerStop = 3, + ITEventPlayerPlayingTrackChanged = 4, + ITEventUserInterfaceEnabled = 5, + ITEventCOMCallsDisabled = 6, + ITEventCOMCallsEnabled = 7, + ITEventQuitting = 8, + ITEventAboutToPromptUserToQuit = 9, + ITEventSoundVolumeChanged = 10 + } ITEvent; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2E4D55FA-1CD3-4831-8751-0C11EC4FF6FD") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0276_0001 + { ITConvertOperationStatusChanged = 1, + ITConvertOperationComplete = 2 + } ITConvertOperationStatusEvent; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("269E36A5-1728-46e4-BF04-93032C3DD51C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0277_0001 + { ITArtworkFormatUnknown = 0, + ITArtworkFormatJPEG = ITArtworkFormatUnknown + 1, + ITArtworkFormatPNG = ITArtworkFormatJPEG + 1, + ITArtworkFormatBMP = ITArtworkFormatPNG + 1 + } ITArtworkFormat; + + + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("DDE76D6E-5F8C-4bda-AFA6-69E82218CFF3") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0001 + { ITPlaylistKindUnknown = 0, + ITPlaylistKindLibrary = ITPlaylistKindUnknown + 1, + ITPlaylistKindUser = ITPlaylistKindLibrary + 1, + ITPlaylistKindCD = ITPlaylistKindUser + 1, + ITPlaylistKindDevice = ITPlaylistKindCD + 1, + ITPlaylistKindRadioTuner = ITPlaylistKindDevice + 1 + } ITPlaylistKind; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("4E1D67A4-6C7A-4c7d-821C-03AF7EB10C35") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0002 + { ITPlaylistRepeatModeOff = 0, + ITPlaylistRepeatModeOne = ITPlaylistRepeatModeOff + 1, + ITPlaylistRepeatModeAll = ITPlaylistRepeatModeOne + 1 + } ITPlaylistRepeatMode; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("BB8E7701-1E77-4972-B6C4-C70AC216F468") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0003 + { ITPlaylistPrintKindPlaylist = 0, + ITPlaylistPrintKindAlbumlist = ITPlaylistPrintKindPlaylist + 1, + ITPlaylistPrintKindInsert = ITPlaylistPrintKindAlbumlist + 1 + } ITPlaylistPrintKind; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("58765E77-E34A-4d67-AC12-5B5BA33EA08F") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0004 + { ITPlaylistSearchFieldAll = 0, + ITPlaylistSearchFieldVisible = ITPlaylistSearchFieldAll + 1, + ITPlaylistSearchFieldArtists = ITPlaylistSearchFieldVisible + 1, + ITPlaylistSearchFieldAlbums = ITPlaylistSearchFieldArtists + 1, + ITPlaylistSearchFieldComposers = ITPlaylistSearchFieldAlbums + 1, + ITPlaylistSearchFieldSongNames = ITPlaylistSearchFieldComposers + 1 + } ITPlaylistSearchField; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("62BC24E6-5C77-4fb7-AA6C-B7FA40C6095D") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0285_0001 + { ITUserPlaylistSpecialKindNone = 0, + ITUserPlaylistSpecialKindPurchasedMusic = ITUserPlaylistSpecialKindNone + 1, + ITUserPlaylistSpecialKindPartyShuffle = ITUserPlaylistSpecialKindPurchasedMusic + 1, + ITUserPlaylistSpecialKindPodcasts = ITUserPlaylistSpecialKindPartyShuffle + 1, + ITUserPlaylistSpecialKindFolder = ITUserPlaylistSpecialKindPodcasts + 1, + ITUserPlaylistSpecialKindVideos = ITUserPlaylistSpecialKindFolder + 1, + ITUserPlaylistSpecialKindMusic = ITUserPlaylistSpecialKindVideos + 1, + ITUserPlaylistSpecialKindMovies = ITUserPlaylistSpecialKindMusic + 1, + ITUserPlaylistSpecialKindTVShows = ITUserPlaylistSpecialKindMovies + 1, + ITUserPlaylistSpecialKindAudiobooks = ITUserPlaylistSpecialKindTVShows + 1 + } ITUserPlaylistSpecialKind; + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("5F35912B-E633-4930-9E25-09489BAED75A") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0288_0001 + { ITSourceKindUnknown = 0, + ITSourceKindLibrary = ITSourceKindUnknown + 1, + ITSourceKindIPod = ITSourceKindLibrary + 1, + ITSourceKindAudioCD = ITSourceKindIPod + 1, + ITSourceKindMP3CD = ITSourceKindAudioCD + 1, + ITSourceKindDevice = ITSourceKindMP3CD + 1, + ITSourceKindRadioTuner = ITSourceKindDevice + 1, + ITSourceKindSharedLibrary = ITSourceKindRadioTuner + 1 + } ITSourceKind; + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("ACA133C5-4697-4d5f-98B1-D9881B85FE98") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0001 + { ITTrackKindUnknown = 0, + ITTrackKindFile = ITTrackKindUnknown + 1, + ITTrackKindCD = ITTrackKindFile + 1, + ITTrackKindURL = ITTrackKindCD + 1, + ITTrackKindDevice = ITTrackKindURL + 1, + ITTrackKindSharedLibrary = ITTrackKindDevice + 1 + } ITTrackKind; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("735ECC17-38CC-4d4d-A838-24AF7DCB440E") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0002 + { ITVideoKindNone = 0, + ITVideoKindMovie = ITVideoKindNone + 1, + ITVideoKindMusicVideo = ITVideoKindMovie + 1, + ITVideoKindTVShow = ITVideoKindMusicVideo + 1 + } ITVideoKind; + +typedef /* [public][public][public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5C75B72C-D066-4faa-8732-D9ED71A6CBD9") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0003 + { ITRatingKindUser = 0, + ITRatingKindComputed = ITRatingKindUser + 1 + } ITRatingKind; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C20CE920-EFD9-4c1a-8036-95A895741214") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0297_0001 + { ITWindowKindUnknown = 0, + ITWindowKindBrowser = ITWindowKindUnknown + 1, + ITWindowKindPlaylist = ITWindowKindBrowser + 1, + ITWindowKindEQ = ITWindowKindPlaylist + 1, + ITWindowKindArtwork = ITWindowKindEQ + 1, + ITWindowKindNowPlaying = ITWindowKindArtwork + 1 + } ITWindowKind; + + +EXTERN_C const IID LIBID_iTunesLib; + +#ifndef __IITObject_INTERFACE_DEFINED__ +#define __IITObject_INTERFACE_DEFINED__ + +/* interface IITObject */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITObject; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9FAB0E27-70D7-4e3a-9965-B0C8B8869BB6") + IITObject : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectIDs( + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Name( + /* [in] */ BSTR name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Index( + /* [retval][out] */ long *index) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SourceID( + /* [retval][out] */ long *sourceID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlaylistID( + /* [retval][out] */ long *playlistID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackID( + /* [retval][out] */ long *trackID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackDatabaseID( + /* [retval][out] */ long *databaseID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITObjectVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITObject * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITObject * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITObject * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITObject * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITObject * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITObject * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITObject * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITObject * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITObject * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITObject * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITObject * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITObject * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITObject * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITObject * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITObject * This, + /* [retval][out] */ long *databaseID); + + END_INTERFACE + } IITObjectVtbl; + + interface IITObject + { + CONST_VTBL struct IITObjectVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITObject_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITObject_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITObject_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITObject_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITObject_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITObject_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITObject_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITObject_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITObject_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITObject_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITObject_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITObject_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITObject_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITObject_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITObject_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITObject_GetITObjectIDs_Proxy( + IITObject * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + +void __RPC_STUB IITObject_GetITObjectIDs_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Name_Proxy( + IITObject * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITObject_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITObject_put_Name_Proxy( + IITObject * This, + /* [in] */ BSTR name); + + +void __RPC_STUB IITObject_put_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Index_Proxy( + IITObject * This, + /* [retval][out] */ long *index); + + +void __RPC_STUB IITObject_get_Index_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_SourceID_Proxy( + IITObject * This, + /* [retval][out] */ long *sourceID); + + +void __RPC_STUB IITObject_get_SourceID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_PlaylistID_Proxy( + IITObject * This, + /* [retval][out] */ long *playlistID); + + +void __RPC_STUB IITObject_get_PlaylistID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackID_Proxy( + IITObject * This, + /* [retval][out] */ long *trackID); + + +void __RPC_STUB IITObject_get_TrackID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackDatabaseID_Proxy( + IITObject * This, + /* [retval][out] */ long *databaseID); + + +void __RPC_STUB IITObject_get_TrackDatabaseID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITObject_INTERFACE_DEFINED__ */ + + +#ifndef __IITSource_INTERFACE_DEFINED__ +#define __IITSource_INTERFACE_DEFINED__ + +/* interface IITSource */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AEC1C4D3-AEF1-4255-B892-3E3D13ADFDF9") + IITSource : public IITObject + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITSourceKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Capacity( + /* [retval][out] */ double *capacity) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FreeSpace( + /* [retval][out] */ double *freespace) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITSource * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITSource * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITSource * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITSource * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITSource * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITSource * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITSource * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITSource * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITSource * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITSource * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITSource * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITSource * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITSource * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITSource * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITSource * This, + /* [retval][out] */ ITSourceKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( + IITSource * This, + /* [retval][out] */ double *capacity); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( + IITSource * This, + /* [retval][out] */ double *freespace); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITSourceVtbl; + + interface IITSource + { + CONST_VTBL struct IITSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITSource_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITSource_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITSource_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITSource_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITSource_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITSource_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITSource_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITSource_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITSource_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITSource_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITSource_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITSource_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITSource_get_Capacity(This,capacity) \ + (This)->lpVtbl -> get_Capacity(This,capacity) + +#define IITSource_get_FreeSpace(This,freespace) \ + (This)->lpVtbl -> get_FreeSpace(This,freespace) + +#define IITSource_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Kind_Proxy( + IITSource * This, + /* [retval][out] */ ITSourceKind *kind); + + +void __RPC_STUB IITSource_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Capacity_Proxy( + IITSource * This, + /* [retval][out] */ double *capacity); + + +void __RPC_STUB IITSource_get_Capacity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_FreeSpace_Proxy( + IITSource * This, + /* [retval][out] */ double *freespace); + + +void __RPC_STUB IITSource_get_FreeSpace_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Playlists_Proxy( + IITSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITSource_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITSource_INTERFACE_DEFINED__ */ + + +#ifndef __IITSourceCollection_INTERFACE_DEFINED__ +#define __IITSourceCollection_INTERFACE_DEFINED__ + +/* interface IITSourceCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITSourceCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2FF6CE20-FF87-4183-B0B3-F323D047AF41") + IITSourceCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITSourceCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITSourceCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITSourceCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITSourceCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITSourceCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITSourceCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITSourceCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITSourceCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITSourceCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITSourceCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITSourceCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITSourceCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITSourceCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource); + + END_INTERFACE + } IITSourceCollectionVtbl; + + interface IITSourceCollection + { + CONST_VTBL struct IITSourceCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITSourceCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITSourceCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITSourceCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITSourceCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITSourceCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITSourceCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITSourceCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITSourceCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITSourceCollection_get_Item(This,index,iSource) \ + (This)->lpVtbl -> get_Item(This,index,iSource) + +#define IITSourceCollection_get_ItemByName(This,name,iSource) \ + (This)->lpVtbl -> get_ItemByName(This,name,iSource) + +#define IITSourceCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITSourceCollection_get_ItemByPersistentID(This,highID,lowID,iSource) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iSource) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Count_Proxy( + IITSourceCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITSourceCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Item_Proxy( + IITSourceCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByName_Proxy( + IITSourceCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get__NewEnum_Proxy( + IITSourceCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITSourceCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByPersistentID_Proxy( + IITSourceCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITSourceCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITEncoder_INTERFACE_DEFINED__ +#define __IITEncoder_INTERFACE_DEFINED__ + +/* interface IITEncoder */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEncoder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1CF95A1C-55FE-4f45-A2D3-85AC6C504A73") + IITEncoder : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( + /* [retval][out] */ BSTR *format) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEncoderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEncoder * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEncoder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEncoder * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEncoder * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEncoder * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEncoder * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEncoder * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITEncoder * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( + IITEncoder * This, + /* [retval][out] */ BSTR *format); + + END_INTERFACE + } IITEncoderVtbl; + + interface IITEncoder + { + CONST_VTBL struct IITEncoderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEncoder_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEncoder_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEncoder_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEncoder_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEncoder_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEncoder_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEncoder_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEncoder_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITEncoder_get_Format(This,format) \ + (This)->lpVtbl -> get_Format(This,format) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Name_Proxy( + IITEncoder * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITEncoder_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Format_Proxy( + IITEncoder * This, + /* [retval][out] */ BSTR *format); + + +void __RPC_STUB IITEncoder_get_Format_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEncoder_INTERFACE_DEFINED__ */ + + +#ifndef __IITEncoderCollection_INTERFACE_DEFINED__ +#define __IITEncoderCollection_INTERFACE_DEFINED__ + +/* interface IITEncoderCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEncoderCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8862BCA9-168D-4549-A9D5-ADB35E553BA6") + IITEncoderCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEncoderCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEncoderCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEncoderCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEncoderCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEncoderCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEncoderCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEncoderCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEncoderCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITEncoderCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITEncoderCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITEncoderCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITEncoderCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITEncoderCollectionVtbl; + + interface IITEncoderCollection + { + CONST_VTBL struct IITEncoderCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEncoderCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEncoderCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEncoderCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEncoderCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEncoderCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEncoderCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEncoderCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEncoderCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITEncoderCollection_get_Item(This,index,iEncoder) \ + (This)->lpVtbl -> get_Item(This,index,iEncoder) + +#define IITEncoderCollection_get_ItemByName(This,name,iEncoder) \ + (This)->lpVtbl -> get_ItemByName(This,name,iEncoder) + +#define IITEncoderCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Count_Proxy( + IITEncoderCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITEncoderCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Item_Proxy( + IITEncoderCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IITEncoderCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_ItemByName_Proxy( + IITEncoderCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IITEncoderCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get__NewEnum_Proxy( + IITEncoderCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITEncoderCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEncoderCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITEQPreset_INTERFACE_DEFINED__ +#define __IITEQPreset_INTERFACE_DEFINED__ + +/* interface IITEQPreset */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEQPreset; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5BE75F4F-68FA-4212-ACB7-BE44EA569759") + IITEQPreset : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Modifiable( + /* [retval][out] */ VARIANT_BOOL *isModifiable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Preamp( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Preamp( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band1( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band1( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band2( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band2( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band3( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band3( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band4( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band4( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band5( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band5( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band6( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band6( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band7( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band7( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band8( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band8( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band9( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band9( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band10( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band10( + /* [in] */ double level) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( + /* [in] */ VARIANT_BOOL updateAllTracks) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rename( + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEQPresetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEQPreset * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEQPreset * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEQPreset * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEQPreset * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEQPreset * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEQPreset * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEQPreset * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITEQPreset * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Modifiable )( + IITEQPreset * This, + /* [retval][out] */ VARIANT_BOOL *isModifiable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Preamp )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Preamp )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band1 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band1 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band2 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band2 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band3 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band3 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band4 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band4 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band5 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band5 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band6 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band6 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band7 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band7 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band8 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band8 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band9 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band9 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band10 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band10 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITEQPreset * This, + /* [in] */ VARIANT_BOOL updateAllTracks); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rename )( + IITEQPreset * This, + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks); + + END_INTERFACE + } IITEQPresetVtbl; + + interface IITEQPreset + { + CONST_VTBL struct IITEQPresetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEQPreset_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEQPreset_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEQPreset_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEQPreset_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEQPreset_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEQPreset_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEQPreset_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEQPreset_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITEQPreset_get_Modifiable(This,isModifiable) \ + (This)->lpVtbl -> get_Modifiable(This,isModifiable) + +#define IITEQPreset_get_Preamp(This,level) \ + (This)->lpVtbl -> get_Preamp(This,level) + +#define IITEQPreset_put_Preamp(This,level) \ + (This)->lpVtbl -> put_Preamp(This,level) + +#define IITEQPreset_get_Band1(This,level) \ + (This)->lpVtbl -> get_Band1(This,level) + +#define IITEQPreset_put_Band1(This,level) \ + (This)->lpVtbl -> put_Band1(This,level) + +#define IITEQPreset_get_Band2(This,level) \ + (This)->lpVtbl -> get_Band2(This,level) + +#define IITEQPreset_put_Band2(This,level) \ + (This)->lpVtbl -> put_Band2(This,level) + +#define IITEQPreset_get_Band3(This,level) \ + (This)->lpVtbl -> get_Band3(This,level) + +#define IITEQPreset_put_Band3(This,level) \ + (This)->lpVtbl -> put_Band3(This,level) + +#define IITEQPreset_get_Band4(This,level) \ + (This)->lpVtbl -> get_Band4(This,level) + +#define IITEQPreset_put_Band4(This,level) \ + (This)->lpVtbl -> put_Band4(This,level) + +#define IITEQPreset_get_Band5(This,level) \ + (This)->lpVtbl -> get_Band5(This,level) + +#define IITEQPreset_put_Band5(This,level) \ + (This)->lpVtbl -> put_Band5(This,level) + +#define IITEQPreset_get_Band6(This,level) \ + (This)->lpVtbl -> get_Band6(This,level) + +#define IITEQPreset_put_Band6(This,level) \ + (This)->lpVtbl -> put_Band6(This,level) + +#define IITEQPreset_get_Band7(This,level) \ + (This)->lpVtbl -> get_Band7(This,level) + +#define IITEQPreset_put_Band7(This,level) \ + (This)->lpVtbl -> put_Band7(This,level) + +#define IITEQPreset_get_Band8(This,level) \ + (This)->lpVtbl -> get_Band8(This,level) + +#define IITEQPreset_put_Band8(This,level) \ + (This)->lpVtbl -> put_Band8(This,level) + +#define IITEQPreset_get_Band9(This,level) \ + (This)->lpVtbl -> get_Band9(This,level) + +#define IITEQPreset_put_Band9(This,level) \ + (This)->lpVtbl -> put_Band9(This,level) + +#define IITEQPreset_get_Band10(This,level) \ + (This)->lpVtbl -> get_Band10(This,level) + +#define IITEQPreset_put_Band10(This,level) \ + (This)->lpVtbl -> put_Band10(This,level) + +#define IITEQPreset_Delete(This,updateAllTracks) \ + (This)->lpVtbl -> Delete(This,updateAllTracks) + +#define IITEQPreset_Rename(This,newName,updateAllTracks) \ + (This)->lpVtbl -> Rename(This,newName,updateAllTracks) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Name_Proxy( + IITEQPreset * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITEQPreset_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Modifiable_Proxy( + IITEQPreset * This, + /* [retval][out] */ VARIANT_BOOL *isModifiable); + + +void __RPC_STUB IITEQPreset_get_Modifiable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Preamp_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Preamp_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Preamp_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Preamp_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band1_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band1_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band1_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band1_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band2_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band2_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band3_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band3_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band3_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band3_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band4_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band4_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band4_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band4_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band5_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band5_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band5_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band5_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band6_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band6_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band6_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band6_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band7_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band7_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band7_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band7_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band8_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band8_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band8_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band8_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band9_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band9_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band9_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band9_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band10_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band10_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band10_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band10_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Delete_Proxy( + IITEQPreset * This, + /* [in] */ VARIANT_BOOL updateAllTracks); + + +void __RPC_STUB IITEQPreset_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Rename_Proxy( + IITEQPreset * This, + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks); + + +void __RPC_STUB IITEQPreset_Rename_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEQPreset_INTERFACE_DEFINED__ */ + + +#ifndef __IITEQPresetCollection_INTERFACE_DEFINED__ +#define __IITEQPresetCollection_INTERFACE_DEFINED__ + +/* interface IITEQPresetCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEQPresetCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AEF4D111-3331-48da-B0C2-B468D5D61D08") + IITEQPresetCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEQPresetCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEQPresetCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEQPresetCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEQPresetCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEQPresetCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEQPresetCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEQPresetCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEQPresetCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITEQPresetCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITEQPresetCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITEQPresetCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITEQPresetCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITEQPresetCollectionVtbl; + + interface IITEQPresetCollection + { + CONST_VTBL struct IITEQPresetCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEQPresetCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEQPresetCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEQPresetCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEQPresetCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEQPresetCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEQPresetCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEQPresetCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEQPresetCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITEQPresetCollection_get_Item(This,index,iEQPreset) \ + (This)->lpVtbl -> get_Item(This,index,iEQPreset) + +#define IITEQPresetCollection_get_ItemByName(This,name,iEQPreset) \ + (This)->lpVtbl -> get_ItemByName(This,name,iEQPreset) + +#define IITEQPresetCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Count_Proxy( + IITEQPresetCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITEQPresetCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Item_Proxy( + IITEQPresetCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IITEQPresetCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_ItemByName_Proxy( + IITEQPresetCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IITEQPresetCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get__NewEnum_Proxy( + IITEQPresetCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITEQPresetCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEQPresetCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylist_INTERFACE_DEFINED__ +#define __IITPlaylist_INTERFACE_DEFINED__ + +/* interface IITPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3D5E072F-2A77-4b17-9E73-E03B77CCCCA9") + IITPlaylist : public IITObject + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFirstTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Print( + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Search( + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITPlaylistKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Source( + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( + /* [retval][out] */ long *duration) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shuffle( + /* [retval][out] */ VARIANT_BOOL *isShuffle) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shuffle( + /* [in] */ VARIANT_BOOL shouldShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( + /* [retval][out] */ double *size) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SongRepeat( + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SongRepeat( + /* [in] */ ITPlaylistRepeatMode repeatMode) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( + /* [retval][out] */ BSTR *time) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( + /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + END_INTERFACE + } IITPlaylistVtbl; + + interface IITPlaylist + { + CONST_VTBL struct IITPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Delete_Proxy( + IITPlaylist * This); + + +void __RPC_STUB IITPlaylist_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_PlayFirstTrack_Proxy( + IITPlaylist * This); + + +void __RPC_STUB IITPlaylist_PlayFirstTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Print_Proxy( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + +void __RPC_STUB IITPlaylist_Print_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Search_Proxy( + IITPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylist_Search_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Kind_Proxy( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + +void __RPC_STUB IITPlaylist_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Source_Proxy( + IITPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITPlaylist_get_Source_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Duration_Proxy( + IITPlaylist * This, + /* [retval][out] */ long *duration); + + +void __RPC_STUB IITPlaylist_get_Duration_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Shuffle_Proxy( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + +void __RPC_STUB IITPlaylist_get_Shuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_Shuffle_Proxy( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + +void __RPC_STUB IITPlaylist_put_Shuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Size_Proxy( + IITPlaylist * This, + /* [retval][out] */ double *size); + + +void __RPC_STUB IITPlaylist_get_Size_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_SongRepeat_Proxy( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + +void __RPC_STUB IITPlaylist_get_SongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_SongRepeat_Proxy( + IITPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + +void __RPC_STUB IITPlaylist_put_SongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Time_Proxy( + IITPlaylist * This, + /* [retval][out] */ BSTR *time); + + +void __RPC_STUB IITPlaylist_get_Time_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Visible_Proxy( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + +void __RPC_STUB IITPlaylist_get_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Tracks_Proxy( + IITPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylist_get_Tracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITOperationStatus_INTERFACE_DEFINED__ +#define __IITOperationStatus_INTERFACE_DEFINED__ + +/* interface IITOperationStatus */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITOperationStatus; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("206479C9-FE32-4f9b-A18A-475AC939B479") + IITOperationStatus : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_InProgress( + /* [retval][out] */ VARIANT_BOOL *isInProgress) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITOperationStatusVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITOperationStatus * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITOperationStatus * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITOperationStatus * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITOperationStatus * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITOperationStatus * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITOperationStatus * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITOperationStatus * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( + IITOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + END_INTERFACE + } IITOperationStatusVtbl; + + interface IITOperationStatus + { + CONST_VTBL struct IITOperationStatusVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITOperationStatus_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITOperationStatus_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITOperationStatus_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITOperationStatus_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITOperationStatus_get_InProgress(This,isInProgress) \ + (This)->lpVtbl -> get_InProgress(This,isInProgress) + +#define IITOperationStatus_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_InProgress_Proxy( + IITOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + +void __RPC_STUB IITOperationStatus_get_InProgress_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_Tracks_Proxy( + IITOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITOperationStatus_get_Tracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITOperationStatus_INTERFACE_DEFINED__ */ + + +#ifndef __IITConvertOperationStatus_INTERFACE_DEFINED__ +#define __IITConvertOperationStatus_INTERFACE_DEFINED__ + +/* interface IITConvertOperationStatus */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITConvertOperationStatus; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7063AAF6-ABA0-493b-B4FC-920A9F105875") + IITConvertOperationStatus : public IITOperationStatus + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetConversionStatus( + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE StopConversion( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackName( + /* [retval][out] */ BSTR *trackName) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ProgressValue( + /* [retval][out] */ long *progressValue) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MaxProgressValue( + /* [retval][out] */ long *maxProgressValue) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITConvertOperationStatusVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITConvertOperationStatus * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITConvertOperationStatus * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITConvertOperationStatus * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITConvertOperationStatus * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITConvertOperationStatus * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITConvertOperationStatus * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITConvertOperationStatus * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( + IITConvertOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITConvertOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetConversionStatus )( + IITConvertOperationStatus * This, + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *StopConversion )( + IITConvertOperationStatus * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackName )( + IITConvertOperationStatus * This, + /* [retval][out] */ BSTR *trackName); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProgressValue )( + IITConvertOperationStatus * This, + /* [retval][out] */ long *progressValue); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MaxProgressValue )( + IITConvertOperationStatus * This, + /* [retval][out] */ long *maxProgressValue); + + END_INTERFACE + } IITConvertOperationStatusVtbl; + + interface IITConvertOperationStatus + { + CONST_VTBL struct IITConvertOperationStatusVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITConvertOperationStatus_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITConvertOperationStatus_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITConvertOperationStatus_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITConvertOperationStatus_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITConvertOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITConvertOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITConvertOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITConvertOperationStatus_get_InProgress(This,isInProgress) \ + (This)->lpVtbl -> get_InProgress(This,isInProgress) + +#define IITConvertOperationStatus_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITConvertOperationStatus_GetConversionStatus(This,trackName,progressValue,maxProgressValue) \ + (This)->lpVtbl -> GetConversionStatus(This,trackName,progressValue,maxProgressValue) + +#define IITConvertOperationStatus_StopConversion(This) \ + (This)->lpVtbl -> StopConversion(This) + +#define IITConvertOperationStatus_get_TrackName(This,trackName) \ + (This)->lpVtbl -> get_TrackName(This,trackName) + +#define IITConvertOperationStatus_get_ProgressValue(This,progressValue) \ + (This)->lpVtbl -> get_ProgressValue(This,progressValue) + +#define IITConvertOperationStatus_get_MaxProgressValue(This,maxProgressValue) \ + (This)->lpVtbl -> get_MaxProgressValue(This,maxProgressValue) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_GetConversionStatus_Proxy( + IITConvertOperationStatus * This, + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue); + + +void __RPC_STUB IITConvertOperationStatus_GetConversionStatus_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_StopConversion_Proxy( + IITConvertOperationStatus * This); + + +void __RPC_STUB IITConvertOperationStatus_StopConversion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_TrackName_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ BSTR *trackName); + + +void __RPC_STUB IITConvertOperationStatus_get_TrackName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_ProgressValue_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ long *progressValue); + + +void __RPC_STUB IITConvertOperationStatus_get_ProgressValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_MaxProgressValue_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ long *maxProgressValue); + + +void __RPC_STUB IITConvertOperationStatus_get_MaxProgressValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITConvertOperationStatus_INTERFACE_DEFINED__ */ + + +#ifndef __IITLibraryPlaylist_INTERFACE_DEFINED__ +#define __IITLibraryPlaylist_INTERFACE_DEFINED__ + +/* interface IITLibraryPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITLibraryPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("53AE1704-491C-4289-94A0-958815675A3D") + IITLibraryPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITLibraryPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITLibraryPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITLibraryPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITLibraryPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITLibraryPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITLibraryPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITLibraryPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITLibraryPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITLibraryPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITLibraryPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITLibraryPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITLibraryPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITLibraryPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITLibraryPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITLibraryPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITLibraryPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITLibraryPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITLibraryPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITLibraryPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITLibraryPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITLibraryPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITLibraryPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITLibraryPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( + IITLibraryPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( + IITLibraryPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + END_INTERFACE + } IITLibraryPlaylistVtbl; + + interface IITLibraryPlaylist + { + CONST_VTBL struct IITLibraryPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITLibraryPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITLibraryPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITLibraryPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITLibraryPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITLibraryPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITLibraryPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITLibraryPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITLibraryPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITLibraryPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITLibraryPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITLibraryPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITLibraryPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITLibraryPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITLibraryPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITLibraryPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITLibraryPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITLibraryPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITLibraryPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITLibraryPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITLibraryPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITLibraryPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITLibraryPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITLibraryPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITLibraryPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITLibraryPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITLibraryPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITLibraryPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITLibraryPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITLibraryPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITLibraryPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITLibraryPlaylist_AddFile(This,filePath,iStatus) \ + (This)->lpVtbl -> AddFile(This,filePath,iStatus) + +#define IITLibraryPlaylist_AddFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) + +#define IITLibraryPlaylist_AddURL(This,url,iURLTrack) \ + (This)->lpVtbl -> AddURL(This,url,iURLTrack) + +#define IITLibraryPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ + (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFile_Proxy( + IITLibraryPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITLibraryPlaylist_AddFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFiles_Proxy( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITLibraryPlaylist_AddFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddURL_Proxy( + IITLibraryPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + +void __RPC_STUB IITLibraryPlaylist_AddURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddTrack_Proxy( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + +void __RPC_STUB IITLibraryPlaylist_AddTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITLibraryPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITUserPlaylist_INTERFACE_DEFINED__ +#define __IITUserPlaylist_INTERFACE_DEFINED__ + +/* interface IITUserPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITUserPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0A504DED-A0B5-465a-8A94-50E20D7DF692") + IITUserPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shared( + /* [retval][out] */ VARIANT_BOOL *isShared) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shared( + /* [in] */ VARIANT_BOOL shouldBeShared) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Smart( + /* [retval][out] */ VARIANT_BOOL *isSmart) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SpecialKind( + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Parent( + /* [retval][out] */ IITUserPlaylist **iParentPlayList) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Parent( + /* [in] */ VARIANT *iParent) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITUserPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITUserPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITUserPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITUserPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITUserPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITUserPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITUserPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITUserPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITUserPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITUserPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITUserPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITUserPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITUserPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITUserPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITUserPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITUserPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITUserPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITUserPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITUserPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITUserPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITUserPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITUserPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITUserPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITUserPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITUserPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITUserPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITUserPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( + IITUserPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( + IITUserPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( + IITUserPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( + IITUserPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shared )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShared); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shared )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldBeShared); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Smart )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isSmart); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SpecialKind )( + IITUserPlaylist * This, + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Parent )( + IITUserPlaylist * This, + /* [retval][out] */ IITUserPlaylist **iParentPlayList); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( + IITUserPlaylist * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( + IITUserPlaylist * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Parent )( + IITUserPlaylist * This, + /* [in] */ VARIANT *iParent); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITUserPlaylist * This); + + END_INTERFACE + } IITUserPlaylistVtbl; + + interface IITUserPlaylist + { + CONST_VTBL struct IITUserPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITUserPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITUserPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITUserPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITUserPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITUserPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITUserPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITUserPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITUserPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITUserPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITUserPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITUserPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITUserPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITUserPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITUserPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITUserPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITUserPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITUserPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITUserPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITUserPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITUserPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITUserPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITUserPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITUserPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITUserPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITUserPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITUserPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITUserPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITUserPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITUserPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITUserPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITUserPlaylist_AddFile(This,filePath,iStatus) \ + (This)->lpVtbl -> AddFile(This,filePath,iStatus) + +#define IITUserPlaylist_AddFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) + +#define IITUserPlaylist_AddURL(This,url,iURLTrack) \ + (This)->lpVtbl -> AddURL(This,url,iURLTrack) + +#define IITUserPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ + (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) + +#define IITUserPlaylist_get_Shared(This,isShared) \ + (This)->lpVtbl -> get_Shared(This,isShared) + +#define IITUserPlaylist_put_Shared(This,shouldBeShared) \ + (This)->lpVtbl -> put_Shared(This,shouldBeShared) + +#define IITUserPlaylist_get_Smart(This,isSmart) \ + (This)->lpVtbl -> get_Smart(This,isSmart) + +#define IITUserPlaylist_get_SpecialKind(This,specialKind) \ + (This)->lpVtbl -> get_SpecialKind(This,specialKind) + +#define IITUserPlaylist_get_Parent(This,iParentPlayList) \ + (This)->lpVtbl -> get_Parent(This,iParentPlayList) + +#define IITUserPlaylist_CreatePlaylist(This,playlistName,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) + +#define IITUserPlaylist_CreateFolder(This,folderName,iFolder) \ + (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) + +#define IITUserPlaylist_put_Parent(This,iParent) \ + (This)->lpVtbl -> put_Parent(This,iParent) + +#define IITUserPlaylist_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFile_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITUserPlaylist_AddFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFiles_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITUserPlaylist_AddFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddURL_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + +void __RPC_STUB IITUserPlaylist_AddURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddTrack_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + +void __RPC_STUB IITUserPlaylist_AddTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Shared_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShared); + + +void __RPC_STUB IITUserPlaylist_get_Shared_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Shared_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldBeShared); + + +void __RPC_STUB IITUserPlaylist_put_Shared_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Smart_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isSmart); + + +void __RPC_STUB IITUserPlaylist_get_Smart_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_SpecialKind_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); + + +void __RPC_STUB IITUserPlaylist_get_SpecialKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Parent_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ IITUserPlaylist **iParentPlayList); + + +void __RPC_STUB IITUserPlaylist_get_Parent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreatePlaylist_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITUserPlaylist_CreatePlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreateFolder_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IITUserPlaylist_CreateFolder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Parent_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *iParent); + + +void __RPC_STUB IITUserPlaylist_put_Parent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_Reveal_Proxy( + IITUserPlaylist * This); + + +void __RPC_STUB IITUserPlaylist_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITUserPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITTrack_INTERFACE_DEFINED__ +#define __IITTrack_INTERFACE_DEFINED__ + +/* interface IITTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4CB0915D-1E54-4727-BAF3-CE6CC9A225A1") + IITTrack : public IITObject + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddArtworkFromFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITTrackKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Album( + /* [retval][out] */ BSTR *album) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Album( + /* [in] */ BSTR album) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Artist( + /* [in] */ BSTR artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BitRate( + /* [retval][out] */ long *bitrate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BPM( + /* [retval][out] */ long *beatsPerMinute) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BPM( + /* [in] */ long beatsPerMinute) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Comment( + /* [retval][out] */ BSTR *comment) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Comment( + /* [in] */ BSTR comment) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( + /* [retval][out] */ VARIANT_BOOL *isCompilation) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Compilation( + /* [in] */ VARIANT_BOOL shouldBeCompilation) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Composer( + /* [in] */ BSTR composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DateAdded( + /* [retval][out] */ DATE *dateAdded) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( + /* [retval][out] */ long *discCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscCount( + /* [in] */ long discCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( + /* [retval][out] */ long *discNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscNumber( + /* [in] */ long discNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( + /* [retval][out] */ long *duration) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Enabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Enabled( + /* [in] */ VARIANT_BOOL shouldBeEnabled) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQ( + /* [retval][out] */ BSTR *eq) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQ( + /* [in] */ BSTR eq) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Finish( + /* [in] */ long finish) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Finish( + /* [retval][out] */ long *finish) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( + /* [retval][out] */ BSTR *genre) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Genre( + /* [in] */ BSTR genre) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Grouping( + /* [retval][out] */ BSTR *grouping) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Grouping( + /* [in] */ BSTR grouping) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_KindAsString( + /* [retval][out] */ BSTR *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ModificationDate( + /* [retval][out] */ DATE *dateModified) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedCount( + /* [retval][out] */ long *playedCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedCount( + /* [in] */ long playedCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedDate( + /* [retval][out] */ DATE *playedDate) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedDate( + /* [in] */ DATE playedDate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayOrderIndex( + /* [retval][out] */ long *index) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Rating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Rating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SampleRate( + /* [retval][out] */ long *sampleRate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( + /* [retval][out] */ long *size) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Start( + /* [retval][out] */ long *start) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Start( + /* [in] */ long start) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( + /* [retval][out] */ BSTR *time) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackCount( + /* [retval][out] */ long *trackCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackCount( + /* [in] */ long trackCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackNumber( + /* [retval][out] */ long *trackNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackNumber( + /* [in] */ long trackNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VolumeAdjustment( + /* [retval][out] */ long *volumeAdjustment) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VolumeAdjustment( + /* [in] */ long volumeAdjustment) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( + /* [retval][out] */ long *year) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Year( + /* [in] */ long year) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artwork( + /* [retval][out] */ IITArtworkCollection **iArtworkCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + END_INTERFACE + } IITTrackVtbl; + + interface IITTrack + { + CONST_VTBL struct IITTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Delete_Proxy( + IITTrack * This); + + +void __RPC_STUB IITTrack_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Play_Proxy( + IITTrack * This); + + +void __RPC_STUB IITTrack_Play_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_AddArtworkFromFile_Proxy( + IITTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + +void __RPC_STUB IITTrack_AddArtworkFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Kind_Proxy( + IITTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + +void __RPC_STUB IITTrack_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Playlist_Proxy( + IITTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITTrack_get_Playlist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Album_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *album); + + +void __RPC_STUB IITTrack_get_Album_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Album_Proxy( + IITTrack * This, + /* [in] */ BSTR album); + + +void __RPC_STUB IITTrack_put_Album_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artist_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITTrack_get_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Artist_Proxy( + IITTrack * This, + /* [in] */ BSTR artist); + + +void __RPC_STUB IITTrack_put_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BitRate_Proxy( + IITTrack * This, + /* [retval][out] */ long *bitrate); + + +void __RPC_STUB IITTrack_get_BitRate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BPM_Proxy( + IITTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + +void __RPC_STUB IITTrack_get_BPM_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_BPM_Proxy( + IITTrack * This, + /* [in] */ long beatsPerMinute); + + +void __RPC_STUB IITTrack_put_BPM_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Comment_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *comment); + + +void __RPC_STUB IITTrack_get_Comment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Comment_Proxy( + IITTrack * This, + /* [in] */ BSTR comment); + + +void __RPC_STUB IITTrack_put_Comment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Compilation_Proxy( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + +void __RPC_STUB IITTrack_get_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Compilation_Proxy( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + +void __RPC_STUB IITTrack_put_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Composer_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITTrack_get_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Composer_Proxy( + IITTrack * This, + /* [in] */ BSTR composer); + + +void __RPC_STUB IITTrack_put_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DateAdded_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *dateAdded); + + +void __RPC_STUB IITTrack_get_DateAdded_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *discCount); + + +void __RPC_STUB IITTrack_get_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscCount_Proxy( + IITTrack * This, + /* [in] */ long discCount); + + +void __RPC_STUB IITTrack_put_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscNumber_Proxy( + IITTrack * This, + /* [retval][out] */ long *discNumber); + + +void __RPC_STUB IITTrack_get_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscNumber_Proxy( + IITTrack * This, + /* [in] */ long discNumber); + + +void __RPC_STUB IITTrack_put_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Duration_Proxy( + IITTrack * This, + /* [retval][out] */ long *duration); + + +void __RPC_STUB IITTrack_get_Duration_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Enabled_Proxy( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IITTrack_get_Enabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Enabled_Proxy( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + +void __RPC_STUB IITTrack_put_Enabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_EQ_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *eq); + + +void __RPC_STUB IITTrack_get_EQ_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_EQ_Proxy( + IITTrack * This, + /* [in] */ BSTR eq); + + +void __RPC_STUB IITTrack_put_EQ_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Finish_Proxy( + IITTrack * This, + /* [in] */ long finish); + + +void __RPC_STUB IITTrack_put_Finish_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Finish_Proxy( + IITTrack * This, + /* [retval][out] */ long *finish); + + +void __RPC_STUB IITTrack_get_Finish_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Genre_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *genre); + + +void __RPC_STUB IITTrack_get_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Genre_Proxy( + IITTrack * This, + /* [in] */ BSTR genre); + + +void __RPC_STUB IITTrack_put_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Grouping_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *grouping); + + +void __RPC_STUB IITTrack_get_Grouping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Grouping_Proxy( + IITTrack * This, + /* [in] */ BSTR grouping); + + +void __RPC_STUB IITTrack_put_Grouping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_KindAsString_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *kind); + + +void __RPC_STUB IITTrack_get_KindAsString_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_ModificationDate_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *dateModified); + + +void __RPC_STUB IITTrack_get_ModificationDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *playedCount); + + +void __RPC_STUB IITTrack_get_PlayedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedCount_Proxy( + IITTrack * This, + /* [in] */ long playedCount); + + +void __RPC_STUB IITTrack_put_PlayedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedDate_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *playedDate); + + +void __RPC_STUB IITTrack_get_PlayedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedDate_Proxy( + IITTrack * This, + /* [in] */ DATE playedDate); + + +void __RPC_STUB IITTrack_put_PlayedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayOrderIndex_Proxy( + IITTrack * This, + /* [retval][out] */ long *index); + + +void __RPC_STUB IITTrack_get_PlayOrderIndex_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Rating_Proxy( + IITTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITTrack_get_Rating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Rating_Proxy( + IITTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITTrack_put_Rating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_SampleRate_Proxy( + IITTrack * This, + /* [retval][out] */ long *sampleRate); + + +void __RPC_STUB IITTrack_get_SampleRate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Size_Proxy( + IITTrack * This, + /* [retval][out] */ long *size); + + +void __RPC_STUB IITTrack_get_Size_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Start_Proxy( + IITTrack * This, + /* [retval][out] */ long *start); + + +void __RPC_STUB IITTrack_get_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Start_Proxy( + IITTrack * This, + /* [in] */ long start); + + +void __RPC_STUB IITTrack_put_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Time_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *time); + + +void __RPC_STUB IITTrack_get_Time_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *trackCount); + + +void __RPC_STUB IITTrack_get_TrackCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackCount_Proxy( + IITTrack * This, + /* [in] */ long trackCount); + + +void __RPC_STUB IITTrack_put_TrackCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackNumber_Proxy( + IITTrack * This, + /* [retval][out] */ long *trackNumber); + + +void __RPC_STUB IITTrack_get_TrackNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackNumber_Proxy( + IITTrack * This, + /* [in] */ long trackNumber); + + +void __RPC_STUB IITTrack_put_TrackNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_VolumeAdjustment_Proxy( + IITTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + +void __RPC_STUB IITTrack_get_VolumeAdjustment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_VolumeAdjustment_Proxy( + IITTrack * This, + /* [in] */ long volumeAdjustment); + + +void __RPC_STUB IITTrack_put_VolumeAdjustment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Year_Proxy( + IITTrack * This, + /* [retval][out] */ long *year); + + +void __RPC_STUB IITTrack_get_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Year_Proxy( + IITTrack * This, + /* [in] */ long year); + + +void __RPC_STUB IITTrack_put_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artwork_Proxy( + IITTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + +void __RPC_STUB IITTrack_get_Artwork_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITTrackCollection_INTERFACE_DEFINED__ +#define __IITTrackCollection_INTERFACE_DEFINED__ + +/* interface IITTrackCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITTrackCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("755D76F1-6B85-4ce4-8F5F-F88D9743DCD8") + IITTrackCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPlayOrder( + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITTrackCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITTrackCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITTrackCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITTrackCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITTrackCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITTrackCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITTrackCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITTrackCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITTrackCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPlayOrder )( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITTrackCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITTrackCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITTrackCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack); + + END_INTERFACE + } IITTrackCollectionVtbl; + + interface IITTrackCollection + { + CONST_VTBL struct IITTrackCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITTrackCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITTrackCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITTrackCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITTrackCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITTrackCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITTrackCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITTrackCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITTrackCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITTrackCollection_get_Item(This,index,iTrack) \ + (This)->lpVtbl -> get_Item(This,index,iTrack) + +#define IITTrackCollection_get_ItemByPlayOrder(This,index,iTrack) \ + (This)->lpVtbl -> get_ItemByPlayOrder(This,index,iTrack) + +#define IITTrackCollection_get_ItemByName(This,name,iTrack) \ + (This)->lpVtbl -> get_ItemByName(This,name,iTrack) + +#define IITTrackCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITTrackCollection_get_ItemByPersistentID(This,highID,lowID,iTrack) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iTrack) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Count_Proxy( + IITTrackCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITTrackCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Item_Proxy( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPlayOrder_Proxy( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByPlayOrder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByName_Proxy( + IITTrackCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get__NewEnum_Proxy( + IITTrackCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITTrackCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPersistentID_Proxy( + IITTrackCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITTrackCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITVisual_INTERFACE_DEFINED__ +#define __IITVisual_INTERFACE_DEFINED__ + +/* interface IITVisual */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITVisual; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("340F3315-ED72-4c09-9ACF-21EB4BDF9931") + IITVisual : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITVisualVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITVisual * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITVisual * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITVisual * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITVisual * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITVisual * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITVisual * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITVisual * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITVisual * This, + /* [retval][out] */ BSTR *name); + + END_INTERFACE + } IITVisualVtbl; + + interface IITVisual + { + CONST_VTBL struct IITVisualVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITVisual_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITVisual_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITVisual_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITVisual_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITVisual_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITVisual_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITVisual_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITVisual_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisual_get_Name_Proxy( + IITVisual * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITVisual_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITVisual_INTERFACE_DEFINED__ */ + + +#ifndef __IITVisualCollection_INTERFACE_DEFINED__ +#define __IITVisualCollection_INTERFACE_DEFINED__ + +/* interface IITVisualCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITVisualCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("88A4CCDD-114F-4043-B69B-84D4E6274957") + IITVisualCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITVisualCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITVisualCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITVisualCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITVisualCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITVisualCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITVisualCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITVisualCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITVisualCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITVisualCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITVisualCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITVisualCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITVisualCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITVisualCollectionVtbl; + + interface IITVisualCollection + { + CONST_VTBL struct IITVisualCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITVisualCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITVisualCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITVisualCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITVisualCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITVisualCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITVisualCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITVisualCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITVisualCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITVisualCollection_get_Item(This,index,iVisual) \ + (This)->lpVtbl -> get_Item(This,index,iVisual) + +#define IITVisualCollection_get_ItemByName(This,name,iVisual) \ + (This)->lpVtbl -> get_ItemByName(This,name,iVisual) + +#define IITVisualCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Count_Proxy( + IITVisualCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITVisualCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Item_Proxy( + IITVisualCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IITVisualCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_ItemByName_Proxy( + IITVisualCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IITVisualCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get__NewEnum_Proxy( + IITVisualCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITVisualCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITVisualCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITWindow_INTERFACE_DEFINED__ +#define __IITWindow_INTERFACE_DEFINED__ + +/* interface IITWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("370D7BE0-3A89-4a42-B902-C75FC138BE09") + IITWindow : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITWindowKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( + /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Visible( + /* [in] */ VARIANT_BOOL shouldBeVisible) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Resizable( + /* [retval][out] */ VARIANT_BOOL *isResizable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Minimized( + /* [retval][out] */ VARIANT_BOOL *isMinimized) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Minimized( + /* [in] */ VARIANT_BOOL shouldBeMinimized) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximizable( + /* [retval][out] */ VARIANT_BOOL *isMaximizable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximized( + /* [retval][out] */ VARIANT_BOOL *isMaximized) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Maximized( + /* [in] */ VARIANT_BOOL shouldBeMaximized) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomable( + /* [retval][out] */ VARIANT_BOOL *isZoomable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomed( + /* [retval][out] */ VARIANT_BOOL *isZoomed) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Zoomed( + /* [in] */ VARIANT_BOOL shouldBeZoomed) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Top( + /* [retval][out] */ long *top) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Top( + /* [in] */ long top) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Left( + /* [retval][out] */ long *left) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Left( + /* [in] */ long left) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Bottom( + /* [retval][out] */ long *bottom) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Bottom( + /* [in] */ long bottom) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Right( + /* [retval][out] */ long *right) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Right( + /* [in] */ long right) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Width( + /* [retval][out] */ long *width) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Width( + /* [in] */ long width) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Height( + /* [retval][out] */ long *height) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Height( + /* [in] */ long height) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITWindow * This, + /* [in] */ long height); + + END_INTERFACE + } IITWindowVtbl; + + interface IITWindow + { + CONST_VTBL struct IITWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Name_Proxy( + IITWindow * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITWindow_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Kind_Proxy( + IITWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + +void __RPC_STUB IITWindow_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Visible_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + +void __RPC_STUB IITWindow_get_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Visible_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + +void __RPC_STUB IITWindow_put_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Resizable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + +void __RPC_STUB IITWindow_get_Resizable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Minimized_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + +void __RPC_STUB IITWindow_get_Minimized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Minimized_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + +void __RPC_STUB IITWindow_put_Minimized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximizable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + +void __RPC_STUB IITWindow_get_Maximizable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximized_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + +void __RPC_STUB IITWindow_get_Maximized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Maximized_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + +void __RPC_STUB IITWindow_put_Maximized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + +void __RPC_STUB IITWindow_get_Zoomable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomed_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + +void __RPC_STUB IITWindow_get_Zoomed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Zoomed_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + +void __RPC_STUB IITWindow_put_Zoomed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Top_Proxy( + IITWindow * This, + /* [retval][out] */ long *top); + + +void __RPC_STUB IITWindow_get_Top_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Top_Proxy( + IITWindow * This, + /* [in] */ long top); + + +void __RPC_STUB IITWindow_put_Top_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Left_Proxy( + IITWindow * This, + /* [retval][out] */ long *left); + + +void __RPC_STUB IITWindow_get_Left_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Left_Proxy( + IITWindow * This, + /* [in] */ long left); + + +void __RPC_STUB IITWindow_put_Left_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Bottom_Proxy( + IITWindow * This, + /* [retval][out] */ long *bottom); + + +void __RPC_STUB IITWindow_get_Bottom_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Bottom_Proxy( + IITWindow * This, + /* [in] */ long bottom); + + +void __RPC_STUB IITWindow_put_Bottom_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Right_Proxy( + IITWindow * This, + /* [retval][out] */ long *right); + + +void __RPC_STUB IITWindow_get_Right_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Right_Proxy( + IITWindow * This, + /* [in] */ long right); + + +void __RPC_STUB IITWindow_put_Right_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Width_Proxy( + IITWindow * This, + /* [retval][out] */ long *width); + + +void __RPC_STUB IITWindow_get_Width_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Width_Proxy( + IITWindow * This, + /* [in] */ long width); + + +void __RPC_STUB IITWindow_put_Width_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Height_Proxy( + IITWindow * This, + /* [retval][out] */ long *height); + + +void __RPC_STUB IITWindow_get_Height_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Height_Proxy( + IITWindow * This, + /* [in] */ long height); + + +void __RPC_STUB IITWindow_put_Height_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITWindow_INTERFACE_DEFINED__ */ + + +#ifndef __IITBrowserWindow_INTERFACE_DEFINED__ +#define __IITBrowserWindow_INTERFACE_DEFINED__ + +/* interface IITBrowserWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITBrowserWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C999F455-C4D5-4aa4-8277-F99753699974") + IITBrowserWindow : public IITWindow + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MiniPlayer( + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MiniPlayer( + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedPlaylist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SelectedPlaylist( + /* [in] */ VARIANT *iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITBrowserWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITBrowserWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITBrowserWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITBrowserWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITBrowserWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITBrowserWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITBrowserWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITBrowserWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITBrowserWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITBrowserWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITBrowserWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITBrowserWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITBrowserWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITBrowserWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITBrowserWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITBrowserWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITBrowserWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITBrowserWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITBrowserWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITBrowserWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITBrowserWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITBrowserWindow * This, + /* [in] */ long height); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MiniPlayer )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MiniPlayer )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IITBrowserWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedPlaylist )( + IITBrowserWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SelectedPlaylist )( + IITBrowserWindow * This, + /* [in] */ VARIANT *iPlaylist); + + END_INTERFACE + } IITBrowserWindowVtbl; + + interface IITBrowserWindow + { + CONST_VTBL struct IITBrowserWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITBrowserWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITBrowserWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITBrowserWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITBrowserWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITBrowserWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITBrowserWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITBrowserWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITBrowserWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITBrowserWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITBrowserWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITBrowserWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITBrowserWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITBrowserWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITBrowserWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITBrowserWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITBrowserWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITBrowserWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITBrowserWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITBrowserWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITBrowserWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITBrowserWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITBrowserWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITBrowserWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITBrowserWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITBrowserWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITBrowserWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITBrowserWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITBrowserWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITBrowserWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITBrowserWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITBrowserWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITBrowserWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + + +#define IITBrowserWindow_get_MiniPlayer(This,isMiniPlayer) \ + (This)->lpVtbl -> get_MiniPlayer(This,isMiniPlayer) + +#define IITBrowserWindow_put_MiniPlayer(This,shouldBeMiniPlayer) \ + (This)->lpVtbl -> put_MiniPlayer(This,shouldBeMiniPlayer) + +#define IITBrowserWindow_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IITBrowserWindow_get_SelectedPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> get_SelectedPlaylist(This,iPlaylist) + +#define IITBrowserWindow_put_SelectedPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> put_SelectedPlaylist(This,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_MiniPlayer_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); + + +void __RPC_STUB IITBrowserWindow_get_MiniPlayer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_MiniPlayer_Proxy( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); + + +void __RPC_STUB IITBrowserWindow_put_MiniPlayer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedTracks_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITBrowserWindow_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedPlaylist_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITBrowserWindow_get_SelectedPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_SelectedPlaylist_Proxy( + IITBrowserWindow * This, + /* [in] */ VARIANT *iPlaylist); + + +void __RPC_STUB IITBrowserWindow_put_SelectedPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITBrowserWindow_INTERFACE_DEFINED__ */ + + +#ifndef __IITWindowCollection_INTERFACE_DEFINED__ +#define __IITWindowCollection_INTERFACE_DEFINED__ + +/* interface IITWindowCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITWindowCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3D8DE381-6C0E-481f-A865-E2385F59FA43") + IITWindowCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITWindowCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITWindowCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITWindowCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITWindowCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITWindowCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITWindowCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITWindowCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITWindowCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITWindowCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITWindowCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITWindowCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITWindowCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITWindowCollectionVtbl; + + interface IITWindowCollection + { + CONST_VTBL struct IITWindowCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITWindowCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITWindowCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITWindowCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITWindowCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITWindowCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITWindowCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITWindowCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITWindowCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITWindowCollection_get_Item(This,index,iWindow) \ + (This)->lpVtbl -> get_Item(This,index,iWindow) + +#define IITWindowCollection_get_ItemByName(This,name,iWindow) \ + (This)->lpVtbl -> get_ItemByName(This,name,iWindow) + +#define IITWindowCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Count_Proxy( + IITWindowCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITWindowCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Item_Proxy( + IITWindowCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow); + + +void __RPC_STUB IITWindowCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_ItemByName_Proxy( + IITWindowCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow); + + +void __RPC_STUB IITWindowCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get__NewEnum_Proxy( + IITWindowCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITWindowCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITWindowCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IiTunes_INTERFACE_DEFINED__ +#define __IiTunes_INTERFACE_DEFINED__ + +/* interface IiTunes */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + + + +EXTERN_C const IID IID_IiTunes; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9DD6680B-3EDC-40db-A771-E6FE4832E34A") + IiTunes : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE BackTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FastForward( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE NextTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayPause( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PreviousTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Resume( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rewind( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack( + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks( + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CheckVersion( + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectByID( + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OpenURL( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GotoMusicStoreHomePage( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Authorize( + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Quit( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Sources( + /* [retval][out] */ IITSourceCollection **iSourceCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Encoders( + /* [retval][out] */ IITEncoderCollection **iEncoderCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQPresets( + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visuals( + /* [retval][out] */ IITVisualCollection **iVisualCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Windows( + /* [retval][out] */ IITWindowCollection **iWindowCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolume( + /* [retval][out] */ long *volume) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SoundVolume( + /* [in] */ long volume) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Mute( + /* [retval][out] */ VARIANT_BOOL *isMuted) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Mute( + /* [in] */ VARIANT_BOOL shouldMute) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerState( + /* [retval][out] */ ITPlayerState *playerState) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerPosition( + /* [retval][out] */ long *playerPos) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayerPosition( + /* [in] */ long playerPos) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEncoder( + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEncoder( + /* [in] */ IITEncoder *iEncoder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualsEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualsEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FullScreenVisuals( + /* [retval][out] */ VARIANT_BOOL *isFullScreen) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_FullScreenVisuals( + /* [in] */ VARIANT_BOOL shouldUseFullScreen) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualSize( + /* [retval][out] */ ITVisualSize *visualSize) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualSize( + /* [in] */ ITVisualSize visualSize) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentVisual( + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentVisual( + /* [in] */ IITVisual *iVisual) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEQPreset( + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEQPreset( + /* [in] */ IITEQPreset *iEQPreset) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamTitle( + /* [retval][out] */ BSTR *streamTitle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamURL( + /* [retval][out] */ BSTR *streamURL) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BrowserWindow( + /* [retval][out] */ IITBrowserWindow **iBrowserWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQWindow( + /* [retval][out] */ IITWindow **iEQWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibrarySource( + /* [retval][out] */ IITSource **iLibrarySource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryPlaylist( + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentTrack( + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentPlaylist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Version( + /* [retval][out] */ BSTR *version) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetOptions( + /* [in] */ long options) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile2( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles2( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack2( + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks2( + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AppCommandMessageProcessingEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AppCommandMessageProcessingEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForceToForegroundOnDialog( + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForceToForegroundOnDialog( + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateEQPreset( + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylistInSource( + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPlayerButtonsState( + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayerButtonClicked( + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetShuffle( + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetSongRepeat( + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ConvertOperationStatus( + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SubscribeToPodcast( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeeds( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolderInSource( + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolumeControlEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryXMLPath( + /* [retval][out] */ BSTR *filePath) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDHigh( + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDLow( + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectPersistentIDs( + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IiTunesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IiTunes * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IiTunes * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IiTunes * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IiTunes * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IiTunes * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IiTunes * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IiTunes * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *BackTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FastForward )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *NextTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Pause )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFile )( + IiTunes * This, + /* [in] */ BSTR filePath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayPause )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PreviousTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Resume )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rewind )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Stop )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile )( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles )( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack )( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks )( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CheckVersion )( + IiTunes * This, + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectByID )( + IiTunes * This, + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *OpenURL )( + IiTunes * This, + /* [in] */ BSTR url); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GotoMusicStoreHomePage )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Authorize )( + IiTunes * This, + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Quit )( + IiTunes * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Sources )( + IiTunes * This, + /* [retval][out] */ IITSourceCollection **iSourceCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Encoders )( + IiTunes * This, + /* [retval][out] */ IITEncoderCollection **iEncoderCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQPresets )( + IiTunes * This, + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visuals )( + IiTunes * This, + /* [retval][out] */ IITVisualCollection **iVisualCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Windows )( + IiTunes * This, + /* [retval][out] */ IITWindowCollection **iWindowCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolume )( + IiTunes * This, + /* [retval][out] */ long *volume); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SoundVolume )( + IiTunes * This, + /* [in] */ long volume); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Mute )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isMuted); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Mute )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldMute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerState )( + IiTunes * This, + /* [retval][out] */ ITPlayerState *playerState); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerPosition )( + IiTunes * This, + /* [retval][out] */ long *playerPos); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayerPosition )( + IiTunes * This, + /* [in] */ long playerPos); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEncoder )( + IiTunes * This, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEncoder )( + IiTunes * This, + /* [in] */ IITEncoder *iEncoder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualsEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualsEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FullScreenVisuals )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isFullScreen); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_FullScreenVisuals )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldUseFullScreen); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualSize )( + IiTunes * This, + /* [retval][out] */ ITVisualSize *visualSize); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualSize )( + IiTunes * This, + /* [in] */ ITVisualSize visualSize); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentVisual )( + IiTunes * This, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentVisual )( + IiTunes * This, + /* [in] */ IITVisual *iVisual); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEQPreset )( + IiTunes * This, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEQPreset )( + IiTunes * This, + /* [in] */ IITEQPreset *iEQPreset); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamTitle )( + IiTunes * This, + /* [retval][out] */ BSTR *streamTitle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamURL )( + IiTunes * This, + /* [retval][out] */ BSTR *streamURL); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserWindow )( + IiTunes * This, + /* [retval][out] */ IITBrowserWindow **iBrowserWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQWindow )( + IiTunes * This, + /* [retval][out] */ IITWindow **iEQWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibrarySource )( + IiTunes * This, + /* [retval][out] */ IITSource **iLibrarySource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryPlaylist )( + IiTunes * This, + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentTrack )( + IiTunes * This, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentPlaylist )( + IiTunes * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IiTunes * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Version )( + IiTunes * This, + /* [retval][out] */ BSTR *version); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetOptions )( + IiTunes * This, + /* [in] */ long options); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile2 )( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles2 )( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack2 )( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks2 )( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AppCommandMessageProcessingEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AppCommandMessageProcessingEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForceToForegroundOnDialog )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForceToForegroundOnDialog )( + IiTunes * This, + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateEQPreset )( + IiTunes * This, + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylistInSource )( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPlayerButtonsState )( + IiTunes * This, + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayerButtonClicked )( + IiTunes * This, + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetShuffle )( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetSongRepeat )( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ConvertOperationStatus )( + IiTunes * This, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SubscribeToPodcast )( + IiTunes * This, + /* [in] */ BSTR url); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeeds )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolderInSource )( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolumeControlEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryXMLPath )( + IiTunes * This, + /* [retval][out] */ BSTR *filePath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDHigh )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDLow )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectPersistentIDs )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID); + + END_INTERFACE + } IiTunesVtbl; + + interface IiTunes + { + CONST_VTBL struct IiTunesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IiTunes_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IiTunes_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IiTunes_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IiTunes_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IiTunes_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IiTunes_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IiTunes_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IiTunes_BackTrack(This) \ + (This)->lpVtbl -> BackTrack(This) + +#define IiTunes_FastForward(This) \ + (This)->lpVtbl -> FastForward(This) + +#define IiTunes_NextTrack(This) \ + (This)->lpVtbl -> NextTrack(This) + +#define IiTunes_Pause(This) \ + (This)->lpVtbl -> Pause(This) + +#define IiTunes_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IiTunes_PlayFile(This,filePath) \ + (This)->lpVtbl -> PlayFile(This,filePath) + +#define IiTunes_PlayPause(This) \ + (This)->lpVtbl -> PlayPause(This) + +#define IiTunes_PreviousTrack(This) \ + (This)->lpVtbl -> PreviousTrack(This) + +#define IiTunes_Resume(This) \ + (This)->lpVtbl -> Resume(This) + +#define IiTunes_Rewind(This) \ + (This)->lpVtbl -> Rewind(This) + +#define IiTunes_Stop(This) \ + (This)->lpVtbl -> Stop(This) + +#define IiTunes_ConvertFile(This,filePath,iStatus) \ + (This)->lpVtbl -> ConvertFile(This,filePath,iStatus) + +#define IiTunes_ConvertFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> ConvertFiles(This,filePaths,iStatus) + +#define IiTunes_ConvertTrack(This,iTrackToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTrack(This,iTrackToConvert,iStatus) + +#define IiTunes_ConvertTracks(This,iTracksToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTracks(This,iTracksToConvert,iStatus) + +#define IiTunes_CheckVersion(This,majorVersion,minorVersion,isCompatible) \ + (This)->lpVtbl -> CheckVersion(This,majorVersion,minorVersion,isCompatible) + +#define IiTunes_GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) \ + (This)->lpVtbl -> GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) + +#define IiTunes_CreatePlaylist(This,playlistName,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) + +#define IiTunes_OpenURL(This,url) \ + (This)->lpVtbl -> OpenURL(This,url) + +#define IiTunes_GotoMusicStoreHomePage(This) \ + (This)->lpVtbl -> GotoMusicStoreHomePage(This) + +#define IiTunes_UpdateIPod(This) \ + (This)->lpVtbl -> UpdateIPod(This) + +#define IiTunes_Authorize(This,numElems,data,names) \ + (This)->lpVtbl -> Authorize(This,numElems,data,names) + +#define IiTunes_Quit(This) \ + (This)->lpVtbl -> Quit(This) + +#define IiTunes_get_Sources(This,iSourceCollection) \ + (This)->lpVtbl -> get_Sources(This,iSourceCollection) + +#define IiTunes_get_Encoders(This,iEncoderCollection) \ + (This)->lpVtbl -> get_Encoders(This,iEncoderCollection) + +#define IiTunes_get_EQPresets(This,iEQPresetCollection) \ + (This)->lpVtbl -> get_EQPresets(This,iEQPresetCollection) + +#define IiTunes_get_Visuals(This,iVisualCollection) \ + (This)->lpVtbl -> get_Visuals(This,iVisualCollection) + +#define IiTunes_get_Windows(This,iWindowCollection) \ + (This)->lpVtbl -> get_Windows(This,iWindowCollection) + +#define IiTunes_get_SoundVolume(This,volume) \ + (This)->lpVtbl -> get_SoundVolume(This,volume) + +#define IiTunes_put_SoundVolume(This,volume) \ + (This)->lpVtbl -> put_SoundVolume(This,volume) + +#define IiTunes_get_Mute(This,isMuted) \ + (This)->lpVtbl -> get_Mute(This,isMuted) + +#define IiTunes_put_Mute(This,shouldMute) \ + (This)->lpVtbl -> put_Mute(This,shouldMute) + +#define IiTunes_get_PlayerState(This,playerState) \ + (This)->lpVtbl -> get_PlayerState(This,playerState) + +#define IiTunes_get_PlayerPosition(This,playerPos) \ + (This)->lpVtbl -> get_PlayerPosition(This,playerPos) + +#define IiTunes_put_PlayerPosition(This,playerPos) \ + (This)->lpVtbl -> put_PlayerPosition(This,playerPos) + +#define IiTunes_get_CurrentEncoder(This,iEncoder) \ + (This)->lpVtbl -> get_CurrentEncoder(This,iEncoder) + +#define IiTunes_put_CurrentEncoder(This,iEncoder) \ + (This)->lpVtbl -> put_CurrentEncoder(This,iEncoder) + +#define IiTunes_get_VisualsEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_VisualsEnabled(This,isEnabled) + +#define IiTunes_put_VisualsEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_VisualsEnabled(This,shouldEnable) + +#define IiTunes_get_FullScreenVisuals(This,isFullScreen) \ + (This)->lpVtbl -> get_FullScreenVisuals(This,isFullScreen) + +#define IiTunes_put_FullScreenVisuals(This,shouldUseFullScreen) \ + (This)->lpVtbl -> put_FullScreenVisuals(This,shouldUseFullScreen) + +#define IiTunes_get_VisualSize(This,visualSize) \ + (This)->lpVtbl -> get_VisualSize(This,visualSize) + +#define IiTunes_put_VisualSize(This,visualSize) \ + (This)->lpVtbl -> put_VisualSize(This,visualSize) + +#define IiTunes_get_CurrentVisual(This,iVisual) \ + (This)->lpVtbl -> get_CurrentVisual(This,iVisual) + +#define IiTunes_put_CurrentVisual(This,iVisual) \ + (This)->lpVtbl -> put_CurrentVisual(This,iVisual) + +#define IiTunes_get_EQEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_EQEnabled(This,isEnabled) + +#define IiTunes_put_EQEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_EQEnabled(This,shouldEnable) + +#define IiTunes_get_CurrentEQPreset(This,iEQPreset) \ + (This)->lpVtbl -> get_CurrentEQPreset(This,iEQPreset) + +#define IiTunes_put_CurrentEQPreset(This,iEQPreset) \ + (This)->lpVtbl -> put_CurrentEQPreset(This,iEQPreset) + +#define IiTunes_get_CurrentStreamTitle(This,streamTitle) \ + (This)->lpVtbl -> get_CurrentStreamTitle(This,streamTitle) + +#define IiTunes_get_CurrentStreamURL(This,streamURL) \ + (This)->lpVtbl -> get_CurrentStreamURL(This,streamURL) + +#define IiTunes_get_BrowserWindow(This,iBrowserWindow) \ + (This)->lpVtbl -> get_BrowserWindow(This,iBrowserWindow) + +#define IiTunes_get_EQWindow(This,iEQWindow) \ + (This)->lpVtbl -> get_EQWindow(This,iEQWindow) + +#define IiTunes_get_LibrarySource(This,iLibrarySource) \ + (This)->lpVtbl -> get_LibrarySource(This,iLibrarySource) + +#define IiTunes_get_LibraryPlaylist(This,iLibraryPlaylist) \ + (This)->lpVtbl -> get_LibraryPlaylist(This,iLibraryPlaylist) + +#define IiTunes_get_CurrentTrack(This,iTrack) \ + (This)->lpVtbl -> get_CurrentTrack(This,iTrack) + +#define IiTunes_get_CurrentPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> get_CurrentPlaylist(This,iPlaylist) + +#define IiTunes_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IiTunes_get_Version(This,version) \ + (This)->lpVtbl -> get_Version(This,version) + +#define IiTunes_SetOptions(This,options) \ + (This)->lpVtbl -> SetOptions(This,options) + +#define IiTunes_ConvertFile2(This,filePath,iStatus) \ + (This)->lpVtbl -> ConvertFile2(This,filePath,iStatus) + +#define IiTunes_ConvertFiles2(This,filePaths,iStatus) \ + (This)->lpVtbl -> ConvertFiles2(This,filePaths,iStatus) + +#define IiTunes_ConvertTrack2(This,iTrackToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTrack2(This,iTrackToConvert,iStatus) + +#define IiTunes_ConvertTracks2(This,iTracksToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTracks2(This,iTracksToConvert,iStatus) + +#define IiTunes_get_AppCommandMessageProcessingEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_AppCommandMessageProcessingEnabled(This,isEnabled) + +#define IiTunes_put_AppCommandMessageProcessingEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_AppCommandMessageProcessingEnabled(This,shouldEnable) + +#define IiTunes_get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ + (This)->lpVtbl -> get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) + +#define IiTunes_put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ + (This)->lpVtbl -> put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) + +#define IiTunes_CreateEQPreset(This,eqPresetName,iEQPreset) \ + (This)->lpVtbl -> CreateEQPreset(This,eqPresetName,iEQPreset) + +#define IiTunes_CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) + +#define IiTunes_GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) \ + (This)->lpVtbl -> GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) + +#define IiTunes_PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) \ + (This)->lpVtbl -> PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) + +#define IiTunes_get_CanSetShuffle(This,iPlaylist,canSetShuffle) \ + (This)->lpVtbl -> get_CanSetShuffle(This,iPlaylist,canSetShuffle) + +#define IiTunes_get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) \ + (This)->lpVtbl -> get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) + +#define IiTunes_get_ConvertOperationStatus(This,iStatus) \ + (This)->lpVtbl -> get_ConvertOperationStatus(This,iStatus) + +#define IiTunes_SubscribeToPodcast(This,url) \ + (This)->lpVtbl -> SubscribeToPodcast(This,url) + +#define IiTunes_UpdatePodcastFeeds(This) \ + (This)->lpVtbl -> UpdatePodcastFeeds(This) + +#define IiTunes_CreateFolder(This,folderName,iFolder) \ + (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) + +#define IiTunes_CreateFolderInSource(This,folderName,iSource,iFolder) \ + (This)->lpVtbl -> CreateFolderInSource(This,folderName,iSource,iFolder) + +#define IiTunes_get_SoundVolumeControlEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_SoundVolumeControlEnabled(This,isEnabled) + +#define IiTunes_get_LibraryXMLPath(This,filePath) \ + (This)->lpVtbl -> get_LibraryXMLPath(This,filePath) + +#define IiTunes_get_ITObjectPersistentIDHigh(This,iObject,highID) \ + (This)->lpVtbl -> get_ITObjectPersistentIDHigh(This,iObject,highID) + +#define IiTunes_get_ITObjectPersistentIDLow(This,iObject,lowID) \ + (This)->lpVtbl -> get_ITObjectPersistentIDLow(This,iObject,lowID) + +#define IiTunes_GetITObjectPersistentIDs(This,iObject,highID,lowID) \ + (This)->lpVtbl -> GetITObjectPersistentIDs(This,iObject,highID,lowID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_BackTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_BackTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_FastForward_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_FastForward_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_NextTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_NextTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Pause_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Pause_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Play_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Play_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayFile_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IiTunes_PlayFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayPause_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_PlayPause_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PreviousTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_PreviousTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Resume_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Resume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Rewind_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Rewind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Stop_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Stop_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles_Proxy( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CheckVersion_Proxy( + IiTunes * This, + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible); + + +void __RPC_STUB IiTunes_CheckVersion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectByID_Proxy( + IiTunes * This, + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject); + + +void __RPC_STUB IiTunes_GetITObjectByID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylist_Proxy( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_CreatePlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_OpenURL_Proxy( + IiTunes * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IiTunes_OpenURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GotoMusicStoreHomePage_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_GotoMusicStoreHomePage_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdateIPod_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_UpdateIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Authorize_Proxy( + IiTunes * This, + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]); + + +void __RPC_STUB IiTunes_Authorize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Quit_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Quit_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Sources_Proxy( + IiTunes * This, + /* [retval][out] */ IITSourceCollection **iSourceCollection); + + +void __RPC_STUB IiTunes_get_Sources_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Encoders_Proxy( + IiTunes * This, + /* [retval][out] */ IITEncoderCollection **iEncoderCollection); + + +void __RPC_STUB IiTunes_get_Encoders_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQPresets_Proxy( + IiTunes * This, + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); + + +void __RPC_STUB IiTunes_get_EQPresets_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Visuals_Proxy( + IiTunes * This, + /* [retval][out] */ IITVisualCollection **iVisualCollection); + + +void __RPC_STUB IiTunes_get_Visuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Windows_Proxy( + IiTunes * This, + /* [retval][out] */ IITWindowCollection **iWindowCollection); + + +void __RPC_STUB IiTunes_get_Windows_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolume_Proxy( + IiTunes * This, + /* [retval][out] */ long *volume); + + +void __RPC_STUB IiTunes_get_SoundVolume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_SoundVolume_Proxy( + IiTunes * This, + /* [in] */ long volume); + + +void __RPC_STUB IiTunes_put_SoundVolume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Mute_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isMuted); + + +void __RPC_STUB IiTunes_get_Mute_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_Mute_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldMute); + + +void __RPC_STUB IiTunes_put_Mute_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerState_Proxy( + IiTunes * This, + /* [retval][out] */ ITPlayerState *playerState); + + +void __RPC_STUB IiTunes_get_PlayerState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerPosition_Proxy( + IiTunes * This, + /* [retval][out] */ long *playerPos); + + +void __RPC_STUB IiTunes_get_PlayerPosition_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_PlayerPosition_Proxy( + IiTunes * This, + /* [in] */ long playerPos); + + +void __RPC_STUB IiTunes_put_PlayerPosition_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEncoder_Proxy( + IiTunes * This, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IiTunes_get_CurrentEncoder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEncoder_Proxy( + IiTunes * This, + /* [in] */ IITEncoder *iEncoder); + + +void __RPC_STUB IiTunes_put_CurrentEncoder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualsEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_VisualsEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualsEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_VisualsEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_FullScreenVisuals_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isFullScreen); + + +void __RPC_STUB IiTunes_get_FullScreenVisuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_FullScreenVisuals_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldUseFullScreen); + + +void __RPC_STUB IiTunes_put_FullScreenVisuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualSize_Proxy( + IiTunes * This, + /* [retval][out] */ ITVisualSize *visualSize); + + +void __RPC_STUB IiTunes_get_VisualSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualSize_Proxy( + IiTunes * This, + /* [in] */ ITVisualSize visualSize); + + +void __RPC_STUB IiTunes_put_VisualSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentVisual_Proxy( + IiTunes * This, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IiTunes_get_CurrentVisual_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentVisual_Proxy( + IiTunes * This, + /* [in] */ IITVisual *iVisual); + + +void __RPC_STUB IiTunes_put_CurrentVisual_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_EQEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_EQEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_EQEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEQPreset_Proxy( + IiTunes * This, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IiTunes_get_CurrentEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEQPreset_Proxy( + IiTunes * This, + /* [in] */ IITEQPreset *iEQPreset); + + +void __RPC_STUB IiTunes_put_CurrentEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamTitle_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *streamTitle); + + +void __RPC_STUB IiTunes_get_CurrentStreamTitle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamURL_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *streamURL); + + +void __RPC_STUB IiTunes_get_CurrentStreamURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_BrowserWindow_Proxy( + IiTunes * This, + /* [retval][out] */ IITBrowserWindow **iBrowserWindow); + + +void __RPC_STUB IiTunes_get_BrowserWindow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQWindow_Proxy( + IiTunes * This, + /* [retval][out] */ IITWindow **iEQWindow); + + +void __RPC_STUB IiTunes_get_EQWindow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibrarySource_Proxy( + IiTunes * This, + /* [retval][out] */ IITSource **iLibrarySource); + + +void __RPC_STUB IiTunes_get_LibrarySource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryPlaylist_Proxy( + IiTunes * This, + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); + + +void __RPC_STUB IiTunes_get_LibraryPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentTrack_Proxy( + IiTunes * This, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IiTunes_get_CurrentTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentPlaylist_Proxy( + IiTunes * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_get_CurrentPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SelectedTracks_Proxy( + IiTunes * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IiTunes_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Version_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *version); + + +void __RPC_STUB IiTunes_get_Version_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SetOptions_Proxy( + IiTunes * This, + /* [in] */ long options); + + +void __RPC_STUB IiTunes_SetOptions_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile2_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFile2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFiles2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTrack2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTracks2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_AppCommandMessageProcessingEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_AppCommandMessageProcessingEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_AppCommandMessageProcessingEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_AppCommandMessageProcessingEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ForceToForegroundOnDialog_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); + + +void __RPC_STUB IiTunes_get_ForceToForegroundOnDialog_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_ForceToForegroundOnDialog_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); + + +void __RPC_STUB IiTunes_put_ForceToForegroundOnDialog_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateEQPreset_Proxy( + IiTunes * This, + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IiTunes_CreateEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylistInSource_Proxy( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_CreatePlaylistInSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetPlayerButtonsState_Proxy( + IiTunes * This, + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled); + + +void __RPC_STUB IiTunes_GetPlayerButtonsState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayerButtonClicked_Proxy( + IiTunes * This, + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys); + + +void __RPC_STUB IiTunes_PlayerButtonClicked_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetShuffle_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle); + + +void __RPC_STUB IiTunes_get_CanSetShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetSongRepeat_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); + + +void __RPC_STUB IiTunes_get_CanSetSongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ConvertOperationStatus_Proxy( + IiTunes * This, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_get_ConvertOperationStatus_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SubscribeToPodcast_Proxy( + IiTunes * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IiTunes_SubscribeToPodcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdatePodcastFeeds_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_UpdatePodcastFeeds_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolder_Proxy( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IiTunes_CreateFolder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolderInSource_Proxy( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IiTunes_CreateFolderInSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolumeControlEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_SoundVolumeControlEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryXMLPath_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *filePath); + + +void __RPC_STUB IiTunes_get_LibraryXMLPath_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDHigh_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID); + + +void __RPC_STUB IiTunes_get_ITObjectPersistentIDHigh_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDLow_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID); + + +void __RPC_STUB IiTunes_get_ITObjectPersistentIDLow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectPersistentIDs_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID); + + +void __RPC_STUB IiTunes_GetITObjectPersistentIDs_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IiTunes_INTERFACE_DEFINED__ */ + + +#ifndef ___IiTunesEvents_DISPINTERFACE_DEFINED__ +#define ___IiTunesEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface _IiTunesEvents */ +/* [helpstring][uuid] */ + + +EXTERN_C const IID DIID__IiTunesEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5846EB78-317E-4b6f-B0C3-11EE8C8FEEF2") + _IiTunesEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct _IiTunesEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + _IiTunesEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + _IiTunesEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + _IiTunesEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + _IiTunesEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + _IiTunesEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + _IiTunesEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + _IiTunesEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } _IiTunesEventsVtbl; + + interface _IiTunesEvents + { + CONST_VTBL struct _IiTunesEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define _IiTunesEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define _IiTunesEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define _IiTunesEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define _IiTunesEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define _IiTunesEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define _IiTunesEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define _IiTunesEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* ___IiTunesEvents_DISPINTERFACE_DEFINED__ */ + + +#ifndef ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ +#define ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface _IITConvertOperationStatusEvents */ +/* [helpstring][uuid] */ + + +EXTERN_C const IID DIID__IITConvertOperationStatusEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5C47A705-8E8A-45a1-9EED-71C993F0BF60") + _IITConvertOperationStatusEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct _IITConvertOperationStatusEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + _IITConvertOperationStatusEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + _IITConvertOperationStatusEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + _IITConvertOperationStatusEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + _IITConvertOperationStatusEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + _IITConvertOperationStatusEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + _IITConvertOperationStatusEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + _IITConvertOperationStatusEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } _IITConvertOperationStatusEventsVtbl; + + interface _IITConvertOperationStatusEvents + { + CONST_VTBL struct _IITConvertOperationStatusEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define _IITConvertOperationStatusEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define _IITConvertOperationStatusEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define _IITConvertOperationStatusEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define _IITConvertOperationStatusEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define _IITConvertOperationStatusEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define _IITConvertOperationStatusEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define _IITConvertOperationStatusEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ */ + + +EXTERN_C const CLSID CLSID_iTunesApp; + +#ifdef __cplusplus + +class DECLSPEC_UUID("DC0C2640-1415-4644-875C-6F4D769839BA") +iTunesApp; +#endif + +EXTERN_C const CLSID CLSID_iTunesConvertOperationStatus; + +#ifdef __cplusplus + +class DECLSPEC_UUID("D06596AD-C900-41b2-BC68-1B486450FC56") +iTunesConvertOperationStatus; +#endif + +#ifndef __IITArtwork_INTERFACE_DEFINED__ +#define __IITArtwork_INTERFACE_DEFINED__ + +/* interface IITArtwork */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITArtwork; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D0A6C1F8-BF3D-4cd8-AC47-FE32BDD17257") + IITArtwork : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetArtworkFromFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SaveArtworkToFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( + /* [retval][out] */ ITArtworkFormat *format) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_IsDownloadedArtwork( + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITArtworkVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITArtwork * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITArtwork * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITArtwork * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITArtwork * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITArtwork * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITArtwork * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITArtwork * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITArtwork * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetArtworkFromFile )( + IITArtwork * This, + /* [in] */ BSTR filePath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SaveArtworkToFile )( + IITArtwork * This, + /* [in] */ BSTR filePath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( + IITArtwork * This, + /* [retval][out] */ ITArtworkFormat *format); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsDownloadedArtwork )( + IITArtwork * This, + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITArtwork * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITArtwork * This, + /* [in] */ BSTR description); + + END_INTERFACE + } IITArtworkVtbl; + + interface IITArtwork + { + CONST_VTBL struct IITArtworkVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITArtwork_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITArtwork_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITArtwork_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITArtwork_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITArtwork_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITArtwork_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITArtwork_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITArtwork_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITArtwork_SetArtworkFromFile(This,filePath) \ + (This)->lpVtbl -> SetArtworkFromFile(This,filePath) + +#define IITArtwork_SaveArtworkToFile(This,filePath) \ + (This)->lpVtbl -> SaveArtworkToFile(This,filePath) + +#define IITArtwork_get_Format(This,format) \ + (This)->lpVtbl -> get_Format(This,format) + +#define IITArtwork_get_IsDownloadedArtwork(This,isDownloadedArtwork) \ + (This)->lpVtbl -> get_IsDownloadedArtwork(This,isDownloadedArtwork) + +#define IITArtwork_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITArtwork_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_Delete_Proxy( + IITArtwork * This); + + +void __RPC_STUB IITArtwork_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SetArtworkFromFile_Proxy( + IITArtwork * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IITArtwork_SetArtworkFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SaveArtworkToFile_Proxy( + IITArtwork * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IITArtwork_SaveArtworkToFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Format_Proxy( + IITArtwork * This, + /* [retval][out] */ ITArtworkFormat *format); + + +void __RPC_STUB IITArtwork_get_Format_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_IsDownloadedArtwork_Proxy( + IITArtwork * This, + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); + + +void __RPC_STUB IITArtwork_get_IsDownloadedArtwork_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Description_Proxy( + IITArtwork * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITArtwork_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITArtwork_put_Description_Proxy( + IITArtwork * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITArtwork_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITArtwork_INTERFACE_DEFINED__ */ + + +#ifndef __IITArtworkCollection_INTERFACE_DEFINED__ +#define __IITArtworkCollection_INTERFACE_DEFINED__ + +/* interface IITArtworkCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITArtworkCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BF2742D7-418C-4858-9AF9-2981B062D23E") + IITArtworkCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITArtworkCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITArtworkCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITArtworkCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITArtworkCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITArtworkCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITArtworkCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITArtworkCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITArtworkCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITArtworkCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITArtworkCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITArtworkCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITArtworkCollectionVtbl; + + interface IITArtworkCollection + { + CONST_VTBL struct IITArtworkCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITArtworkCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITArtworkCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITArtworkCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITArtworkCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITArtworkCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITArtworkCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITArtworkCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITArtworkCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITArtworkCollection_get_Item(This,index,iArtwork) \ + (This)->lpVtbl -> get_Item(This,index,iArtwork) + +#define IITArtworkCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Count_Proxy( + IITArtworkCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITArtworkCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Item_Proxy( + IITArtworkCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork); + + +void __RPC_STUB IITArtworkCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get__NewEnum_Proxy( + IITArtworkCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITArtworkCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITArtworkCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITURLTrack_INTERFACE_DEFINED__ +#define __IITURLTrack_INTERFACE_DEFINED__ + +/* interface IITURLTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITURLTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1116E3B5-29FD-4393-A7BD-454E5E327900") + IITURLTrack : public IITTrack + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_URL( + /* [retval][out] */ BSTR *url) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_URL( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( + /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DownloadPodcastEpisode( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( + /* [retval][out] */ BSTR *category) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( + /* [in] */ BSTR category) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( + /* [retval][out] */ BSTR *longDescription) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( + /* [in] */ BSTR longDescription) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITURLTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITURLTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITURLTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITURLTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITURLTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITURLTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITURLTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITURLTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITURLTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITURLTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITURLTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITURLTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITURLTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITURLTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITURLTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITURLTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITURLTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITURLTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITURLTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITURLTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITURLTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITURLTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITURLTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITURLTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITURLTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITURLTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITURLTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITURLTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITURLTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITURLTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITURLTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITURLTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITURLTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITURLTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITURLTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITURLTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITURLTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITURLTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITURLTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITURLTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITURLTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITURLTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITURLTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITURLTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITURLTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITURLTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITURLTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITURLTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITURLTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITURLTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITURLTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITURLTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITURLTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITURLTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITURLTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITURLTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITURLTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITURLTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITURLTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITURLTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITURLTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITURLTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITURLTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITURLTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITURLTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITURLTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITURLTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITURLTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_URL )( + IITURLTrack * This, + /* [retval][out] */ BSTR *url); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_URL )( + IITURLTrack * This, + /* [in] */ BSTR url); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *DownloadPodcastEpisode )( + IITURLTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( + IITURLTrack * This, + /* [retval][out] */ BSTR *category); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( + IITURLTrack * This, + /* [in] */ BSTR category); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITURLTrack * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITURLTrack * This, + /* [in] */ BSTR description); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( + IITURLTrack * This, + /* [retval][out] */ BSTR *longDescription); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( + IITURLTrack * This, + /* [in] */ BSTR longDescription); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITURLTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( + IITURLTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITURLTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITURLTrackVtbl; + + interface IITURLTrack + { + CONST_VTBL struct IITURLTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITURLTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITURLTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITURLTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITURLTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITURLTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITURLTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITURLTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITURLTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITURLTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITURLTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITURLTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITURLTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITURLTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITURLTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITURLTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITURLTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITURLTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITURLTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITURLTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITURLTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITURLTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITURLTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITURLTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITURLTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITURLTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITURLTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITURLTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITURLTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITURLTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITURLTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITURLTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITURLTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITURLTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITURLTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITURLTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITURLTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITURLTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITURLTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITURLTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITURLTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITURLTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITURLTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITURLTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITURLTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITURLTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITURLTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITURLTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITURLTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITURLTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITURLTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITURLTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITURLTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITURLTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITURLTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITURLTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITURLTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITURLTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITURLTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITURLTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITURLTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITURLTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITURLTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITURLTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITURLTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITURLTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITURLTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITURLTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITURLTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITURLTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITURLTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITURLTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITURLTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + + +#define IITURLTrack_get_URL(This,url) \ + (This)->lpVtbl -> get_URL(This,url) + +#define IITURLTrack_put_URL(This,url) \ + (This)->lpVtbl -> put_URL(This,url) + +#define IITURLTrack_get_Podcast(This,isPodcast) \ + (This)->lpVtbl -> get_Podcast(This,isPodcast) + +#define IITURLTrack_UpdatePodcastFeed(This) \ + (This)->lpVtbl -> UpdatePodcastFeed(This) + +#define IITURLTrack_DownloadPodcastEpisode(This) \ + (This)->lpVtbl -> DownloadPodcastEpisode(This) + +#define IITURLTrack_get_Category(This,category) \ + (This)->lpVtbl -> get_Category(This,category) + +#define IITURLTrack_put_Category(This,category) \ + (This)->lpVtbl -> put_Category(This,category) + +#define IITURLTrack_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITURLTrack_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#define IITURLTrack_get_LongDescription(This,longDescription) \ + (This)->lpVtbl -> get_LongDescription(This,longDescription) + +#define IITURLTrack_put_LongDescription(This,longDescription) \ + (This)->lpVtbl -> put_LongDescription(This,longDescription) + +#define IITURLTrack_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#define IITURLTrack_get_AlbumRating(This,rating) \ + (This)->lpVtbl -> get_AlbumRating(This,rating) + +#define IITURLTrack_put_AlbumRating(This,rating) \ + (This)->lpVtbl -> put_AlbumRating(This,rating) + +#define IITURLTrack_get_AlbumRatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) + +#define IITURLTrack_get_RatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_RatingKind(This,ratingKind) + +#define IITURLTrack_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_URL_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *url); + + +void __RPC_STUB IITURLTrack_get_URL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_URL_Proxy( + IITURLTrack * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IITURLTrack_put_URL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Podcast_Proxy( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + +void __RPC_STUB IITURLTrack_get_Podcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_UpdatePodcastFeed_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_UpdatePodcastFeed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_DownloadPodcastEpisode_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_DownloadPodcastEpisode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Category_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *category); + + +void __RPC_STUB IITURLTrack_get_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Category_Proxy( + IITURLTrack * This, + /* [in] */ BSTR category); + + +void __RPC_STUB IITURLTrack_put_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Description_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITURLTrack_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Description_Proxy( + IITURLTrack * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITURLTrack_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_LongDescription_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *longDescription); + + +void __RPC_STUB IITURLTrack_get_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_LongDescription_Proxy( + IITURLTrack * This, + /* [in] */ BSTR longDescription); + + +void __RPC_STUB IITURLTrack_put_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_Reveal_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRating_Proxy( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITURLTrack_get_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_AlbumRating_Proxy( + IITURLTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITURLTrack_put_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRatingKind_Proxy( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITURLTrack_get_AlbumRatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_RatingKind_Proxy( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITURLTrack_get_RatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Playlists_Proxy( + IITURLTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITURLTrack_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITURLTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITAudioCDPlaylist_INTERFACE_DEFINED__ +#define __IITAudioCDPlaylist_INTERFACE_DEFINED__ + +/* interface IITAudioCDPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITAudioCDPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CF496DF3-0FED-4d7d-9BD8-529B6E8A082E") + IITAudioCDPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( + /* [retval][out] */ VARIANT_BOOL *isCompiliation) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( + /* [retval][out] */ long *discCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( + /* [retval][out] */ long *discNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( + /* [retval][out] */ BSTR *genre) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( + /* [retval][out] */ long *year) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITAudioCDPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITAudioCDPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITAudioCDPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITAudioCDPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITAudioCDPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITAudioCDPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITAudioCDPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITAudioCDPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITAudioCDPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITAudioCDPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITAudioCDPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITAudioCDPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITAudioCDPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITAudioCDPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITAudioCDPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITAudioCDPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITAudioCDPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITAudioCDPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITAudioCDPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITAudioCDPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITAudioCDPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isCompiliation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *year); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITAudioCDPlaylist * This); + + END_INTERFACE + } IITAudioCDPlaylistVtbl; + + interface IITAudioCDPlaylist + { + CONST_VTBL struct IITAudioCDPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITAudioCDPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITAudioCDPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITAudioCDPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITAudioCDPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITAudioCDPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITAudioCDPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITAudioCDPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITAudioCDPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITAudioCDPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITAudioCDPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITAudioCDPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITAudioCDPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITAudioCDPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITAudioCDPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITAudioCDPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITAudioCDPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITAudioCDPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITAudioCDPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITAudioCDPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITAudioCDPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITAudioCDPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITAudioCDPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITAudioCDPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITAudioCDPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITAudioCDPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITAudioCDPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITAudioCDPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITAudioCDPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITAudioCDPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITAudioCDPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITAudioCDPlaylist_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITAudioCDPlaylist_get_Compilation(This,isCompiliation) \ + (This)->lpVtbl -> get_Compilation(This,isCompiliation) + +#define IITAudioCDPlaylist_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITAudioCDPlaylist_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITAudioCDPlaylist_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITAudioCDPlaylist_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITAudioCDPlaylist_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITAudioCDPlaylist_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Artist_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITAudioCDPlaylist_get_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Compilation_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isCompiliation); + + +void __RPC_STUB IITAudioCDPlaylist_get_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Composer_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITAudioCDPlaylist_get_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscCount_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discCount); + + +void __RPC_STUB IITAudioCDPlaylist_get_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscNumber_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discNumber); + + +void __RPC_STUB IITAudioCDPlaylist_get_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Genre_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *genre); + + +void __RPC_STUB IITAudioCDPlaylist_get_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Year_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *year); + + +void __RPC_STUB IITAudioCDPlaylist_get_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_Reveal_Proxy( + IITAudioCDPlaylist * This); + + +void __RPC_STUB IITAudioCDPlaylist_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITAudioCDPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylistCollection_INTERFACE_DEFINED__ +#define __IITPlaylistCollection_INTERFACE_DEFINED__ + +/* interface IITPlaylistCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylistCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FF194254-909D-4437-9C50-3AAC2AE6305C") + IITPlaylistCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylistCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylistCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylistCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylistCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylistCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylistCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylistCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITPlaylistCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITPlaylistCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITPlaylistCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITPlaylistCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITPlaylistCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist); + + END_INTERFACE + } IITPlaylistCollectionVtbl; + + interface IITPlaylistCollection + { + CONST_VTBL struct IITPlaylistCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylistCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylistCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylistCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylistCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylistCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylistCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylistCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylistCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITPlaylistCollection_get_Item(This,index,iPlaylist) \ + (This)->lpVtbl -> get_Item(This,index,iPlaylist) + +#define IITPlaylistCollection_get_ItemByName(This,name,iPlaylist) \ + (This)->lpVtbl -> get_ItemByName(This,name,iPlaylist) + +#define IITPlaylistCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITPlaylistCollection_get_ItemByPersistentID(This,highID,lowID,iPlaylist) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Count_Proxy( + IITPlaylistCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITPlaylistCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Item_Proxy( + IITPlaylistCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByName_Proxy( + IITPlaylistCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get__NewEnum_Proxy( + IITPlaylistCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITPlaylistCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByPersistentID_Proxy( + IITPlaylistCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylistCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITIPodSource_INTERFACE_DEFINED__ +#define __IITIPodSource_INTERFACE_DEFINED__ + +/* interface IITIPodSource */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITIPodSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CF4D8ACE-1720-4fb9-B0AE-9877249E89B0") + IITIPodSource : public IITSource + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE EjectIPod( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoftwareVersion( + /* [retval][out] */ BSTR *softwareVersion) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITIPodSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITIPodSource * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITIPodSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITIPodSource * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITIPodSource * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITIPodSource * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITIPodSource * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITIPodSource * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITIPodSource * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITIPodSource * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITIPodSource * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITIPodSource * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITIPodSource * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITIPodSource * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITIPodSource * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITIPodSource * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITIPodSource * This, + /* [retval][out] */ ITSourceKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( + IITIPodSource * This, + /* [retval][out] */ double *capacity); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( + IITIPodSource * This, + /* [retval][out] */ double *freespace); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITIPodSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( + IITIPodSource * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *EjectIPod )( + IITIPodSource * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoftwareVersion )( + IITIPodSource * This, + /* [retval][out] */ BSTR *softwareVersion); + + END_INTERFACE + } IITIPodSourceVtbl; + + interface IITIPodSource + { + CONST_VTBL struct IITIPodSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITIPodSource_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITIPodSource_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITIPodSource_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITIPodSource_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITIPodSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITIPodSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITIPodSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITIPodSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITIPodSource_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITIPodSource_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITIPodSource_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITIPodSource_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITIPodSource_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITIPodSource_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITIPodSource_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITIPodSource_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITIPodSource_get_Capacity(This,capacity) \ + (This)->lpVtbl -> get_Capacity(This,capacity) + +#define IITIPodSource_get_FreeSpace(This,freespace) \ + (This)->lpVtbl -> get_FreeSpace(This,freespace) + +#define IITIPodSource_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + + +#define IITIPodSource_UpdateIPod(This) \ + (This)->lpVtbl -> UpdateIPod(This) + +#define IITIPodSource_EjectIPod(This) \ + (This)->lpVtbl -> EjectIPod(This) + +#define IITIPodSource_get_SoftwareVersion(This,softwareVersion) \ + (This)->lpVtbl -> get_SoftwareVersion(This,softwareVersion) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_UpdateIPod_Proxy( + IITIPodSource * This); + + +void __RPC_STUB IITIPodSource_UpdateIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_EjectIPod_Proxy( + IITIPodSource * This); + + +void __RPC_STUB IITIPodSource_EjectIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITIPodSource_get_SoftwareVersion_Proxy( + IITIPodSource * This, + /* [retval][out] */ BSTR *softwareVersion); + + +void __RPC_STUB IITIPodSource_get_SoftwareVersion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITIPodSource_INTERFACE_DEFINED__ */ + + +#ifndef __IITFileOrCDTrack_INTERFACE_DEFINED__ +#define __IITFileOrCDTrack_INTERFACE_DEFINED__ + +/* interface IITFileOrCDTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITFileOrCDTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("00D7FE99-7868-4cc7-AD9E-ACFD70D09566") + IITFileOrCDTrack : public IITTrack + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Location( + /* [retval][out] */ BSTR *location) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateInfoFromFile( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( + /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RememberBookmark( + /* [retval][out] */ VARIANT_BOOL *rememberBookmark) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_RememberBookmark( + /* [in] */ VARIANT_BOOL shouldRememberBookmark) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ExcludeFromShuffle( + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ExcludeFromShuffle( + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Lyrics( + /* [retval][out] */ BSTR *lyrics) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Lyrics( + /* [in] */ BSTR lyrics) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( + /* [retval][out] */ BSTR *category) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( + /* [in] */ BSTR category) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( + /* [retval][out] */ BSTR *longDescription) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( + /* [in] */ BSTR longDescription) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BookmarkTime( + /* [retval][out] */ long *bookmarkTime) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BookmarkTime( + /* [in] */ long bookmarkTime) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VideoKind( + /* [retval][out] */ ITVideoKind *videoKind) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VideoKind( + /* [in] */ ITVideoKind videoKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedCount( + /* [retval][out] */ long *skippedCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedCount( + /* [in] */ long skippedCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedDate( + /* [retval][out] */ DATE *skippedDate) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedDate( + /* [in] */ DATE skippedDate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PartOfGaplessAlbum( + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PartOfGaplessAlbum( + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumArtist( + /* [retval][out] */ BSTR *albumArtist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumArtist( + /* [in] */ BSTR albumArtist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Show( + /* [retval][out] */ BSTR *showName) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Show( + /* [in] */ BSTR showName) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SeasonNumber( + /* [retval][out] */ long *seasonNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SeasonNumber( + /* [in] */ long seasonNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeID( + /* [retval][out] */ BSTR *episodeID) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeID( + /* [in] */ BSTR episodeID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeNumber( + /* [retval][out] */ long *episodeNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeNumber( + /* [in] */ long episodeNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64High( + /* [retval][out] */ long *sizeHigh) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64Low( + /* [retval][out] */ long *sizeLow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Unplayed( + /* [retval][out] */ VARIANT_BOOL *isUnplayed) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Unplayed( + /* [in] */ VARIANT_BOOL shouldBeUnplayed) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbum( + /* [retval][out] */ BSTR *album) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbum( + /* [in] */ BSTR album) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbumArtist( + /* [retval][out] */ BSTR *albumArtist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbumArtist( + /* [in] */ BSTR albumArtist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortArtist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortArtist( + /* [in] */ BSTR artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortComposer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortComposer( + /* [in] */ BSTR composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortName( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortName( + /* [in] */ BSTR name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortShow( + /* [retval][out] */ BSTR *showName) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortShow( + /* [in] */ BSTR showName) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITFileOrCDTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITFileOrCDTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITFileOrCDTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITFileOrCDTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITFileOrCDTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITFileOrCDTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITFileOrCDTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITFileOrCDTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITFileOrCDTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITFileOrCDTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITFileOrCDTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITFileOrCDTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITFileOrCDTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITFileOrCDTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITFileOrCDTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITFileOrCDTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITFileOrCDTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITFileOrCDTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITFileOrCDTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITFileOrCDTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITFileOrCDTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITFileOrCDTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITFileOrCDTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITFileOrCDTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITFileOrCDTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITFileOrCDTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITFileOrCDTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Location )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *location); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateInfoFromFile )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RememberBookmark )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *rememberBookmark); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_RememberBookmark )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldRememberBookmark); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ExcludeFromShuffle )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ExcludeFromShuffle )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Lyrics )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *lyrics); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Lyrics )( + IITFileOrCDTrack * This, + /* [in] */ BSTR lyrics); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *category); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( + IITFileOrCDTrack * This, + /* [in] */ BSTR category); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITFileOrCDTrack * This, + /* [in] */ BSTR description); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *longDescription); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( + IITFileOrCDTrack * This, + /* [in] */ BSTR longDescription); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BookmarkTime )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bookmarkTime); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BookmarkTime )( + IITFileOrCDTrack * This, + /* [in] */ long bookmarkTime); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VideoKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITVideoKind *videoKind); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VideoKind )( + IITFileOrCDTrack * This, + /* [in] */ ITVideoKind videoKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *skippedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedCount )( + IITFileOrCDTrack * This, + /* [in] */ long skippedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *skippedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedDate )( + IITFileOrCDTrack * This, + /* [in] */ DATE skippedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PartOfGaplessAlbum )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PartOfGaplessAlbum )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Show )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Show )( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SeasonNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *seasonNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SeasonNumber )( + IITFileOrCDTrack * This, + /* [in] */ long seasonNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeID )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *episodeID); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeID )( + IITFileOrCDTrack * This, + /* [in] */ BSTR episodeID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *episodeNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeNumber )( + IITFileOrCDTrack * This, + /* [in] */ long episodeNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64High )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeHigh); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64Low )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeLow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Unplayed )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isUnplayed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Unplayed )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeUnplayed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbum )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbum )( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbumArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbumArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortComposer )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortComposer )( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortName )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortName )( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortShow )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortShow )( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITFileOrCDTrackVtbl; + + interface IITFileOrCDTrack + { + CONST_VTBL struct IITFileOrCDTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITFileOrCDTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITFileOrCDTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITFileOrCDTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITFileOrCDTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITFileOrCDTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITFileOrCDTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITFileOrCDTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITFileOrCDTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITFileOrCDTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITFileOrCDTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITFileOrCDTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITFileOrCDTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITFileOrCDTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITFileOrCDTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITFileOrCDTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITFileOrCDTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITFileOrCDTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITFileOrCDTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITFileOrCDTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITFileOrCDTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITFileOrCDTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITFileOrCDTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITFileOrCDTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITFileOrCDTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITFileOrCDTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITFileOrCDTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITFileOrCDTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITFileOrCDTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITFileOrCDTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITFileOrCDTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITFileOrCDTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITFileOrCDTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITFileOrCDTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITFileOrCDTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITFileOrCDTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITFileOrCDTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITFileOrCDTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITFileOrCDTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITFileOrCDTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITFileOrCDTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITFileOrCDTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITFileOrCDTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITFileOrCDTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITFileOrCDTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITFileOrCDTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITFileOrCDTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITFileOrCDTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITFileOrCDTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITFileOrCDTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITFileOrCDTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITFileOrCDTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITFileOrCDTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITFileOrCDTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITFileOrCDTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITFileOrCDTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITFileOrCDTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITFileOrCDTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITFileOrCDTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITFileOrCDTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITFileOrCDTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITFileOrCDTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITFileOrCDTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITFileOrCDTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITFileOrCDTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITFileOrCDTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITFileOrCDTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITFileOrCDTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITFileOrCDTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITFileOrCDTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITFileOrCDTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITFileOrCDTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITFileOrCDTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + + +#define IITFileOrCDTrack_get_Location(This,location) \ + (This)->lpVtbl -> get_Location(This,location) + +#define IITFileOrCDTrack_UpdateInfoFromFile(This) \ + (This)->lpVtbl -> UpdateInfoFromFile(This) + +#define IITFileOrCDTrack_get_Podcast(This,isPodcast) \ + (This)->lpVtbl -> get_Podcast(This,isPodcast) + +#define IITFileOrCDTrack_UpdatePodcastFeed(This) \ + (This)->lpVtbl -> UpdatePodcastFeed(This) + +#define IITFileOrCDTrack_get_RememberBookmark(This,rememberBookmark) \ + (This)->lpVtbl -> get_RememberBookmark(This,rememberBookmark) + +#define IITFileOrCDTrack_put_RememberBookmark(This,shouldRememberBookmark) \ + (This)->lpVtbl -> put_RememberBookmark(This,shouldRememberBookmark) + +#define IITFileOrCDTrack_get_ExcludeFromShuffle(This,excludeFromShuffle) \ + (This)->lpVtbl -> get_ExcludeFromShuffle(This,excludeFromShuffle) + +#define IITFileOrCDTrack_put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) \ + (This)->lpVtbl -> put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) + +#define IITFileOrCDTrack_get_Lyrics(This,lyrics) \ + (This)->lpVtbl -> get_Lyrics(This,lyrics) + +#define IITFileOrCDTrack_put_Lyrics(This,lyrics) \ + (This)->lpVtbl -> put_Lyrics(This,lyrics) + +#define IITFileOrCDTrack_get_Category(This,category) \ + (This)->lpVtbl -> get_Category(This,category) + +#define IITFileOrCDTrack_put_Category(This,category) \ + (This)->lpVtbl -> put_Category(This,category) + +#define IITFileOrCDTrack_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITFileOrCDTrack_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#define IITFileOrCDTrack_get_LongDescription(This,longDescription) \ + (This)->lpVtbl -> get_LongDescription(This,longDescription) + +#define IITFileOrCDTrack_put_LongDescription(This,longDescription) \ + (This)->lpVtbl -> put_LongDescription(This,longDescription) + +#define IITFileOrCDTrack_get_BookmarkTime(This,bookmarkTime) \ + (This)->lpVtbl -> get_BookmarkTime(This,bookmarkTime) + +#define IITFileOrCDTrack_put_BookmarkTime(This,bookmarkTime) \ + (This)->lpVtbl -> put_BookmarkTime(This,bookmarkTime) + +#define IITFileOrCDTrack_get_VideoKind(This,videoKind) \ + (This)->lpVtbl -> get_VideoKind(This,videoKind) + +#define IITFileOrCDTrack_put_VideoKind(This,videoKind) \ + (This)->lpVtbl -> put_VideoKind(This,videoKind) + +#define IITFileOrCDTrack_get_SkippedCount(This,skippedCount) \ + (This)->lpVtbl -> get_SkippedCount(This,skippedCount) + +#define IITFileOrCDTrack_put_SkippedCount(This,skippedCount) \ + (This)->lpVtbl -> put_SkippedCount(This,skippedCount) + +#define IITFileOrCDTrack_get_SkippedDate(This,skippedDate) \ + (This)->lpVtbl -> get_SkippedDate(This,skippedDate) + +#define IITFileOrCDTrack_put_SkippedDate(This,skippedDate) \ + (This)->lpVtbl -> put_SkippedDate(This,skippedDate) + +#define IITFileOrCDTrack_get_PartOfGaplessAlbum(This,partOfGaplessAlbum) \ + (This)->lpVtbl -> get_PartOfGaplessAlbum(This,partOfGaplessAlbum) + +#define IITFileOrCDTrack_put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) \ + (This)->lpVtbl -> put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) + +#define IITFileOrCDTrack_get_AlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> get_AlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_put_AlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> put_AlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_get_Show(This,showName) \ + (This)->lpVtbl -> get_Show(This,showName) + +#define IITFileOrCDTrack_put_Show(This,showName) \ + (This)->lpVtbl -> put_Show(This,showName) + +#define IITFileOrCDTrack_get_SeasonNumber(This,seasonNumber) \ + (This)->lpVtbl -> get_SeasonNumber(This,seasonNumber) + +#define IITFileOrCDTrack_put_SeasonNumber(This,seasonNumber) \ + (This)->lpVtbl -> put_SeasonNumber(This,seasonNumber) + +#define IITFileOrCDTrack_get_EpisodeID(This,episodeID) \ + (This)->lpVtbl -> get_EpisodeID(This,episodeID) + +#define IITFileOrCDTrack_put_EpisodeID(This,episodeID) \ + (This)->lpVtbl -> put_EpisodeID(This,episodeID) + +#define IITFileOrCDTrack_get_EpisodeNumber(This,episodeNumber) \ + (This)->lpVtbl -> get_EpisodeNumber(This,episodeNumber) + +#define IITFileOrCDTrack_put_EpisodeNumber(This,episodeNumber) \ + (This)->lpVtbl -> put_EpisodeNumber(This,episodeNumber) + +#define IITFileOrCDTrack_get_Size64High(This,sizeHigh) \ + (This)->lpVtbl -> get_Size64High(This,sizeHigh) + +#define IITFileOrCDTrack_get_Size64Low(This,sizeLow) \ + (This)->lpVtbl -> get_Size64Low(This,sizeLow) + +#define IITFileOrCDTrack_get_Unplayed(This,isUnplayed) \ + (This)->lpVtbl -> get_Unplayed(This,isUnplayed) + +#define IITFileOrCDTrack_put_Unplayed(This,shouldBeUnplayed) \ + (This)->lpVtbl -> put_Unplayed(This,shouldBeUnplayed) + +#define IITFileOrCDTrack_get_SortAlbum(This,album) \ + (This)->lpVtbl -> get_SortAlbum(This,album) + +#define IITFileOrCDTrack_put_SortAlbum(This,album) \ + (This)->lpVtbl -> put_SortAlbum(This,album) + +#define IITFileOrCDTrack_get_SortAlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> get_SortAlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_put_SortAlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> put_SortAlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_get_SortArtist(This,artist) \ + (This)->lpVtbl -> get_SortArtist(This,artist) + +#define IITFileOrCDTrack_put_SortArtist(This,artist) \ + (This)->lpVtbl -> put_SortArtist(This,artist) + +#define IITFileOrCDTrack_get_SortComposer(This,composer) \ + (This)->lpVtbl -> get_SortComposer(This,composer) + +#define IITFileOrCDTrack_put_SortComposer(This,composer) \ + (This)->lpVtbl -> put_SortComposer(This,composer) + +#define IITFileOrCDTrack_get_SortName(This,name) \ + (This)->lpVtbl -> get_SortName(This,name) + +#define IITFileOrCDTrack_put_SortName(This,name) \ + (This)->lpVtbl -> put_SortName(This,name) + +#define IITFileOrCDTrack_get_SortShow(This,showName) \ + (This)->lpVtbl -> get_SortShow(This,showName) + +#define IITFileOrCDTrack_put_SortShow(This,showName) \ + (This)->lpVtbl -> put_SortShow(This,showName) + +#define IITFileOrCDTrack_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#define IITFileOrCDTrack_get_AlbumRating(This,rating) \ + (This)->lpVtbl -> get_AlbumRating(This,rating) + +#define IITFileOrCDTrack_put_AlbumRating(This,rating) \ + (This)->lpVtbl -> put_AlbumRating(This,rating) + +#define IITFileOrCDTrack_get_AlbumRatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) + +#define IITFileOrCDTrack_get_RatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_RatingKind(This,ratingKind) + +#define IITFileOrCDTrack_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Location_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *location); + + +void __RPC_STUB IITFileOrCDTrack_get_Location_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdateInfoFromFile_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_UpdateInfoFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Podcast_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + +void __RPC_STUB IITFileOrCDTrack_get_Podcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdatePodcastFeed_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_UpdatePodcastFeed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RememberBookmark_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *rememberBookmark); + + +void __RPC_STUB IITFileOrCDTrack_get_RememberBookmark_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_RememberBookmark_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldRememberBookmark); + + +void __RPC_STUB IITFileOrCDTrack_put_RememberBookmark_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_ExcludeFromShuffle_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); + + +void __RPC_STUB IITFileOrCDTrack_get_ExcludeFromShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_ExcludeFromShuffle_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); + + +void __RPC_STUB IITFileOrCDTrack_put_ExcludeFromShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Lyrics_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *lyrics); + + +void __RPC_STUB IITFileOrCDTrack_get_Lyrics_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Lyrics_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR lyrics); + + +void __RPC_STUB IITFileOrCDTrack_put_Lyrics_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Category_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *category); + + +void __RPC_STUB IITFileOrCDTrack_get_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Category_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR category); + + +void __RPC_STUB IITFileOrCDTrack_put_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Description_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITFileOrCDTrack_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Description_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITFileOrCDTrack_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_LongDescription_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *longDescription); + + +void __RPC_STUB IITFileOrCDTrack_get_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_LongDescription_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR longDescription); + + +void __RPC_STUB IITFileOrCDTrack_put_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_BookmarkTime_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bookmarkTime); + + +void __RPC_STUB IITFileOrCDTrack_get_BookmarkTime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_BookmarkTime_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long bookmarkTime); + + +void __RPC_STUB IITFileOrCDTrack_put_BookmarkTime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_VideoKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITVideoKind *videoKind); + + +void __RPC_STUB IITFileOrCDTrack_get_VideoKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_VideoKind_Proxy( + IITFileOrCDTrack * This, + /* [in] */ ITVideoKind videoKind); + + +void __RPC_STUB IITFileOrCDTrack_put_VideoKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedCount_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *skippedCount); + + +void __RPC_STUB IITFileOrCDTrack_get_SkippedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedCount_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long skippedCount); + + +void __RPC_STUB IITFileOrCDTrack_put_SkippedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedDate_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *skippedDate); + + +void __RPC_STUB IITFileOrCDTrack_get_SkippedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedDate_Proxy( + IITFileOrCDTrack * This, + /* [in] */ DATE skippedDate); + + +void __RPC_STUB IITFileOrCDTrack_put_SkippedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_PartOfGaplessAlbum_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); + + +void __RPC_STUB IITFileOrCDTrack_get_PartOfGaplessAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_PartOfGaplessAlbum_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); + + +void __RPC_STUB IITFileOrCDTrack_put_PartOfGaplessAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_put_AlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Show_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + +void __RPC_STUB IITFileOrCDTrack_get_Show_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Show_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + +void __RPC_STUB IITFileOrCDTrack_put_Show_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SeasonNumber_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *seasonNumber); + + +void __RPC_STUB IITFileOrCDTrack_get_SeasonNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SeasonNumber_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long seasonNumber); + + +void __RPC_STUB IITFileOrCDTrack_put_SeasonNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeID_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *episodeID); + + +void __RPC_STUB IITFileOrCDTrack_get_EpisodeID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeID_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR episodeID); + + +void __RPC_STUB IITFileOrCDTrack_put_EpisodeID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeNumber_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *episodeNumber); + + +void __RPC_STUB IITFileOrCDTrack_get_EpisodeNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeNumber_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long episodeNumber); + + +void __RPC_STUB IITFileOrCDTrack_put_EpisodeNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64High_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeHigh); + + +void __RPC_STUB IITFileOrCDTrack_get_Size64High_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64Low_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeLow); + + +void __RPC_STUB IITFileOrCDTrack_get_Size64Low_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Unplayed_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isUnplayed); + + +void __RPC_STUB IITFileOrCDTrack_get_Unplayed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Unplayed_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeUnplayed); + + +void __RPC_STUB IITFileOrCDTrack_put_Unplayed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbum_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + +void __RPC_STUB IITFileOrCDTrack_get_SortAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbum_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + +void __RPC_STUB IITFileOrCDTrack_put_SortAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_get_SortAlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_put_SortAlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITFileOrCDTrack_get_SortArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + +void __RPC_STUB IITFileOrCDTrack_put_SortArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortComposer_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITFileOrCDTrack_get_SortComposer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortComposer_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + +void __RPC_STUB IITFileOrCDTrack_put_SortComposer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortName_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITFileOrCDTrack_get_SortName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortName_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + +void __RPC_STUB IITFileOrCDTrack_put_SortName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortShow_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + +void __RPC_STUB IITFileOrCDTrack_get_SortShow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortShow_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + +void __RPC_STUB IITFileOrCDTrack_put_SortShow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_Reveal_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRating_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumRating_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITFileOrCDTrack_put_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRatingKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumRatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RatingKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITFileOrCDTrack_get_RatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Playlists_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITFileOrCDTrack_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITFileOrCDTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylistWindow_INTERFACE_DEFINED__ +#define __IITPlaylistWindow_INTERFACE_DEFINED__ + +/* interface IITPlaylistWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylistWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("349CBB45-2E5A-4822-8E4A-A75555A186F7") + IITPlaylistWindow : public IITWindow + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylistWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylistWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylistWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylistWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylistWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylistWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylistWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITPlaylistWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITPlaylistWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITPlaylistWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITPlaylistWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITPlaylistWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITPlaylistWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITPlaylistWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITPlaylistWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITPlaylistWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITPlaylistWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITPlaylistWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITPlaylistWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITPlaylistWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITPlaylistWindow * This, + /* [in] */ long height); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IITPlaylistWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITPlaylistWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + END_INTERFACE + } IITPlaylistWindowVtbl; + + interface IITPlaylistWindow + { + CONST_VTBL struct IITPlaylistWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylistWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylistWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylistWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylistWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylistWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylistWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylistWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylistWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITPlaylistWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITPlaylistWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITPlaylistWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITPlaylistWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITPlaylistWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITPlaylistWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITPlaylistWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITPlaylistWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITPlaylistWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITPlaylistWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITPlaylistWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITPlaylistWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITPlaylistWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITPlaylistWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITPlaylistWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITPlaylistWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITPlaylistWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITPlaylistWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITPlaylistWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITPlaylistWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITPlaylistWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITPlaylistWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITPlaylistWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITPlaylistWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + + +#define IITPlaylistWindow_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IITPlaylistWindow_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_SelectedTracks_Proxy( + IITPlaylistWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylistWindow_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_Playlist_Proxy( + IITPlaylistWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistWindow_get_Playlist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylistWindow_INTERFACE_DEFINED__ */ + +#endif /* __iTunesLib_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c b/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c new file mode 100644 index 00000000..9402c13e --- /dev/null +++ b/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c @@ -0,0 +1,175 @@ + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 6.00.0366 */ +/* at Wed Jun 25 17:02:20 2008 + */ +/* Compiler settings for iTunesCOMInterface.idl: + Oicf, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, LIBID_iTunesLib,0x9E93C96F,0xCF0D,0x43f6,0x8B,0xA8,0xB8,0x07,0xA3,0x37,0x07,0x12); + + +MIDL_DEFINE_GUID(IID, IID_IITObject,0x9FAB0E27,0x70D7,0x4e3a,0x99,0x65,0xB0,0xC8,0xB8,0x86,0x9B,0xB6); + + +MIDL_DEFINE_GUID(IID, IID_IITSource,0xAEC1C4D3,0xAEF1,0x4255,0xB8,0x92,0x3E,0x3D,0x13,0xAD,0xFD,0xF9); + + +MIDL_DEFINE_GUID(IID, IID_IITSourceCollection,0x2FF6CE20,0xFF87,0x4183,0xB0,0xB3,0xF3,0x23,0xD0,0x47,0xAF,0x41); + + +MIDL_DEFINE_GUID(IID, IID_IITEncoder,0x1CF95A1C,0x55FE,0x4f45,0xA2,0xD3,0x85,0xAC,0x6C,0x50,0x4A,0x73); + + +MIDL_DEFINE_GUID(IID, IID_IITEncoderCollection,0x8862BCA9,0x168D,0x4549,0xA9,0xD5,0xAD,0xB3,0x5E,0x55,0x3B,0xA6); + + +MIDL_DEFINE_GUID(IID, IID_IITEQPreset,0x5BE75F4F,0x68FA,0x4212,0xAC,0xB7,0xBE,0x44,0xEA,0x56,0x97,0x59); + + +MIDL_DEFINE_GUID(IID, IID_IITEQPresetCollection,0xAEF4D111,0x3331,0x48da,0xB0,0xC2,0xB4,0x68,0xD5,0xD6,0x1D,0x08); + + +MIDL_DEFINE_GUID(IID, IID_IITPlaylist,0x3D5E072F,0x2A77,0x4b17,0x9E,0x73,0xE0,0x3B,0x77,0xCC,0xCC,0xA9); + + +MIDL_DEFINE_GUID(IID, IID_IITOperationStatus,0x206479C9,0xFE32,0x4f9b,0xA1,0x8A,0x47,0x5A,0xC9,0x39,0xB4,0x79); + + +MIDL_DEFINE_GUID(IID, IID_IITConvertOperationStatus,0x7063AAF6,0xABA0,0x493b,0xB4,0xFC,0x92,0x0A,0x9F,0x10,0x58,0x75); + + +MIDL_DEFINE_GUID(IID, IID_IITLibraryPlaylist,0x53AE1704,0x491C,0x4289,0x94,0xA0,0x95,0x88,0x15,0x67,0x5A,0x3D); + + +MIDL_DEFINE_GUID(IID, IID_IITUserPlaylist,0x0A504DED,0xA0B5,0x465a,0x8A,0x94,0x50,0xE2,0x0D,0x7D,0xF6,0x92); + + +MIDL_DEFINE_GUID(IID, IID_IITTrack,0x4CB0915D,0x1E54,0x4727,0xBA,0xF3,0xCE,0x6C,0xC9,0xA2,0x25,0xA1); + + +MIDL_DEFINE_GUID(IID, IID_IITTrackCollection,0x755D76F1,0x6B85,0x4ce4,0x8F,0x5F,0xF8,0x8D,0x97,0x43,0xDC,0xD8); + + +MIDL_DEFINE_GUID(IID, IID_IITVisual,0x340F3315,0xED72,0x4c09,0x9A,0xCF,0x21,0xEB,0x4B,0xDF,0x99,0x31); + + +MIDL_DEFINE_GUID(IID, IID_IITVisualCollection,0x88A4CCDD,0x114F,0x4043,0xB6,0x9B,0x84,0xD4,0xE6,0x27,0x49,0x57); + + +MIDL_DEFINE_GUID(IID, IID_IITWindow,0x370D7BE0,0x3A89,0x4a42,0xB9,0x02,0xC7,0x5F,0xC1,0x38,0xBE,0x09); + + +MIDL_DEFINE_GUID(IID, IID_IITBrowserWindow,0xC999F455,0xC4D5,0x4aa4,0x82,0x77,0xF9,0x97,0x53,0x69,0x99,0x74); + + +MIDL_DEFINE_GUID(IID, IID_IITWindowCollection,0x3D8DE381,0x6C0E,0x481f,0xA8,0x65,0xE2,0x38,0x5F,0x59,0xFA,0x43); + + +MIDL_DEFINE_GUID(IID, IID_IiTunes,0x9DD6680B,0x3EDC,0x40db,0xA7,0x71,0xE6,0xFE,0x48,0x32,0xE3,0x4A); + + +MIDL_DEFINE_GUID(IID, DIID__IiTunesEvents,0x5846EB78,0x317E,0x4b6f,0xB0,0xC3,0x11,0xEE,0x8C,0x8F,0xEE,0xF2); + + +MIDL_DEFINE_GUID(IID, DIID__IITConvertOperationStatusEvents,0x5C47A705,0x8E8A,0x45a1,0x9E,0xED,0x71,0xC9,0x93,0xF0,0xBF,0x60); + + +MIDL_DEFINE_GUID(CLSID, CLSID_iTunesApp,0xDC0C2640,0x1415,0x4644,0x87,0x5C,0x6F,0x4D,0x76,0x98,0x39,0xBA); + + +MIDL_DEFINE_GUID(CLSID, CLSID_iTunesConvertOperationStatus,0xD06596AD,0xC900,0x41b2,0xBC,0x68,0x1B,0x48,0x64,0x50,0xFC,0x56); + + +MIDL_DEFINE_GUID(IID, IID_IITArtwork,0xD0A6C1F8,0xBF3D,0x4cd8,0xAC,0x47,0xFE,0x32,0xBD,0xD1,0x72,0x57); + + +MIDL_DEFINE_GUID(IID, IID_IITArtworkCollection,0xBF2742D7,0x418C,0x4858,0x9A,0xF9,0x29,0x81,0xB0,0x62,0xD2,0x3E); + + +MIDL_DEFINE_GUID(IID, IID_IITURLTrack,0x1116E3B5,0x29FD,0x4393,0xA7,0xBD,0x45,0x4E,0x5E,0x32,0x79,0x00); + + +MIDL_DEFINE_GUID(IID, IID_IITAudioCDPlaylist,0xCF496DF3,0x0FED,0x4d7d,0x9B,0xD8,0x52,0x9B,0x6E,0x8A,0x08,0x2E); + + +MIDL_DEFINE_GUID(IID, IID_IITPlaylistCollection,0xFF194254,0x909D,0x4437,0x9C,0x50,0x3A,0xAC,0x2A,0xE6,0x30,0x5C); + + +MIDL_DEFINE_GUID(IID, IID_IITIPodSource,0xCF4D8ACE,0x1720,0x4fb9,0xB0,0xAE,0x98,0x77,0x24,0x9E,0x89,0xB0); + + +MIDL_DEFINE_GUID(IID, IID_IITFileOrCDTrack,0x00D7FE99,0x7868,0x4cc7,0xAD,0x9E,0xAC,0xFD,0x70,0xD0,0x95,0x66); + + +MIDL_DEFINE_GUID(IID, IID_IITPlaylistWindow,0x349CBB45,0x2E5A,0x4822,0x8E,0x4A,0xA7,0x55,0x55,0xA1,0x86,0xF7); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/Plugins/PluginNowPlaying/StdAfx.cpp b/Plugins/PluginNowPlaying/StdAfx.cpp new file mode 100644 index 00000000..ef9ca8a6 --- /dev/null +++ b/Plugins/PluginNowPlaying/StdAfx.cpp @@ -0,0 +1,19 @@ +/* + Copyright (C) 2010-2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" diff --git a/Plugins/PluginNowPlaying/StdAfx.h b/Plugins/PluginNowPlaying/StdAfx.h new file mode 100644 index 00000000..7220d915 --- /dev/null +++ b/Plugins/PluginNowPlaying/StdAfx.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2010-2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __STDAFX_H__ +#define __STDAFX_H__ + +// WinAPI +#include + +// STL +#include +#include + +// Runtime +#include + +// Rainmeter's exported functions +#include "../../Library/Export.h" + +// TagLib +#include "fileref.h" + +#endif diff --git a/Plugins/PluginNowPlaying/readme.txt b/Plugins/PluginNowPlaying/readme.txt new file mode 100644 index 00000000..993073fa --- /dev/null +++ b/Plugins/PluginNowPlaying/readme.txt @@ -0,0 +1,7 @@ +* iTunes implementation based on + - onlylyric by zlbruce (onlylyric.googlecode.com) + - iTunesPlugin by Elestel (rainmeter.googlecode.com) + +* WMP implementation based on + - onlylyric by zlbruce (onlylyric.googlecode.com) + - Last.fm WMP plugin (www.last.fm) \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/sha2/hmac_sha2.c b/Plugins/PluginNowPlaying/sha2/hmac_sha2.c new file mode 100644 index 00000000..5fbce5c5 --- /dev/null +++ b/Plugins/PluginNowPlaying/sha2/hmac_sha2.c @@ -0,0 +1,544 @@ +/*- + * HMAC-SHA-224/256/384/512 implementation + * Last update: 06/15/2005 + * Issue date: 06/15/2005 + * + * Copyright (C) 2005 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "hmac_sha2.h" + +/* HMAC-SHA-224 functions */ + +void hmac_sha224_init(hmac_sha224_ctx *ctx, unsigned char *key, + unsigned int key_size) +{ + unsigned int fill; + unsigned int num; + + unsigned char *key_used; + unsigned char key_temp[SHA224_DIGEST_SIZE]; + int i; + + if (key_size == SHA224_BLOCK_SIZE) { + key_used = key; + num = SHA224_BLOCK_SIZE; + } else { + if (key_size > SHA224_BLOCK_SIZE){ + key_used = key_temp; + num = SHA224_DIGEST_SIZE; + sha224(key, key_size, key_used); + } else { /* key_size > SHA224_BLOCK_SIZE */ + key_used = key; + num = key_size; + } + fill = SHA224_BLOCK_SIZE - num; + + memset(ctx->block_ipad + num, 0x36, fill); + memset(ctx->block_opad + num, 0x5c, fill); + } + + for (i = 0; i < num; i++) { + ctx->block_ipad[i] = key_used[i] ^ 0x36; + ctx->block_opad[i] = key_used[i] ^ 0x5c; + } + + sha224_init(&ctx->ctx_inside); + sha224_update(&ctx->ctx_inside, ctx->block_ipad, SHA224_BLOCK_SIZE); + + sha224_init(&ctx->ctx_outside); + sha224_update(&ctx->ctx_outside, ctx->block_opad, + SHA224_BLOCK_SIZE); + + /* for hmac_reinit */ + memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside, + sizeof(sha224_ctx)); + memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside, + sizeof(sha224_ctx)); +} + +void hmac_sha224_reinit(hmac_sha224_ctx *ctx) +{ + memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit, + sizeof(sha224_ctx)); + memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit, + sizeof(sha224_ctx)); +} + +void hmac_sha224_update(hmac_sha224_ctx *ctx, unsigned char *message, + unsigned int message_len) +{ + sha224_update(&ctx->ctx_inside, message, message_len); +} + +void hmac_sha224_final(hmac_sha224_ctx *ctx, unsigned char *mac, + unsigned int mac_size) +{ + unsigned char digest_inside[SHA224_DIGEST_SIZE]; + unsigned char mac_temp[SHA224_DIGEST_SIZE]; + + sha224_final(&ctx->ctx_inside, digest_inside); + sha224_update(&ctx->ctx_outside, digest_inside, SHA224_DIGEST_SIZE); + sha224_final(&ctx->ctx_outside, mac_temp); + memcpy(mac, mac_temp, mac_size); +} + +void hmac_sha224(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size) +{ + hmac_sha224_ctx ctx; + + hmac_sha224_init(&ctx, key, key_size); + hmac_sha224_update(&ctx, message, message_len); + hmac_sha224_final(&ctx, mac, mac_size); +} + +/* HMAC-SHA-256 functions */ + +void hmac_sha256_init(hmac_sha256_ctx *ctx, unsigned char *key, + unsigned int key_size) +{ + unsigned int fill; + unsigned int num; + + unsigned char *key_used; + unsigned char key_temp[SHA256_DIGEST_SIZE]; + int i; + + if (key_size == SHA256_BLOCK_SIZE) { + key_used = key; + num = SHA256_BLOCK_SIZE; + } else { + if (key_size > SHA256_BLOCK_SIZE){ + key_used = key_temp; + num = SHA256_DIGEST_SIZE; + sha256(key, key_size, key_used); + } else { /* key_size > SHA256_BLOCK_SIZE */ + key_used = key; + num = key_size; + } + fill = SHA256_BLOCK_SIZE - num; + + memset(ctx->block_ipad + num, 0x36, fill); + memset(ctx->block_opad + num, 0x5c, fill); + } + + for (i = 0; i < num; i++) { + ctx->block_ipad[i] = key_used[i] ^ 0x36; + ctx->block_opad[i] = key_used[i] ^ 0x5c; + } + + sha256_init(&ctx->ctx_inside); + sha256_update(&ctx->ctx_inside, ctx->block_ipad, SHA256_BLOCK_SIZE); + + sha256_init(&ctx->ctx_outside); + sha256_update(&ctx->ctx_outside, ctx->block_opad, + SHA256_BLOCK_SIZE); + + /* for hmac_reinit */ + memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside, + sizeof(sha256_ctx)); + memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside, + sizeof(sha256_ctx)); +} + +void hmac_sha256_reinit(hmac_sha256_ctx *ctx) +{ + memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit, + sizeof(sha256_ctx)); + memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit, + sizeof(sha256_ctx)); +} + +void hmac_sha256_update(hmac_sha256_ctx *ctx, unsigned char *message, + unsigned int message_len) +{ + sha256_update(&ctx->ctx_inside, message, message_len); +} + +void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac, + unsigned int mac_size) +{ + unsigned char digest_inside[SHA256_DIGEST_SIZE]; + unsigned char mac_temp[SHA256_DIGEST_SIZE]; + + sha256_final(&ctx->ctx_inside, digest_inside); + sha256_update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_SIZE); + sha256_final(&ctx->ctx_outside, mac_temp); + memcpy(mac, mac_temp, mac_size); +} + +void hmac_sha256(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size) +{ + hmac_sha256_ctx ctx; + + hmac_sha256_init(&ctx, key, key_size); + hmac_sha256_update(&ctx, message, message_len); + hmac_sha256_final(&ctx, mac, mac_size); +} + +/* HMAC-SHA-384 functions */ + +void hmac_sha384_init(hmac_sha384_ctx *ctx, unsigned char *key, + unsigned int key_size) +{ + unsigned int fill; + unsigned int num; + + unsigned char *key_used; + unsigned char key_temp[SHA384_DIGEST_SIZE]; + int i; + + if (key_size == SHA384_BLOCK_SIZE) { + key_used = key; + num = SHA384_BLOCK_SIZE; + } else { + if (key_size > SHA384_BLOCK_SIZE){ + key_used = key_temp; + num = SHA384_DIGEST_SIZE; + sha384(key, key_size, key_used); + } else { /* key_size > SHA384_BLOCK_SIZE */ + key_used = key; + num = key_size; + } + fill = SHA384_BLOCK_SIZE - num; + + memset(ctx->block_ipad + num, 0x36, fill); + memset(ctx->block_opad + num, 0x5c, fill); + } + + for (i = 0; i < num; i++) { + ctx->block_ipad[i] = key_used[i] ^ 0x36; + ctx->block_opad[i] = key_used[i] ^ 0x5c; + } + + sha384_init(&ctx->ctx_inside); + sha384_update(&ctx->ctx_inside, ctx->block_ipad, SHA384_BLOCK_SIZE); + + sha384_init(&ctx->ctx_outside); + sha384_update(&ctx->ctx_outside, ctx->block_opad, + SHA384_BLOCK_SIZE); + + /* for hmac_reinit */ + memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside, + sizeof(sha384_ctx)); + memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside, + sizeof(sha384_ctx)); +} + +void hmac_sha384_reinit(hmac_sha384_ctx *ctx) +{ + memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit, + sizeof(sha384_ctx)); + memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit, + sizeof(sha384_ctx)); +} + +void hmac_sha384_update(hmac_sha384_ctx *ctx, unsigned char *message, + unsigned int message_len) +{ + sha384_update(&ctx->ctx_inside, message, message_len); +} + +void hmac_sha384_final(hmac_sha384_ctx *ctx, unsigned char *mac, + unsigned int mac_size) +{ + unsigned char digest_inside[SHA384_DIGEST_SIZE]; + unsigned char mac_temp[SHA384_DIGEST_SIZE]; + + sha384_final(&ctx->ctx_inside, digest_inside); + sha384_update(&ctx->ctx_outside, digest_inside, SHA384_DIGEST_SIZE); + sha384_final(&ctx->ctx_outside, mac_temp); + memcpy(mac, mac_temp, mac_size); +} + +void hmac_sha384(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size) +{ + hmac_sha384_ctx ctx; + + hmac_sha384_init(&ctx, key, key_size); + hmac_sha384_update(&ctx, message, message_len); + hmac_sha384_final(&ctx, mac, mac_size); +} + +/* HMAC-SHA-512 functions */ + +void hmac_sha512_init(hmac_sha512_ctx *ctx, unsigned char *key, + unsigned int key_size) +{ + unsigned int fill; + unsigned int num; + + unsigned char *key_used; + unsigned char key_temp[SHA512_DIGEST_SIZE]; + int i; + + if (key_size == SHA512_BLOCK_SIZE) { + key_used = key; + num = SHA512_BLOCK_SIZE; + } else { + if (key_size > SHA512_BLOCK_SIZE){ + key_used = key_temp; + num = SHA512_DIGEST_SIZE; + sha512(key, key_size, key_used); + } else { /* key_size > SHA512_BLOCK_SIZE */ + key_used = key; + num = key_size; + } + fill = SHA512_BLOCK_SIZE - num; + + memset(ctx->block_ipad + num, 0x36, fill); + memset(ctx->block_opad + num, 0x5c, fill); + } + + for (i = 0; i < num; i++) { + ctx->block_ipad[i] = key_used[i] ^ 0x36; + ctx->block_opad[i] = key_used[i] ^ 0x5c; + } + + sha512_init(&ctx->ctx_inside); + sha512_update(&ctx->ctx_inside, ctx->block_ipad, SHA512_BLOCK_SIZE); + + sha512_init(&ctx->ctx_outside); + sha512_update(&ctx->ctx_outside, ctx->block_opad, + SHA512_BLOCK_SIZE); + + /* for hmac_reinit */ + memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside, + sizeof(sha512_ctx)); + memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside, + sizeof(sha512_ctx)); +} + +void hmac_sha512_reinit(hmac_sha512_ctx *ctx) +{ + memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit, + sizeof(sha512_ctx)); + memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit, + sizeof(sha512_ctx)); +} + +void hmac_sha512_update(hmac_sha512_ctx *ctx, unsigned char *message, + unsigned int message_len) +{ + sha512_update(&ctx->ctx_inside, message, message_len); +} + +void hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *mac, + unsigned int mac_size) +{ + unsigned char digest_inside[SHA512_DIGEST_SIZE]; + unsigned char mac_temp[SHA512_DIGEST_SIZE]; + + sha512_final(&ctx->ctx_inside, digest_inside); + sha512_update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_SIZE); + sha512_final(&ctx->ctx_outside, mac_temp); + memcpy(mac, mac_temp, mac_size); +} + +void hmac_sha512(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size) +{ + hmac_sha512_ctx ctx; + + hmac_sha512_init(&ctx, key, key_size); + hmac_sha512_update(&ctx, message, message_len); + hmac_sha512_final(&ctx, mac, mac_size); +} + +#ifdef TEST_VECTORS + +/* IETF Validation tests */ + +#include +#include + +void test(unsigned char *vector, unsigned char *digest, + unsigned int digest_size) +{ + unsigned char output[2 * SHA512_DIGEST_SIZE + 1]; + int i; + + output[2 * digest_size] = '\0'; + + for (i = 0; i < digest_size ; i++) { + sprintf((char *) output + 2*i, "%02x", digest[i]); + } + + printf("H: %s\n", output); + if (strcmp((char *) vector, (char *) output)) { + fprintf(stderr, "Test failed.\n"); + exit(1); + } +} + +int main() +{ + static unsigned char *vectors[] = + { + /* HMAC-SHA-224 */ + "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22", + "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44", + "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea", + "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a", + "0e2aea68a90c8d37c988bcdb9fca6fa8", + "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e", + "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1", + /* HMAC-SHA-256 */ + "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", + "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", + "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", + "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", + "a3b6167473100ee06e0c796c2955552b", + "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", + "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2", + /* HMAC-SHA-384 */ + "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c" + "faea9ea9076ede7f4af152e8b2fa9cb6", + "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e" + "8e2240ca5e69e2c78b3239ecfab21649", + "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b" + "2a5ab39dc13814b94e3ab6e101a34f27", + "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e" + "6801dd23c4a7d679ccf8a386c674cffb", + "3abf34c3503b2a23a46efc619baef897", + "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6" + "0c2ef6ab4030fe8296248df163f44952", + "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5" + "a678cc31e799176d3860e6110c46523e", + /* HMAC-SHA-512 */ + "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde" + "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854", + "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554" + "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737", + "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39" + "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb", + "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db" + "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd", + "415fad6271580a531d4179bc891d87a6", + "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352" + "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598", + "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944" + "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58" + }; + + static unsigned char *messages[] = + { + "Hi There", + "what do ya want for nothing?", + NULL, + NULL, + "Test With Truncation", + "Test Using Larger Than Block-Size Key - Hash Key First", + "This is a test using a larger than block-size key " + "and a larger than block-size data. The key needs" + " to be hashed before being used by the HMAC algorithm." + }; + + unsigned char mac[SHA512_DIGEST_SIZE]; + unsigned char *keys[7]; + unsigned int keys_len[7] = {20, 4, 20, 25, 20, 131, 131}; + unsigned int messages2and3_len = 50; + unsigned int mac_224_size, mac_256_size, mac_384_size, mac_512_size; + int i; + + for (i = 0; i < 7; i++) { + keys[i] = malloc(keys_len[i]); + if (keys[i] == NULL) { + fprintf(stderr, "Can't allocate memory\n"); + return 1; + } + } + + memset(keys[0], 0x0b, keys_len[0]); + strcpy(keys[1], "Jefe"); + memset(keys[2], 0xaa, keys_len[2]); + for (i = 0; i < keys_len[3]; i++) + keys[3][i] = (unsigned char) i + 1; + memset(keys[4], 0x0c, keys_len[4]); + memset(keys[5], 0xaa, keys_len[5]); + memset(keys[6], 0xaa, keys_len[6]); + + messages[2] = malloc(messages2and3_len + 1); + messages[3] = malloc(messages2and3_len + 1); + + if (messages[2] == NULL || messages[3] == NULL) { + fprintf(stderr, "Can't allocate memory\n"); + return 1; + } + + messages[2][messages2and3_len] = '\0'; + messages[3][messages2and3_len] = '\0'; + + memset(messages[2], 0xdd, messages2and3_len); + memset(messages[3], 0xcd, messages2and3_len); + + printf("HMAC-SHA-2 IETF Validation tests\n\n"); + + for (i = 0; i < 7; i++) { + if (i != 4) { + mac_224_size = SHA224_DIGEST_SIZE; + mac_256_size = SHA256_DIGEST_SIZE; + mac_384_size = SHA384_DIGEST_SIZE; + mac_512_size = SHA512_DIGEST_SIZE; + } else { + mac_224_size = 128 / 8; mac_256_size = 128 / 8; + mac_384_size = 128 / 8; mac_512_size = 128 / 8; + } + + printf("Test %d:\n", i + 1); + + hmac_sha224(keys[i], keys_len[i], messages[i], strlen(messages[i]), + mac, mac_224_size); + test(vectors[i], mac, mac_224_size ); + hmac_sha256(keys[i], keys_len[i], messages[i], strlen(messages[i]), + mac, mac_256_size); + test(vectors[7 + i], mac, mac_256_size); + hmac_sha384(keys[i], keys_len[i], messages[i], strlen(messages[i]), + mac, mac_384_size); + test(vectors[14 + i], mac, mac_384_size); + hmac_sha512(keys[i], keys_len[i], messages[i], strlen(messages[i]), + mac, mac_512_size); + test(vectors[21 + i], mac, mac_512_size); + } + + printf("All tests passed.\n"); + + return 0; +} + +#endif /* TEST_VECTORS */ + diff --git a/Plugins/PluginNowPlaying/sha2/hmac_sha2.h b/Plugins/PluginNowPlaying/sha2/hmac_sha2.h new file mode 100644 index 00000000..d1e2d3c2 --- /dev/null +++ b/Plugins/PluginNowPlaying/sha2/hmac_sha2.h @@ -0,0 +1,140 @@ +/*- + * HMAC-SHA-224/256/384/512 implementation + * Last update: 06/15/2005 + * Issue date: 06/15/2005 + * + * Copyright (C) 2005 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _HMAC_SHA2_H +#define _HMAC_SHA2_H + +#include "sha2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + sha224_ctx ctx_inside; + sha224_ctx ctx_outside; + + /* for hmac_reinit */ + sha224_ctx ctx_inside_reinit; + sha224_ctx ctx_outside_reinit; + + unsigned char block_ipad[SHA224_BLOCK_SIZE]; + unsigned char block_opad[SHA224_BLOCK_SIZE]; +} hmac_sha224_ctx; + +typedef struct { + sha256_ctx ctx_inside; + sha256_ctx ctx_outside; + + /* for hmac_reinit */ + sha256_ctx ctx_inside_reinit; + sha256_ctx ctx_outside_reinit; + + unsigned char block_ipad[SHA256_BLOCK_SIZE]; + unsigned char block_opad[SHA256_BLOCK_SIZE]; +} hmac_sha256_ctx; + +typedef struct { + sha384_ctx ctx_inside; + sha384_ctx ctx_outside; + + /* for hmac_reinit */ + sha384_ctx ctx_inside_reinit; + sha384_ctx ctx_outside_reinit; + + unsigned char block_ipad[SHA384_BLOCK_SIZE]; + unsigned char block_opad[SHA384_BLOCK_SIZE]; +} hmac_sha384_ctx; + +typedef struct { + sha512_ctx ctx_inside; + sha512_ctx ctx_outside; + + /* for hmac_reinit */ + sha512_ctx ctx_inside_reinit; + sha512_ctx ctx_outside_reinit; + + unsigned char block_ipad[SHA512_BLOCK_SIZE]; + unsigned char block_opad[SHA512_BLOCK_SIZE]; +} hmac_sha512_ctx; + +void hmac_sha224_init(hmac_sha224_ctx *ctx, unsigned char *key, + unsigned int key_size); +void hmac_sha224_reinit(hmac_sha224_ctx *ctx); +void hmac_sha224_update(hmac_sha224_ctx *ctx, unsigned char *message, + unsigned int message_len); +void hmac_sha224_final(hmac_sha224_ctx *ctx, unsigned char *mac, + unsigned int mac_size); +void hmac_sha224(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size); + +void hmac_sha256_init(hmac_sha256_ctx *ctx, unsigned char *key, + unsigned int key_size); +void hmac_sha256_reinit(hmac_sha256_ctx *ctx); +void hmac_sha256_update(hmac_sha256_ctx *ctx, unsigned char *message, + unsigned int message_len); +void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac, + unsigned int mac_size); +void hmac_sha256(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size); + +void hmac_sha384_init(hmac_sha384_ctx *ctx, unsigned char *key, + unsigned int key_size); +void hmac_sha384_reinit(hmac_sha384_ctx *ctx); +void hmac_sha384_update(hmac_sha384_ctx *ctx, unsigned char *message, + unsigned int message_len); +void hmac_sha384_final(hmac_sha384_ctx *ctx, unsigned char *mac, + unsigned int mac_size); +void hmac_sha384(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size); + +void hmac_sha512_init(hmac_sha512_ctx *ctx, unsigned char *key, + unsigned int key_size); +void hmac_sha512_reinit(hmac_sha512_ctx *ctx); +void hmac_sha512_update(hmac_sha512_ctx *ctx, unsigned char *message, + unsigned int message_len); +void hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *mac, + unsigned int mac_size); +void hmac_sha512(unsigned char *key, unsigned int key_size, + unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size); + +#ifdef __cplusplus +} +#endif + +#endif /* ! _HMAC_SHA2_H */ + diff --git a/Plugins/PluginNowPlaying/sha2/sha2.c b/Plugins/PluginNowPlaying/sha2/sha2.c new file mode 100644 index 00000000..a8e044de --- /dev/null +++ b/Plugins/PluginNowPlaying/sha2/sha2.c @@ -0,0 +1,950 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#define UNROLL_LOOPS /* Enable loops unrolling */ +#endif + +#include + +#include "sha2.h" + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) +#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) + +#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) +#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) +#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7)) +#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6)) + +#define UNPACK32(x, str) \ +{ \ + *((str) + 3) = (uint8) ((x) ); \ + *((str) + 2) = (uint8) ((x) >> 8); \ + *((str) + 1) = (uint8) ((x) >> 16); \ + *((str) + 0) = (uint8) ((x) >> 24); \ +} + +#define PACK32(str, x) \ +{ \ + *(x) = ((uint32) *((str) + 3) ) \ + | ((uint32) *((str) + 2) << 8) \ + | ((uint32) *((str) + 1) << 16) \ + | ((uint32) *((str) + 0) << 24); \ +} + +#define UNPACK64(x, str) \ +{ \ + *((str) + 7) = (uint8) ((x) ); \ + *((str) + 6) = (uint8) ((x) >> 8); \ + *((str) + 5) = (uint8) ((x) >> 16); \ + *((str) + 4) = (uint8) ((x) >> 24); \ + *((str) + 3) = (uint8) ((x) >> 32); \ + *((str) + 2) = (uint8) ((x) >> 40); \ + *((str) + 1) = (uint8) ((x) >> 48); \ + *((str) + 0) = (uint8) ((x) >> 56); \ +} + +#define PACK64(str, x) \ +{ \ + *(x) = ((uint64) *((str) + 7) ) \ + | ((uint64) *((str) + 6) << 8) \ + | ((uint64) *((str) + 5) << 16) \ + | ((uint64) *((str) + 4) << 24) \ + | ((uint64) *((str) + 3) << 32) \ + | ((uint64) *((str) + 2) << 40) \ + | ((uint64) *((str) + 1) << 48) \ + | ((uint64) *((str) + 0) << 56); \ +} + +/* Macros used for loops unrolling */ + +#define SHA256_SCR(i) \ +{ \ + w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \ + + SHA256_F3(w[i - 15]) + w[i - 16]; \ +} + +#define SHA512_SCR(i) \ +{ \ + w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \ + + SHA512_F3(w[i - 15]) + w[i - 16]; \ +} + +#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \ +{ \ + t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \ + + sha256_k[j] + w[j]; \ + t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ +} + +#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \ +{ \ + t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \ + + sha512_k[j] + w[j]; \ + t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ +} + +uint32 sha224_h0[8] = + {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; + +uint32 sha256_h0[8] = + {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + +uint64 sha384_h0[8] = + {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL}; + +uint64 sha512_h0[8] = + {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}; + +uint32 sha256_k[64] = + {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +uint64 sha512_k[80] = + {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL}; + +/* SHA-256 functions */ + +void sha256_transf(sha256_ctx *ctx, const unsigned char *message, + unsigned int block_nb) +{ + uint32 w[64]; + uint32 wv[8]; + uint32 t1, t2; + const unsigned char *sub_block; + int i; + +#ifndef UNROLL_LOOPS + int j; +#endif + + for (i = 0; i < (int) block_nb; i++) { + sub_block = message + (i << 6); + +#ifndef UNROLL_LOOPS + for (j = 0; j < 16; j++) { + PACK32(&sub_block[j << 2], &w[j]); + } + + for (j = 16; j < 64; j++) { + SHA256_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 64; j++) { + t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + + sha256_k[j] + w[j]; + t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } +#else + PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]); + PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]); + PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]); + PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]); + PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]); + PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]); + PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]); + PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]); + + SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19); + SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23); + SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27); + SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31); + SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35); + SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39); + SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43); + SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47); + SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51); + SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55); + SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59); + SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63); + + wv[0] = ctx->h[0]; wv[1] = ctx->h[1]; + wv[2] = ctx->h[2]; wv[3] = ctx->h[3]; + wv[4] = ctx->h[4]; wv[5] = ctx->h[5]; + wv[6] = ctx->h[6]; wv[7] = ctx->h[7]; + + SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1); + SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3); + SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5); + SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7); + SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9); + SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11); + SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13); + SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15); + SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17); + SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19); + SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21); + SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23); + SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25); + SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27); + SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29); + SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31); + SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33); + SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35); + SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37); + SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39); + SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41); + SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43); + SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45); + SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47); + SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49); + SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51); + SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53); + SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55); + SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57); + SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59); + SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61); + SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63); + + ctx->h[0] += wv[0]; ctx->h[1] += wv[1]; + ctx->h[2] += wv[2]; ctx->h[3] += wv[3]; + ctx->h[4] += wv[4]; ctx->h[5] += wv[5]; + ctx->h[6] += wv[6]; ctx->h[7] += wv[7]; +#endif /* !UNROLL_LOOPS */ + } +} + +void sha256(const unsigned char *message, unsigned int len, unsigned char *digest) +{ + sha256_ctx ctx; + + sha256_init(&ctx); + sha256_update(&ctx, message, len); + sha256_final(&ctx, digest); +} + +void sha256_init(sha256_ctx *ctx) +{ +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha256_h0[i]; + } +#else + ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1]; + ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3]; + ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5]; + ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha256_update(sha256_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const unsigned char *shifted_message; + + tmp_len = SHA256_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA256_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA256_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf(ctx, ctx->block, 1); + sha256_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA256_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void sha256_final(sha256_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) + < (ctx->len % SHA256_BLOCK_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha256_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0 ; i < 8; i++) { + UNPACK32(ctx->h[i], &digest[i << 2]); + } +#else + UNPACK32(ctx->h[0], &digest[ 0]); + UNPACK32(ctx->h[1], &digest[ 4]); + UNPACK32(ctx->h[2], &digest[ 8]); + UNPACK32(ctx->h[3], &digest[12]); + UNPACK32(ctx->h[4], &digest[16]); + UNPACK32(ctx->h[5], &digest[20]); + UNPACK32(ctx->h[6], &digest[24]); + UNPACK32(ctx->h[7], &digest[28]); +#endif /* !UNROLL_LOOPS */ +} + +/* SHA-512 functions */ + +void sha512_transf(sha512_ctx *ctx, const unsigned char *message, + unsigned int block_nb) +{ + uint64 w[80]; + uint64 wv[8]; + uint64 t1, t2; + const unsigned char *sub_block; + int i, j; + + for (i = 0; i < (int) block_nb; i++) { + sub_block = message + (i << 7); + +#ifndef UNROLL_LOOPS + for (j = 0; j < 16; j++) { + PACK64(&sub_block[j << 3], &w[j]); + } + + for (j = 16; j < 80; j++) { + SHA512_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 80; j++) { + t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + + sha512_k[j] + w[j]; + t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } +#else + PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]); + PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]); + PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]); + PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]); + PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]); + PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]); + PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]); + PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]); + + SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19); + SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23); + SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27); + SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31); + SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35); + SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39); + SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43); + SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47); + SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51); + SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55); + SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59); + SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63); + SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67); + SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71); + SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75); + SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79); + + wv[0] = ctx->h[0]; wv[1] = ctx->h[1]; + wv[2] = ctx->h[2]; wv[3] = ctx->h[3]; + wv[4] = ctx->h[4]; wv[5] = ctx->h[5]; + wv[6] = ctx->h[6]; wv[7] = ctx->h[7]; + + j = 0; + + do { + SHA512_EXP(0,1,2,3,4,5,6,7,j); j++; + SHA512_EXP(7,0,1,2,3,4,5,6,j); j++; + SHA512_EXP(6,7,0,1,2,3,4,5,j); j++; + SHA512_EXP(5,6,7,0,1,2,3,4,j); j++; + SHA512_EXP(4,5,6,7,0,1,2,3,j); j++; + SHA512_EXP(3,4,5,6,7,0,1,2,j); j++; + SHA512_EXP(2,3,4,5,6,7,0,1,j); j++; + SHA512_EXP(1,2,3,4,5,6,7,0,j); j++; + } while (j < 80); + + ctx->h[0] += wv[0]; ctx->h[1] += wv[1]; + ctx->h[2] += wv[2]; ctx->h[3] += wv[3]; + ctx->h[4] += wv[4]; ctx->h[5] += wv[5]; + ctx->h[6] += wv[6]; ctx->h[7] += wv[7]; +#endif /* !UNROLL_LOOPS */ + } +} + +void sha512(const unsigned char *message, unsigned int len, + unsigned char *digest) +{ + sha512_ctx ctx; + + sha512_init(&ctx); + sha512_update(&ctx, message, len); + sha512_final(&ctx, digest); +} + +void sha512_init(sha512_ctx *ctx) +{ +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha512_h0[i]; + } +#else + ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1]; + ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3]; + ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5]; + ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha512_update(sha512_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const unsigned char *shifted_message; + + tmp_len = SHA512_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA512_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA512_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha512_transf(ctx, ctx->block, 1); + sha512_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA512_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 7], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void sha512_final(sha512_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = 1 + ((SHA512_BLOCK_SIZE - 17) + < (ctx->len % SHA512_BLOCK_SIZE)); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha512_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0 ; i < 8; i++) { + UNPACK64(ctx->h[i], &digest[i << 3]); + } +#else + UNPACK64(ctx->h[0], &digest[ 0]); + UNPACK64(ctx->h[1], &digest[ 8]); + UNPACK64(ctx->h[2], &digest[16]); + UNPACK64(ctx->h[3], &digest[24]); + UNPACK64(ctx->h[4], &digest[32]); + UNPACK64(ctx->h[5], &digest[40]); + UNPACK64(ctx->h[6], &digest[48]); + UNPACK64(ctx->h[7], &digest[56]); +#endif /* !UNROLL_LOOPS */ +} + +/* SHA-384 functions */ + +void sha384(const unsigned char *message, unsigned int len, + unsigned char *digest) +{ + sha384_ctx ctx; + + sha384_init(&ctx); + sha384_update(&ctx, message, len); + sha384_final(&ctx, digest); +} + +void sha384_init(sha384_ctx *ctx) +{ +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha384_h0[i]; + } +#else + ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1]; + ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3]; + ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5]; + ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha384_update(sha384_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const unsigned char *shifted_message; + + tmp_len = SHA384_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA384_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA384_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha512_transf(ctx, ctx->block, 1); + sha512_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA384_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 7], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void sha384_final(sha384_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = (1 + ((SHA384_BLOCK_SIZE - 17) + < (ctx->len % SHA384_BLOCK_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha512_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0 ; i < 6; i++) { + UNPACK64(ctx->h[i], &digest[i << 3]); + } +#else + UNPACK64(ctx->h[0], &digest[ 0]); + UNPACK64(ctx->h[1], &digest[ 8]); + UNPACK64(ctx->h[2], &digest[16]); + UNPACK64(ctx->h[3], &digest[24]); + UNPACK64(ctx->h[4], &digest[32]); + UNPACK64(ctx->h[5], &digest[40]); +#endif /* !UNROLL_LOOPS */ +} + +/* SHA-224 functions */ + +void sha224(const unsigned char *message, unsigned int len, + unsigned char *digest) +{ + sha224_ctx ctx; + + sha224_init(&ctx); + sha224_update(&ctx, message, len); + sha224_final(&ctx, digest); +} + +void sha224_init(sha224_ctx *ctx) +{ +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha224_h0[i]; + } +#else + ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1]; + ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3]; + ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5]; + ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha224_update(sha224_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const unsigned char *shifted_message; + + tmp_len = SHA224_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA224_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA224_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf(ctx, ctx->block, 1); + sha256_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA224_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void sha224_final(sha224_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = (1 + ((SHA224_BLOCK_SIZE - 9) + < (ctx->len % SHA224_BLOCK_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha256_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0 ; i < 7; i++) { + UNPACK32(ctx->h[i], &digest[i << 2]); + } +#else + UNPACK32(ctx->h[0], &digest[ 0]); + UNPACK32(ctx->h[1], &digest[ 4]); + UNPACK32(ctx->h[2], &digest[ 8]); + UNPACK32(ctx->h[3], &digest[12]); + UNPACK32(ctx->h[4], &digest[16]); + UNPACK32(ctx->h[5], &digest[20]); + UNPACK32(ctx->h[6], &digest[24]); +#endif /* !UNROLL_LOOPS */ +} + +#ifdef TEST_VECTORS + +/* FIPS 180-2 Validation tests */ + +#include +#include + +void test(const unsigned char *vector, unsigned char *digest, + unsigned int digest_size) +{ + unsigned char output[2 * SHA512_DIGEST_SIZE + 1]; + int i; + + output[2 * digest_size] = '\0'; + + for (i = 0; i < (int) digest_size ; i++) { + sprintf((char *) output + 2 * i, "%02x", digest[i]); + } + + printf("H: %s\n", output); + if (strcmp((char *) vector, (char *) output)) { + fprintf(stderr, "Test failed.\n"); + exit(EXIT_FAILURE); + } +} + +int main() +{ + static const unsigned char *vectors[4][3] = + { /* SHA-224 */ + { + "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", + "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525", + "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67", + }, + /* SHA-256 */ + { + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", + "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", + }, + /* SHA-384 */ + { + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" + "8086072ba1e7cc2358baeca134c825a7", + "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712" + "fcc7c71a557e2db966c3e9fa91746039", + "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b" + "07b8b3dc38ecc4ebae97ddd87f3d8985", + }, + /* SHA-512 */ + { + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909", + "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb" + "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b" + } + }; + + static const unsigned char message1[] = "abc"; + static const unsigned char message2a[] = "abcdbcdecdefdefgefghfghighijhi" + "jkijkljklmklmnlmnomnopnopq"; + static const unsigned char message2b[] = + "abcdefghbcdefghicdefghijdefghijkefghij" + "klfghijklmghijklmnhijklmnoijklmnopjklm" + "nopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + unsigned char *message3; + unsigned int message3_len = 1000000; + unsigned char digest[SHA512_DIGEST_SIZE]; + + message3 = malloc(message3_len); + if (message3 == NULL) { + fprintf(stderr, "Can't allocate memory\n"); + return -1; + } + memset(message3, 'a', message3_len); + + printf("SHA-2 FIPS 180-2 Validation tests\n\n"); + printf("SHA-224 Test vectors\n"); + + sha224(message1, strlen((char *) message1), digest); + test(vectors[0][0], digest, SHA224_DIGEST_SIZE); + sha224(message2a, strlen((char *) message2a), digest); + test(vectors[0][1], digest, SHA224_DIGEST_SIZE); + sha224(message3, message3_len, digest); + test(vectors[0][2], digest, SHA224_DIGEST_SIZE); + printf("\n"); + + printf("SHA-256 Test vectors\n"); + + sha256(message1, strlen((char *) message1), digest); + test(vectors[1][0], digest, SHA256_DIGEST_SIZE); + sha256(message2a, strlen((char *) message2a), digest); + test(vectors[1][1], digest, SHA256_DIGEST_SIZE); + sha256(message3, message3_len, digest); + test(vectors[1][2], digest, SHA256_DIGEST_SIZE); + printf("\n"); + + printf("SHA-384 Test vectors\n"); + + sha384(message1, strlen((char *) message1), digest); + test(vectors[2][0], digest, SHA384_DIGEST_SIZE); + sha384(message2b, strlen((char *) message2b), digest); + test(vectors[2][1], digest, SHA384_DIGEST_SIZE); + sha384(message3, message3_len, digest); + test(vectors[2][2], digest, SHA384_DIGEST_SIZE); + printf("\n"); + + printf("SHA-512 Test vectors\n"); + + sha512(message1, strlen((char *) message1), digest); + test(vectors[3][0], digest, SHA512_DIGEST_SIZE); + sha512(message2b, strlen((char *) message2b), digest); + test(vectors[3][1], digest, SHA512_DIGEST_SIZE); + sha512(message3, message3_len, digest); + test(vectors[3][2], digest, SHA512_DIGEST_SIZE); + printf("\n"); + + printf("All tests passed.\n"); + + return 0; +} + +#endif /* TEST_VECTORS */ + diff --git a/Plugins/PluginNowPlaying/sha2/sha2.h b/Plugins/PluginNowPlaying/sha2/sha2.h new file mode 100644 index 00000000..3c92a432 --- /dev/null +++ b/Plugins/PluginNowPlaying/sha2/sha2.h @@ -0,0 +1,108 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef SHA2_H +#define SHA2_H + +#define SHA224_DIGEST_SIZE ( 224 / 8) +#define SHA256_DIGEST_SIZE ( 256 / 8) +#define SHA384_DIGEST_SIZE ( 384 / 8) +#define SHA512_DIGEST_SIZE ( 512 / 8) + +#define SHA256_BLOCK_SIZE ( 512 / 8) +#define SHA512_BLOCK_SIZE (1024 / 8) +#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE +#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE + +#ifndef SHA2_TYPES +#define SHA2_TYPES +typedef unsigned char uint8; +typedef unsigned int uint32; +typedef unsigned long long uint64; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned int tot_len; + unsigned int len; + unsigned char block[2 * SHA256_BLOCK_SIZE]; + uint32 h[8]; +} sha256_ctx; + +typedef struct { + unsigned int tot_len; + unsigned int len; + unsigned char block[2 * SHA512_BLOCK_SIZE]; + uint64 h[8]; +} sha512_ctx; + +typedef sha512_ctx sha384_ctx; +typedef sha256_ctx sha224_ctx; + +void sha224_init(sha224_ctx *ctx); +void sha224_update(sha224_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha224_final(sha224_ctx *ctx, unsigned char *digest); +void sha224(const unsigned char *message, unsigned int len, + unsigned char *digest); + +void sha256_init(sha256_ctx * ctx); +void sha256_update(sha256_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha256_final(sha256_ctx *ctx, unsigned char *digest); +void sha256(const unsigned char *message, unsigned int len, + unsigned char *digest); + +void sha384_init(sha384_ctx *ctx); +void sha384_update(sha384_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha384_final(sha384_ctx *ctx, unsigned char *digest); +void sha384(const unsigned char *message, unsigned int len, + unsigned char *digest); + +void sha512_init(sha512_ctx *ctx); +void sha512_update(sha512_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha512_final(sha512_ctx *ctx, unsigned char *digest); +void sha512(const unsigned char *message, unsigned int len, + unsigned char *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* !SHA2_H */ + diff --git a/Plugins/PluginNowPlaying/taglib/COPYING.LGPL b/Plugins/PluginNowPlaying/taglib/COPYING.LGPL new file mode 100644 index 00000000..4362b491 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/COPYING.LGPL @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + 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 + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Plugins/PluginNowPlaying/taglib/COPYING.MPL b/Plugins/PluginNowPlaying/taglib/COPYING.MPL new file mode 100644 index 00000000..7714141d --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/COPYING.MPL @@ -0,0 +1,470 @@ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + diff --git a/Plugins/PluginNowPlaying/taglib/ape/ape-tag-format.txt b/Plugins/PluginNowPlaying/taglib/ape/ape-tag-format.txt new file mode 100644 index 00000000..21ff1c86 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/ape-tag-format.txt @@ -0,0 +1,170 @@ +================================================================================ += APE Tag Specification, Version 2.000 +================================================================================ + +Original Content (C) 2004, Frank Klemm +Formatting / Editing (C) 2004, Scott Wheeler + +================================================================================ += Contents +================================================================================ + +1 - APE Tag General Structure +2 - APE Tag Header / Footer Format +3 - APE Tag Flags +4 - APE Tag Item Format +5 - APE Tag Item Supported Keys +6 - APE Tag Item Content +7 - Data Types +7.1 - Data Types / UTF-8 +7.2 - Data Types / Dates +7.3 - Data Types / Timestamps + +================================================================================ += 1 - APE Tag General Structure +================================================================================ + +Member of Basic Components of SV8 Stream Note: + +It is strongly recommended that the data size be stored in the tags. The size +should normally be in the roughly one kilobyte, never more than 8 kilobytes. + +Larger data should be stored externally using link entries. Linked data is much +easier to process by normal programs, so for instance JPEG data should not be +included inside the audio file. + +APE Tag Version 2.000 (with header, recommended): + +/================================\ +| APE Tag Header | 32 bytes | +|-------------------|------------| +| APE Tag Item 1 | > 10 bytes | +| APE Tag Item 2 | > 10 bytes | +| APE Tag Item n-1 | > 10 bytes | +| APE Tag Item n | > 10 bytes | +|-------------------|------------| +| APE Tag Footer | 32 bytes | +\================================/ + + +APE tag items should be sorted ascending by size. When streaming, parts of the +APE tag may be dropped to reduce the danger of drop outs between tracks. This +is not required, but is strongly recommended. It would be desirable for the i +tems to be sorted by importance / size, but this is not feasible. This +convention should only be broken when adding less important small items and it +is not desirable to rewrite the entire tag. An APE tag at the end of a file +(the recommended location) must have at least a footer; an APE tag at the +beginning of a file (strongly discouraged) must have at least a header. + +APE Tag Version 1.000 (without header, deprecated) + +/================================\ +| APE Tag Item 1 | > 10 bytes | +| APE Tag Item 2 | > 10 bytes | +| APE Tag Item n-1 | > 10 bytes | +| APE Tag Item n | > 10 bytes | +|-------------------|------------| +| APE Tag Footer | 32 bytes | +\================================/ + +================================================================================ += 2 - APE Tag Header / Footer Format +================================================================================ + +Contains number, length and attributes of all tag items + +Header and Footer are different in 1 bit in the Tags Flags to distinguish +between them. + +Member of APE Tag 2.0 + +/===========================================================================\ +| Preamble | 8 bytes | { 'A', 'P', 'E', 'T', 'A', 'G', 'E', 'X' } | +|----------------|---------|------------------------------------------------| +| Version Number | 4 bytes | 1000 = Version 1.000, 2000 = Version 2.000 | +|----------------|---------|------------------------------------------------| +| Tag Size | 4 bytes | Tag size in bytes including footer and all tag | +| | | items excluding the header (for 1.000 | +| | | compatibility) | +|----------------|---------|------------------------------------------------| +| Item Count | 4 bytes | Number of items in the tag | +|----------------|---------|------------------------------------------------| +| Tag Flags | 4 bytes | Global flags | +|----------------|---------|------------------------------------------------| +| Reserved | 8 bytes | Must be zeroed | +\===========================================================================/ + +================================================================================ += 3 - APE Tag Flags +================================================================================ + +The general flag structure for either items or headers / footers is the same. +Bits 31, 30 and 29 are specific to headers / footers, whereas 2 through 0 are +item specific. + +Note: APE Tags from Version 1.0 do not use any of the following. All flags in +that version are zeroed and ignored when reading. + +/=================================================================\ +| Contains Header | Bit 31 | 1 - has header | 0 - no header | +|-----------------|-------------|---------------------------------| +| Contains Footer | Bit 30 | 1 - has footer | 0 - no footer | +|-----------------|-------------|---------------------------------| +| Is Header | Bit 29 | 1 - is header | 0 - is footer | +|-----------------|-------------|---------------------------------| +| Undefined | Bits 28 - 3 | Undefined, must be zeroed | +|-----------------|-------------|---------------------------------| +| Encoding | Bits 2 - 1 | 00 - UTF-8 | +| | | 01 - Binary Data * | +| | | 10 - External Reference ** | +| | | 11 - Reserved | +|-----------------|-------------|---------------------------------| +| Read Only | Bit 0 | 1 - read only | 0 - read/write | +\=================================================================/ + + (*) Should be ignored by tools for editing text values +(**) Allowed external reference formats: + - http://host/directory/filename.ext + - ftp://host/directory/filename.ext + - filename.ext + - /directory/filename.ext + - DRIVE:/directory/filename.ext + + Note: External references are also UTF-8 encoded. + +================================================================================ += 4 - APE Tag Item Format +================================================================================ + +APE Tag Items are stored as key-value pairs. APE Tags Item Key are case +sensitive, however it is illegal to use keys which only differ in case and +it is recommended that tag reading not be case sensitive. + +Every key can only occur (at most) once. It is not possible to repeat a key +to signify updated contents. + +Tags can be partially or completely repeated in the streaming format. This +makes it possible to display an artist and / or title if it was missed at the +beginning of the stream. It is recommended that the important information like +artist, album and title should occur approximately every 2 minutes in the +stream and again 5 to 10 seconds before the end. However, care should be tak +en not to replicate this information too often or during passages with high +bitrate demands to avoid unnecessary drop-outs. + +/==============================================================================\ +| Content Size | 4 bytes | Length of the value in bytes | +|----------------|---------------|---------------------------------------------| +| Flags | 4 bytes | Item flags | +|----------------|---------------|---------------------------------------------| +| Key | 2 - 255 bytes | Item key | +|----------------|---------------|---------------------------------------------| +| Key Terminator | 1 byte | Null byte that indicates the end of the key | +|----------------|---------------|---------------------------------------------| +| Value | variable | Content (formatted according to the flags) | +\==============================================================================/ + +================================================================================ + +Sections 5 - 7 haven't yet been converted from: + +http://www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html diff --git a/Plugins/PluginNowPlaying/taglib/ape/apefile.cpp b/Plugins/PluginNowPlaying/taglib/ape/apefile.cpp new file mode 100644 index 00000000..5d914756 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apefile.cpp @@ -0,0 +1,270 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "apefile.h" + +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +namespace +{ + enum { APEIndex, ID3v1Index }; +} + +class APE::File::FilePrivate +{ +public: + FilePrivate() : + APELocation(-1), + APESize(0), + ID3v1Location(-1), + properties(0), + hasAPE(false), + hasID3v1(false) {} + + ~FilePrivate() + { + delete properties; + } + + long APELocation; + uint APESize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasAPE; + bool hasID3v1; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +APE::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +APE::File::~File() +{ + delete d; +} + +TagLib::Tag *APE::File::tag() const +{ + return &d->tag; +} + +APE::Properties *APE::File::audioProperties() const +{ + return d->properties; +} + +bool APE::File::save() +{ + if(readOnly()) { + debug("APE::File::save() -- File is read only."); + return false; + } + + // Update ID3v1 tag + + if(ID3v1Tag()) { + if(d->hasID3v1) { + seek(d->ID3v1Location); + writeBlock(ID3v1Tag()->render()); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + writeBlock(ID3v1Tag()->render()); + d->hasID3v1 = true; + } + } + else { + if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->hasID3v1 = false; + if(d->hasAPE) { + if(d->APELocation > d->ID3v1Location) + d->APELocation -= 128; + } + } + } + + // Update APE tag + + if(APETag()) { + if(d->hasAPE) + insert(APETag()->render(), d->APELocation, d->APESize); + else { + if(d->hasID3v1) { + insert(APETag()->render(), d->ID3v1Location, 0); + d->APESize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + d->APELocation = d->ID3v1Location; + d->ID3v1Location += d->APESize; + } + else { + seek(0, End); + d->APELocation = tell(); + writeBlock(APETag()->render()); + d->APESize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + } + } + } + else { + if(d->hasAPE) { + removeBlock(d->APELocation, d->APESize); + d->hasAPE = false; + if(d->hasID3v1) { + if(d->ID3v1Location > d->APELocation) { + d->ID3v1Location -= d->APESize; + } + } + } + } + + return true; +} + +ID3v1::Tag *APE::File::ID3v1Tag(bool create) +{ + return d->tag.access(ID3v1Index, create); +} + +APE::Tag *APE::File::APETag(bool create) +{ + return d->tag.access(APEIndex, create); +} + +void APE::File::strip(int tags) +{ + if(tags & ID3v1) { + d->tag.set(ID3v1Index, 0); + APETag(true); + } + + if(tags & APE) { + d->tag.set(APEIndex, 0); + + if(!ID3v1Tag()) + APETag(true); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void APE::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + d->hasID3v1 = true; + } + + // Look for an APE tag + + d->APELocation = findAPE(); + + if(d->APELocation >= 0) { + d->tag.set(APEIndex, new APE::Tag(this, d->APELocation)); + d->APESize = APETag()->footer()->completeTagSize(); + d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize; + d->hasAPE = true; + } + + if(!d->hasID3v1) + APETag(true); + + // Look for APE audio properties + + if(readProperties) { + d->properties = new Properties(this); + } +} + +long APE::File::findAPE() +{ + if(!isValid()) + return -1; + + if(d->hasID3v1) + seek(-160, End); + else + seek(-32, End); + + long p = tell(); + + if(readBlock(8) == APE::Tag::fileIdentifier()) + return p; + + return -1; +} + +long APE::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} diff --git a/Plugins/PluginNowPlaying/taglib/ape/apefile.h b/Plugins/PluginNowPlaying/taglib/ape/apefile.h new file mode 100644 index 00000000..a4bc80d9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apefile.h @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEFILE_H +#define TAGLIB_APEFILE_H + +#include "tfile.h" +#include "taglib_export.h" +#include "apeproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of APE metadata + + /*! + * This is implementation of APE metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace APE { + + //! An implementation of TagLib::File with APE specific methods + + /*! + * This implements and provides an interface APE WavPack files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to APE files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches APE tags. + APE = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Contructs an WavPack 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, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the APE::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + * + * \note According to the official Monkey's Audio SDK, an APE file + * can only have either ID3V1 or APE tags, so a parameter is used here. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * a APE tag if one does not exist. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findID3v1(); + long findAPE(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ape/apefooter.cpp b/Plugins/PluginNowPlaying/taglib/ape/apefooter.cpp new file mode 100644 index 00000000..0805e9e0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apefooter.cpp @@ -0,0 +1,236 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + (C) 2002 - 2008 by Scott Wheeler (id3v2header.cpp) + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include +#include + +#include "apefooter.h" + +using namespace TagLib; +using namespace APE; + +class Footer::FooterPrivate +{ +public: + FooterPrivate() : version(0), + footerPresent(true), + headerPresent(false), + isHeader(false), + itemCount(0), + tagSize(0) {} + + ~FooterPrivate() {} + + uint version; + + bool footerPresent; + bool headerPresent; + + bool isHeader; + + uint itemCount; + uint tagSize; + + static const uint size = 32; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +TagLib::uint Footer::size() +{ + return FooterPrivate::size; +} + +ByteVector Footer::fileIdentifier() +{ + return ByteVector::fromCString("APETAGEX"); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Footer::Footer() +{ + d = new FooterPrivate; +} + +Footer::Footer(const ByteVector &data) +{ + d = new FooterPrivate; + parse(data); +} + +Footer::~Footer() +{ + delete d; +} + +TagLib::uint Footer::version() const +{ + return d->version; +} + +bool Footer::headerPresent() const +{ + return d->headerPresent; +} + +bool Footer::footerPresent() const +{ + return d->footerPresent; +} + +bool Footer::isHeader() const +{ + return d->isHeader; +} + +void Footer::setHeaderPresent(bool b) const +{ + d->headerPresent = b; +} + +TagLib::uint Footer::itemCount() const +{ + return d->itemCount; +} + +void Footer::setItemCount(uint s) +{ + d->itemCount = s; +} + +TagLib::uint Footer::tagSize() const +{ + return d->tagSize; +} + +TagLib::uint Footer::completeTagSize() const +{ + if(d->headerPresent) + return d->tagSize + d->size; + else + return d->tagSize; +} + +void Footer::setTagSize(uint s) +{ + d->tagSize = s; +} + +void Footer::setData(const ByteVector &data) +{ + parse(data); +} + +ByteVector Footer::renderFooter() const +{ + return render(false); +} + +ByteVector Footer::renderHeader() const +{ + if (!d->headerPresent) return ByteVector(); + + return render(true); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void Footer::parse(const ByteVector &data) +{ + if(data.size() < size()) + return; + + // The first eight bytes, data[0..7], are the File Identifier, "APETAGEX". + + // Read the version number + + d->version = data.mid(8, 4).toUInt(false); + + // Read the tag size + + d->tagSize = data.mid(12, 4).toUInt(false); + + // Read the item count + + d->itemCount = data.mid(16, 4).toUInt(false); + + // Read the flags + + std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.mid(20, 4).toUInt(false))); + + d->headerPresent = flags[31]; + d->footerPresent = !flags[30]; + d->isHeader = flags[29]; + +} + +ByteVector Footer::render(bool isHeader) const +{ + ByteVector v; + + // add the file identifier -- "APETAGEX" + + v.append(fileIdentifier()); + + // add the version number -- we always render a 2.000 tag regardless of what + // the tag originally was. + + v.append(ByteVector::fromUInt(2000, false)); + + // add the tag size + + v.append(ByteVector::fromUInt(d->tagSize, false)); + + // add the item count + + v.append(ByteVector::fromUInt(d->itemCount, false)); + + // render and add the flags + + std::bitset<32> flags; + + flags[31] = d->headerPresent; + flags[30] = false; // footer is always present + flags[29] = isHeader; + + v.append(ByteVector::fromUInt(flags.to_ulong(), false)); + + // add the reserved 64bit + + v.append(ByteVector::fromLongLong(0)); + + return v; +} diff --git a/Plugins/PluginNowPlaying/taglib/ape/apefooter.h b/Plugins/PluginNowPlaying/taglib/ape/apefooter.h new file mode 100644 index 00000000..080f9300 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apefooter.h @@ -0,0 +1,173 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEFOOTER_H +#define TAGLIB_APEFOOTER_H + +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace APE { + + //! An implementation of APE footers + + /*! + * This class implements APE footers (and headers). It attempts to follow, both + * semantically and programatically, the structure specified in + * the APE v2.0 standard. The API is based on the properties of APE footer and + * headers specified there. + */ + + class TAGLIB_EXPORT Footer + { + public: + /*! + * Constructs an empty APE footer. + */ + Footer(); + + /*! + * Constructs an APE footer based on \a data. parse() is called + * immediately. + */ + Footer(const ByteVector &data); + + /*! + * Destroys the footer. + */ + virtual ~Footer(); + + /*! + * Returns the version number. (Note: This is the 1000 or 2000.) + */ + uint version() const; + + /*! + * Returns true if a header is present in the tag. + */ + bool headerPresent() const; + + /*! + * Returns true if a footer is present in the tag. + */ + bool footerPresent() const; + + /*! + * Returns true this is actually the header. + */ + bool isHeader() const; + + /*! + * Sets whether the header should be rendered or not + */ + void setHeaderPresent(bool b) const; + + /*! + * Returns the number of items in the tag. + */ + uint itemCount() const; + + /*! + * Set the item count to \a s. + * \see itemCount() + */ + void setItemCount(uint s); + + /*! + * Returns the tag size in bytes. This is the size of the frame content and footer. + * The size of the \e entire tag will be this plus the header size, if present. + * + * \see completeTagSize() + */ + uint tagSize() const; + + /*! + * Returns the tag size, including if present, the header + * size. + * + * \see tagSize() + */ + uint completeTagSize() const; + + /*! + * Set the tag size to \a s. + * \see tagSize() + */ + void setTagSize(uint s); + + /*! + * Returns the size of the footer. Presently this is always 32 bytes. + */ + static uint size(); + + /*! + * Returns the string used to identify an APE tag inside of a file. + * Presently this is always "APETAGEX". + */ + static ByteVector fileIdentifier(); + + /*! + * Sets the data that will be used as the footer. 32 bytes, + * starting from \a data will be used. + */ + void setData(const ByteVector &data); + + /*! + * Renders the footer back to binary format. + */ + ByteVector renderFooter() const; + + /*! + * Renders the header corresponding to the footer. If headerPresent is + * set to false, it returns an empty ByteVector. + */ + ByteVector renderHeader() const; + + protected: + /*! + * Called by setData() to parse the footer data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + /*! + * Called by renderFooter and renderHeader + */ + ByteVector render(bool isHeader) const; + + private: + Footer(const Footer &); + Footer &operator=(const Footer &); + + class FooterPrivate; + FooterPrivate *d; + }; + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ape/apeitem.cpp b/Plugins/PluginNowPlaying/taglib/ape/apeitem.cpp new file mode 100644 index 00000000..350eac0b --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apeitem.cpp @@ -0,0 +1,230 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.com + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "apeitem.h" + +using namespace TagLib; +using namespace APE; + +class APE::Item::ItemPrivate +{ +public: + ItemPrivate() : type(Text), readOnly(false) {} + + Item::ItemTypes type; + String key; + ByteVector value; + StringList text; + bool readOnly; +}; + +APE::Item::Item() +{ + d = new ItemPrivate; +} + +APE::Item::Item(const String &key, const String &value) +{ + d = new ItemPrivate; + d->key = key; + d->text.append(value); +} + +APE::Item::Item(const String &key, const StringList &values) +{ + d = new ItemPrivate; + d->key = key; + d->text = values; +} + +APE::Item::Item(const Item &item) +{ + d = new ItemPrivate(*item.d); +} + +APE::Item::~Item() +{ + delete d; +} + +Item &APE::Item::operator=(const Item &item) +{ + delete d; + d = new ItemPrivate(*item.d); + return *this; +} + +void APE::Item::setReadOnly(bool readOnly) +{ + d->readOnly = readOnly; +} + +bool APE::Item::isReadOnly() const +{ + return d->readOnly; +} + +void APE::Item::setType(APE::Item::ItemTypes val) +{ + d->type = val; +} + +APE::Item::ItemTypes APE::Item::type() const +{ + return d->type; +} + +String APE::Item::key() const +{ + return d->key; +} + +ByteVector APE::Item::value() const +{ + // This seems incorrect as it won't be actually rendering the value to keep it + // up to date. + + return d->value; +} + +void APE::Item::setKey(const String &key) +{ + d->key = key; +} + +void APE::Item::setValue(const String &value) +{ + d->text = value; +} + +void APE::Item::setValues(const StringList &value) +{ + d->text = value; +} + +void APE::Item::appendValue(const String &value) +{ + d->text.append(value); +} + +void APE::Item::appendValues(const StringList &values) +{ + d->text.append(values); +} + +int APE::Item::size() const +{ + return 8 + d->key.size() + 1 + d->value.size(); +} + +StringList APE::Item::toStringList() const +{ + return d->text; +} + +StringList APE::Item::values() const +{ + return d->text; +} + +String APE::Item::toString() const +{ + return isEmpty() ? String::null : d->text.front(); +} + +bool APE::Item::isEmpty() const +{ + switch(d->type) { + case Text: + case Binary: + if(d->text.isEmpty()) + return true; + if(d->text.size() == 1 && d->text.front().isEmpty()) + return true; + return false; + case Locator: + return d->value.isEmpty(); + default: + return false; + } +} + +void APE::Item::parse(const ByteVector &data) +{ + // 11 bytes is the minimum size for an APE item + + if(data.size() < 11) { + debug("APE::Item::parse() -- no data in item"); + return; + } + + uint valueLength = data.mid(0, 4).toUInt(false); + uint flags = data.mid(4, 4).toUInt(false); + + d->key = String(data.mid(8), String::UTF8); + + d->value = data.mid(8 + d->key.size() + 1, valueLength); + + setReadOnly(flags & 1); + setType(ItemTypes((flags >> 1) & 3)); + + if(int(d->type) < 2) + d->text = StringList(ByteVectorList::split(d->value, '\0'), String::UTF8); +} + +ByteVector APE::Item::render() const +{ + ByteVector data; + TagLib::uint flags = ((d->readOnly) ? 1 : 0) | (d->type << 1); + ByteVector value; + + if(isEmpty()) + return data; + + if(d->type == Text) { + StringList::ConstIterator it = d->text.begin(); + + value.append(it->data(String::UTF8)); + it++; + for(; it != d->text.end(); ++it) { + value.append('\0'); + value.append(it->data(String::UTF8)); + } + d->value = value; + } + else + value.append(d->value); + + data.append(ByteVector::fromUInt(value.size(), false)); + data.append(ByteVector::fromUInt(flags, false)); + data.append(d->key.data(String::UTF8)); + data.append(ByteVector('\0')); + data.append(value); + + return data; +} diff --git a/Plugins/PluginNowPlaying/taglib/ape/apeitem.h b/Plugins/PluginNowPlaying/taglib/ape/apeitem.h new file mode 100644 index 00000000..01fcc764 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apeitem.h @@ -0,0 +1,204 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEITEM_H +#define TAGLIB_APEITEM_H + +#include "tbytevector.h" +#include "tstring.h" +#include "tstringlist.h" + +namespace TagLib { + + namespace APE { + + //! An implementation of APE-items + + /*! + * This class provides the features of items in the APEv2 standard. + */ + class TAGLIB_EXPORT Item + { + public: + /*! + * Enum of types an Item can have. The value of 3 is reserved. + */ + enum ItemTypes { + //! Item contains text information coded in UTF-8 + Text = 0, + //! Item contains binary information + Binary = 1, + //! Item is a locator of external stored information + Locator = 2 + }; + /*! + * Constructs an empty item. + */ + Item(); + + /*! + * Constructs an item with \a key and \a value. + */ + // BIC: Remove this, StringList has a constructor from a single string + Item(const String &key, const String &value); + + /*! + * Constructs an item with \a key and \a values. + */ + Item(const String &key, const StringList &values); + + /*! + * Construct an item as a copy of \a item. + */ + Item(const Item &item); + + /*! + * Destroys the item. + */ + virtual ~Item(); + + /*! + * Copies the contents of \a item into this item. + */ + Item &operator=(const Item &item); + + /*! + * Returns the key. + */ + String key() const; + + /*! + * Returns the binary value. + * + * \deprecated This will be removed in the next binary incompatible version + * as it is not kept in sync with the things that are set using setValue() + * and friends. + */ + ByteVector value() const; + + /*! + * Sets the key for the item to \a key. + */ + void setKey(const String &key); + + /*! + * Sets the value of the item to \a value and clears any previous contents. + * + * \see toString() + */ + void setValue(const String &value); + + /*! + * Sets the value of the item to the list of values in \a value and clears + * any previous contents. + * + * \see toStringList() + */ + void setValues(const StringList &values); + + /*! + * Appends \a value to create (or extend) the current list of values. + * + * \see toString() + */ + void appendValue(const String &value); + + /*! + * Appends \a values to extend the current list of values. + * + * \see toStringList() + */ + void appendValues(const StringList &values); + + /*! + * Returns the size of the full item. + */ + int size() const; + + /*! + * Returns the value as a single string. In case of multiple strings, + * the first is returned. + */ + String toString() const; + + /*! + * \deprecated + * \see values + */ + StringList toStringList() const; + + /*! + * Returns the list of values. + */ + StringList values() const; + + /*! + * Render the item to a ByteVector. + */ + ByteVector render() const; + + /*! + * Parse the item from the ByteVector \a data. + */ + void parse(const ByteVector& data); + + /*! + * Set the item to read-only. + */ + void setReadOnly(bool readOnly); + + /*! + * Return true if the item is read-only. + */ + bool isReadOnly() const; + + /*! + * Sets the type of the item to \a type. + * + * \see ItemTypes + */ + void setType(ItemTypes type); + + /*! + * Returns the type of the item. + */ + ItemTypes type() const; + + /*! + * Returns if the item has any real content. + */ + bool isEmpty() const; + + private: + class ItemPrivate; + ItemPrivate *d; + }; + } + +} + +#endif + + diff --git a/Plugins/PluginNowPlaying/taglib/ape/apeproperties.cpp b/Plugins/PluginNowPlaying/taglib/ape/apeproperties.cpp new file mode 100644 index 00000000..3154d104 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apeproperties.cpp @@ -0,0 +1,224 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include "id3v2tag.h" +#include "apeproperties.h" +#include "apefile.h" + +using namespace TagLib; + +class APE::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(File *file, long streamLength) : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + version(0), + bitsPerSample(0), + file(file), + streamLength(streamLength) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int version; + int bitsPerSample; + File *file; + long streamLength; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +APE::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file, file->length()); + read(); +} + +APE::Properties::~Properties() +{ + delete d; +} + +int APE::Properties::length() const +{ + return d->length; +} + +int APE::Properties::bitrate() const +{ + return d->bitrate; +} + +int APE::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int APE::Properties::channels() const +{ + return d->channels; +} + +int APE::Properties::version() const +{ + return d->version; +} + +int APE::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + + +void APE::Properties::read() +{ + // First we are searching the descriptor + long offset = findDescriptor(); + if(offset < 0) + return; + + // Then we read the header common for all versions of APE + d->file->seek(offset); + ByteVector commonHeader=d->file->readBlock(6); + if(!commonHeader.startsWith("MAC ")) + return; + d->version = commonHeader.mid(4).toUInt(false); + + if(d->version >= 3980) { + analyzeCurrent(); + } + else { + analyzeOld(); + } +} + +long APE::Properties::findDescriptor() +{ + long ID3v2Location = findID3v2(); + long ID3v2OriginalSize = 0; + bool hasID3v2 = false; + if(ID3v2Location >= 0) { + ID3v2::Tag tag(d->file, ID3v2Location, 0); + ID3v2OriginalSize = tag.header()->completeTagSize(); + if(tag.header()->tagSize() > 0) + hasID3v2 = true; + } + + long offset = 0; + if(hasID3v2) + offset = d->file->find("MAC ", ID3v2Location + ID3v2OriginalSize); + else + offset = d->file->find("MAC "); + + if(offset < 0) { + debug("APE::Properties::findDescriptor() -- APE descriptor not found"); + return -1; + } + + return offset; +} + +long APE::Properties::findID3v2() +{ + if(!d->file->isValid()) + return -1; + + d->file->seek(0); + + if(d->file->readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} + +void APE::Properties::analyzeCurrent() +{ + // Read the descriptor + d->file->seek(2, File::Current); + ByteVector descriptor = d->file->readBlock(44); + uint descriptorBytes = descriptor.mid(0,4).toUInt(false); + + if ((descriptorBytes - 52) > 0) + d->file->seek(descriptorBytes - 52, File::Current); + + // Read the header + ByteVector header = d->file->readBlock(24); + + // Get the APE info + d->channels = header.mid(18, 2).toShort(false); + d->sampleRate = header.mid(20, 4).toUInt(false); + d->bitsPerSample = header.mid(16, 2).toShort(false); + //d->compressionLevel = + + uint totalFrames = header.mid(12, 4).toUInt(false); + uint blocksPerFrame = header.mid(4, 4).toUInt(false); + uint finalFrameBlocks = header.mid(8, 4).toUInt(false); + uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0; + d->length = totalBlocks / d->sampleRate; + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} + +void APE::Properties::analyzeOld() +{ + ByteVector header = d->file->readBlock(26); + uint totalFrames = header.mid(18, 4).toUInt(false); + + // Fail on 0 length APE files (catches non-finalized APE files) + if(totalFrames == 0) + return; + + short compressionLevel = header.mid(0, 2).toShort(false); + uint blocksPerFrame; + if(d->version >= 3950) + blocksPerFrame = 73728 * 4; + else if(d->version >= 3900 || (d->version >= 3800 && compressionLevel == 4000)) + blocksPerFrame = 73728; + else + blocksPerFrame = 9216; + d->channels = header.mid(4, 2).toShort(false); + d->sampleRate = header.mid(6, 4).toUInt(false); + uint finalFrameBlocks = header.mid(22, 4).toUInt(false); + uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0; + d->length = totalBlocks / d->sampleRate; + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} + diff --git a/Plugins/PluginNowPlaying/taglib/ape/apeproperties.h b/Plugins/PluginNowPlaying/taglib/ape/apeproperties.h new file mode 100644 index 00000000..8b543a57 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apeproperties.h @@ -0,0 +1,98 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEPROPERTIES_H +#define TAGLIB_APEPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace APE { + + class File; + + //! An implementation of audio property reading for APE + + /*! + * This reads the data from an APE stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of APE::Properties with the data read from the + * ByteVector \a data. + */ + Properties(File *f, ReadStyle style = Average); + + /*! + * Destroys this APE::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns number of bits per sample. + */ + int bitsPerSample() const; + + /*! + * Returns APE version. + */ + int version() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + long findDescriptor(); + long findID3v2(); + + void analyzeCurrent(); + void analyzeOld(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ape/apetag.cpp b/Plugins/PluginNowPlaying/taglib/ape/apetag.cpp new file mode 100644 index 00000000..082fd038 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apetag.cpp @@ -0,0 +1,271 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.com + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef __SUNPRO_CC +// Sun Studio finds multiple specializations of Map because +// it considers specializations with and without class types +// to be different; this define forces Map to use only the +// specialization with the class keyword. +#define WANT_CLASS_INSTANTIATION_OF_MAP (1) +#endif + +#include +#include +#include + +#include "apetag.h" +#include "apefooter.h" +#include "apeitem.h" + +using namespace TagLib; +using namespace APE; + +class APE::Tag::TagPrivate +{ +public: + TagPrivate() : file(0), footerLocation(-1), tagLength(0) {} + + File *file; + long footerLocation; + long tagLength; + + Footer footer; + + ItemListMap itemListMap; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +APE::Tag::Tag() : TagLib::Tag() +{ + d = new TagPrivate; +} + +APE::Tag::Tag(File *file, long footerLocation) : TagLib::Tag() +{ + d = new TagPrivate; + d->file = file; + d->footerLocation = footerLocation; + + read(); +} + +APE::Tag::~Tag() +{ + delete d; +} + +ByteVector APE::Tag::fileIdentifier() +{ + return ByteVector::fromCString("APETAGEX"); +} + +String APE::Tag::title() const +{ + if(d->itemListMap["TITLE"].isEmpty()) + return String::null; + return d->itemListMap["TITLE"].toString(); +} + +String APE::Tag::artist() const +{ + if(d->itemListMap["ARTIST"].isEmpty()) + return String::null; + return d->itemListMap["ARTIST"].toString(); +} + +String APE::Tag::album() const +{ + if(d->itemListMap["ALBUM"].isEmpty()) + return String::null; + return d->itemListMap["ALBUM"].toString(); +} + +String APE::Tag::comment() const +{ + if(d->itemListMap["COMMENT"].isEmpty()) + return String::null; + return d->itemListMap["COMMENT"].toString(); +} + +String APE::Tag::genre() const +{ + if(d->itemListMap["GENRE"].isEmpty()) + return String::null; + return d->itemListMap["GENRE"].toString(); +} + +TagLib::uint APE::Tag::year() const +{ + if(d->itemListMap["YEAR"].isEmpty()) + return 0; + return d->itemListMap["YEAR"].toString().toInt(); +} + +TagLib::uint APE::Tag::track() const +{ + if(d->itemListMap["TRACK"].isEmpty()) + return 0; + return d->itemListMap["TRACK"].toString().toInt(); +} + +void APE::Tag::setTitle(const String &s) +{ + addValue("TITLE", s, true); +} + +void APE::Tag::setArtist(const String &s) +{ + addValue("ARTIST", s, true); +} + +void APE::Tag::setAlbum(const String &s) +{ + addValue("ALBUM", s, true); +} + +void APE::Tag::setComment(const String &s) +{ + addValue("COMMENT", s, true); +} + +void APE::Tag::setGenre(const String &s) +{ + addValue("GENRE", s, true); +} + +void APE::Tag::setYear(uint i) +{ + if(i <= 0) + removeItem("YEAR"); + else + addValue("YEAR", String::number(i), true); +} + +void APE::Tag::setTrack(uint i) +{ + if(i <= 0) + removeItem("TRACK"); + else + addValue("TRACK", String::number(i), true); +} + +APE::Footer *APE::Tag::footer() const +{ + return &d->footer; +} + +const APE::ItemListMap& APE::Tag::itemListMap() const +{ + return d->itemListMap; +} + +void APE::Tag::removeItem(const String &key) +{ + Map::Iterator it = d->itemListMap.find(key.upper()); + if(it != d->itemListMap.end()) + d->itemListMap.erase(it); +} + +void APE::Tag::addValue(const String &key, const String &value, bool replace) +{ + if(replace) + removeItem(key); + if(!value.isEmpty()) { + if(d->itemListMap.contains(key) || !replace) + d->itemListMap[key.upper()].appendValue(value); + else + setItem(key, Item(key, value)); + } +} + +void APE::Tag::setItem(const String &key, const Item &item) +{ + d->itemListMap.insert(key.upper(), item); +} + +bool APE::Tag::isEmpty() const +{ + return d->itemListMap.isEmpty(); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected methods +//////////////////////////////////////////////////////////////////////////////// + +void APE::Tag::read() +{ + if(d->file && d->file->isValid()) { + + d->file->seek(d->footerLocation); + d->footer.setData(d->file->readBlock(Footer::size())); + + if(d->footer.tagSize() <= Footer::size() || + d->footer.tagSize() > uint(d->file->length())) + return; + + d->file->seek(d->footerLocation + Footer::size() - d->footer.tagSize()); + parse(d->file->readBlock(d->footer.tagSize() - Footer::size())); + } +} + +ByteVector APE::Tag::render() const +{ + ByteVector data; + uint itemCount = 0; + + { + for(Map::ConstIterator it = d->itemListMap.begin(); + it != d->itemListMap.end(); ++it) + { + data.append(it->second.render()); + itemCount++; + } + } + + d->footer.setItemCount(itemCount); + d->footer.setTagSize(data.size() + Footer::size()); + d->footer.setHeaderPresent(true); + + return d->footer.renderHeader() + data + d->footer.renderFooter(); +} + +void APE::Tag::parse(const ByteVector &data) +{ + uint pos = 0; + + // 11 bytes is the minimum size for an APE item + + for(uint i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) { + APE::Item item; + item.parse(data.mid(pos)); + + d->itemListMap.insert(item.key().upper(), item); + + pos += item.size(); + } +} diff --git a/Plugins/PluginNowPlaying/taglib/ape/apetag.h b/Plugins/PluginNowPlaying/taglib/ape/apetag.h new file mode 100644 index 00000000..13efd5e0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ape/apetag.h @@ -0,0 +1,170 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APETAG_H +#define TAGLIB_APETAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "tmap.h" +#include "tstring.h" +#include "taglib_export.h" + +#include "apeitem.h" + +namespace TagLib { + + class File; + + //! An implementation of the APE tagging format + + namespace APE { + + class Footer; + + /*! + * A mapping between a list of item names, or keys, and the associated item. + * + * \see APE::Tag::itemListMap() + */ + typedef Map ItemListMap; + + + //! An APE tag implementation + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Create an APE tag with default values. + */ + Tag(); + + /*! + * Create an APE tag and parse the data in \a file with APE footer at + * \a tagOffset. + */ + Tag(TagLib::File *file, long footerLocation); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Renders the in memory values to a ByteVector suitable for writing to + * the file. + */ + ByteVector render() const; + + /*! + * Returns the string "APETAGEX" suitable for usage in locating the tag in a + * file. + */ + static ByteVector fileIdentifier(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual uint year() const; + virtual uint track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(uint i); + virtual void setTrack(uint i); + + /*! + * Returns a pointer to the tag's footer. + */ + Footer *footer() const; + + /*! + * Returns a reference to the item list map. This is an ItemListMap of + * all of the items in the tag. + * + * This is the most powerfull structure for accessing the items of the tag. + * + * APE tags are case-insensitive, all keys in this map have been converted + * to upper case. + * + * \warning You should not modify this data structure directly, instead + * use setItem() and removeItem(). + */ + const ItemListMap &itemListMap() const; + + /*! + * Removes the \a key item from the tag + */ + void removeItem(const String &key); + + /*! + * Adds to the item specified by \a key the data \a value. If \a replace + * is true, then all of the other values on the same key will be removed + * first. + */ + void addValue(const String &key, const String &value, bool replace = true); + + /*! + * Sets the \a key item to the value of \a item. If an item with the \a key is already + * present, it will be replaced. + */ + void setItem(const String &key, const Item &item); + + /*! + * Returns true if the tag does not contain any data. + */ + bool isEmpty() const; + + protected: + + /*! + * Reads from the file specified in the constructor. + */ + void read(); + + /*! + * Parses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asfattribute.cpp b/Plugins/PluginNowPlaying/taglib/asf/asfattribute.cpp new file mode 100644 index 00000000..ecdf1f61 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asfattribute.cpp @@ -0,0 +1,356 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_ASF + +#include +#include +#include "asfattribute.h" +#include "asffile.h" + +using namespace TagLib; + +class ASF::Attribute::AttributePrivate : public RefCounter +{ +public: + AttributePrivate() + : pictureValue(ASF::Picture::fromInvalid()), + stream(0), + language(0) {} + AttributeTypes type; + String stringValue; + ByteVector byteVectorValue; + ASF::Picture pictureValue; + union { + unsigned int intValue; + unsigned short shortValue; + unsigned long long longLongValue; + bool boolValue; + }; + int stream; + int language; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Attribute::Attribute() +{ + d = new AttributePrivate; + d->type = UnicodeType; +} + +ASF::Attribute::Attribute(const ASF::Attribute &other) + : d(other.d) +{ + d->ref(); +} + +ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other) +{ + if(d->deref()) + delete d; + d = other.d; + d->ref(); + return *this; +} + +ASF::Attribute::~Attribute() +{ + if(d->deref()) + delete d; +} + +ASF::Attribute::Attribute(const String &value) +{ + d = new AttributePrivate; + d->type = UnicodeType; + d->stringValue = value; +} + +ASF::Attribute::Attribute(const ByteVector &value) +{ + d = new AttributePrivate; + d->type = BytesType; + d->byteVectorValue = value; +} + +ASF::Attribute::Attribute(const ASF::Picture &value) +{ + d = new AttributePrivate; + d->type = BytesType; + d->pictureValue = value; +} + +ASF::Attribute::Attribute(unsigned int value) +{ + d = new AttributePrivate; + d->type = DWordType; + d->intValue = value; +} + +ASF::Attribute::Attribute(unsigned long long value) +{ + d = new AttributePrivate; + d->type = QWordType; + d->longLongValue = value; +} + +ASF::Attribute::Attribute(unsigned short value) +{ + d = new AttributePrivate; + d->type = WordType; + d->shortValue = value; +} + +ASF::Attribute::Attribute(bool value) +{ + d = new AttributePrivate; + d->type = BoolType; + d->boolValue = value; +} + +ASF::Attribute::AttributeTypes ASF::Attribute::type() const +{ + return d->type; +} + +String ASF::Attribute::toString() const +{ + return d->stringValue; +} + +ByteVector ASF::Attribute::toByteVector() const +{ + if(d->pictureValue.isValid()) + return d->pictureValue.render(); + return d->byteVectorValue; +} + +unsigned short ASF::Attribute::toBool() const +{ + return d->shortValue; +} + +unsigned short ASF::Attribute::toUShort() const +{ + return d->shortValue; +} + +unsigned int ASF::Attribute::toUInt() const +{ + return d->intValue; +} + +unsigned long long ASF::Attribute::toULongLong() const +{ + return d->longLongValue; +} + +ASF::Picture ASF::Attribute::toPicture() const +{ + return d->pictureValue; +} + +String ASF::Attribute::parse(ASF::File &f, int kind) +{ + uint size, nameLength; + String name; + d->pictureValue = Picture::fromInvalid(); + // extended content descriptor + if(kind == 0) { + nameLength = f.readWORD(); + name = f.readString(nameLength); + d->type = ASF::Attribute::AttributeTypes(f.readWORD()); + size = f.readWORD(); + } + // metadata & metadata library + else { + int temp = f.readWORD(); + // metadata library + if(kind == 2) { + d->language = temp; + } + d->stream = f.readWORD(); + nameLength = f.readWORD(); + d->type = ASF::Attribute::AttributeTypes(f.readWORD()); + size = f.readDWORD(); + name = f.readString(nameLength); + } + + if(kind != 2 && size > 65535) { + debug("ASF::Attribute::parse() -- Value larger than 64kB"); + } + + switch(d->type) { + case WordType: + d->shortValue = f.readWORD(); + break; + + case BoolType: + if(kind == 0) { + d->boolValue = f.readDWORD() == 1; + } + else { + d->boolValue = f.readWORD() == 1; + } + break; + + case DWordType: + d->intValue = f.readDWORD(); + break; + + case QWordType: + d->longLongValue = f.readQWORD(); + break; + + case UnicodeType: + d->stringValue = f.readString(size); + break; + + case BytesType: + case GuidType: + d->byteVectorValue = f.readBlock(size); + break; + } + + if(d->type == BytesType && name == "WM/Picture") { + d->pictureValue.parse(d->byteVectorValue); + if(d->pictureValue.isValid()) { + d->byteVectorValue.clear(); + } + } + + return name; +} + +int ASF::Attribute::dataSize() const +{ + switch (d->type) { + case WordType: + return 2; + case BoolType: + return 4; + case DWordType: + return 4; + case QWordType: + return 5; + case UnicodeType: + return d->stringValue.size() * 2 + 2; + case BytesType: + if(d->pictureValue.isValid()) + return d->pictureValue.dataSize(); + case GuidType: + return d->byteVectorValue.size(); + } + return 0; +} + +ByteVector ASF::Attribute::render(const String &name, int kind) const +{ + ByteVector data; + + switch (d->type) { + case WordType: + data.append(ByteVector::fromShort(d->shortValue, false)); + break; + + case BoolType: + if(kind == 0) { + data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false)); + } + else { + data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false)); + } + break; + + case DWordType: + data.append(ByteVector::fromUInt(d->intValue, false)); + break; + + case QWordType: + data.append(ByteVector::fromLongLong(d->longLongValue, false)); + break; + + case UnicodeType: + data.append(File::renderString(d->stringValue)); + break; + + case BytesType: + if(d->pictureValue.isValid()) { + data.append(d->pictureValue.render()); + break; + } + case GuidType: + data.append(d->byteVectorValue); + break; + } + + if(kind == 0) { + data = File::renderString(name, true) + + ByteVector::fromShort((int)d->type, false) + + ByteVector::fromShort(data.size(), false) + + data; + } + else { + ByteVector nameData = File::renderString(name); + data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) + + ByteVector::fromShort(d->stream, false) + + ByteVector::fromShort(nameData.size(), false) + + ByteVector::fromShort((int)d->type, false) + + ByteVector::fromUInt(data.size(), false) + + nameData + + data; + } + + return data; +} + +int ASF::Attribute::language() const +{ + return d->language; +} + +void ASF::Attribute::setLanguage(int value) +{ + d->language = value; +} + +int ASF::Attribute::stream() const +{ + return d->stream; +} + +void ASF::Attribute::setStream(int value) +{ + d->stream = value; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asfattribute.h b/Plugins/PluginNowPlaying/taglib/asf/asfattribute.h new file mode 100644 index 00000000..56186999 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asfattribute.h @@ -0,0 +1,203 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFATTRIBUTE_H +#define TAGLIB_ASFATTRIBUTE_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "asfpicture.h" + +namespace TagLib +{ + + namespace ASF + { + + class File; + class Picture; + + class TAGLIB_EXPORT Attribute + { + public: + + /*! + * Enum of types an Attribute can have. + */ + enum AttributeTypes { + UnicodeType = 0, + BytesType = 1, + BoolType = 2, + DWordType = 3, + QWordType = 4, + WordType = 5, + GuidType = 6 + }; + + /*! + * Constructs an empty attribute. + */ + Attribute(); + + /*! + * Constructs an attribute with \a key and a UnicodeType \a value. + */ + Attribute(const String &value); + + /*! + * Constructs an attribute with \a key and a BytesType \a value. + */ + Attribute(const ByteVector &value); + + /*! + * Constructs an attribute with \a key and a Picture \a value. + * + * This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that, + * while there may be any number of APIC frames associated with a file, + * only one may be of type 1 and only one may be of type 2. + * + * The specification also states that the description of the picture can be no longer than 64 characters, but can be empty. + * WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications. + * You must add code in your application to perform validations if you want to maintain complete compatibility with ID3. + */ + Attribute(const Picture &value); + + /*! + * Constructs an attribute with \a key and a DWordType \a value. + */ + Attribute(unsigned int value); + + /*! + * Constructs an attribute with \a key and a QWordType \a value. + */ + Attribute(unsigned long long value); + + /*! + * Constructs an attribute with \a key and a WordType \a value. + */ + Attribute(unsigned short value); + + /*! + * Constructs an attribute with \a key and a BoolType \a value. + */ + Attribute(bool value); + + /*! + * Construct an attribute as a copy of \a other. + */ + Attribute(const Attribute &item); + + /*! + * Copies the contents of \a other into this item. + */ + ASF::Attribute &operator=(const Attribute &other); + + /*! + * Destroys the attribute. + */ + virtual ~Attribute(); + + /*! + * Returns type of the value. + */ + AttributeTypes type() const; + + /*! + * Returns the BoolType \a value. + */ + unsigned short toBool() const; + + /*! + * Returns the WordType \a value. + */ + unsigned short toUShort() const; + + /*! + * Returns the DWordType \a value. + */ + unsigned int toUInt() const; + + /*! + * Returns the QWordType \a value. + */ + unsigned long long toULongLong() const; + + /*! + * Returns the UnicodeType \a value. + */ + String toString() const; + + /*! + * Returns the BytesType \a value. + */ + ByteVector toByteVector() const; + + /*! + * Returns the Picture \a value. + */ + Picture toPicture() const; + + /*! + * Returns the language number, or 0 is no stream number was set. + */ + int language() const; + + /*! + * Sets the language number. + */ + void setLanguage(int value); + + /*! + * Returns the stream number, or 0 is no stream number was set. + */ + int stream() const; + + /*! + * Sets the stream number. + */ + void setStream(int value); + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + String parse(ASF::File &file, int kind = 0); +#endif + + //! Returns the size of the stored data + int dataSize() const; + + private: + friend class File; + + ByteVector render(const String &name, int kind = 0) const; + + class AttributePrivate; + AttributePrivate *d; + }; + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asffile.cpp b/Plugins/PluginNowPlaying/taglib/asf/asffile.cpp new file mode 100644 index 00000000..0a947472 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asffile.cpp @@ -0,0 +1,543 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_ASF + +#include +#include +#include +#include "asffile.h" +#include "asftag.h" +#include "asfproperties.h" + +using namespace TagLib; + +class ASF::File::FilePrivate +{ +public: + FilePrivate(): + size(0), + tag(0), + properties(0), + contentDescriptionObject(0), + extendedContentDescriptionObject(0), + headerExtensionObject(0), + metadataObject(0), + metadataLibraryObject(0) {} + unsigned long long size; + ASF::Tag *tag; + ASF::Properties *properties; + List objects; + ASF::File::ContentDescriptionObject *contentDescriptionObject; + ASF::File::ExtendedContentDescriptionObject *extendedContentDescriptionObject; + ASF::File::HeaderExtensionObject *headerExtensionObject; + ASF::File::MetadataObject *metadataObject; + ASF::File::MetadataLibraryObject *metadataLibraryObject; +}; + +static ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); +static ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16); +static ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16); +static ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); +static ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16); +static ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16); +static ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16); +static ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16); + +class ASF::File::BaseObject +{ +public: + ByteVector data; + virtual ~BaseObject() {} + virtual ByteVector guid() = 0; + virtual void parse(ASF::File *file, unsigned int size); + virtual ByteVector render(ASF::File *file); +}; + +class ASF::File::UnknownObject : public ASF::File::BaseObject +{ + ByteVector myGuid; +public: + UnknownObject(const ByteVector &guid); + ByteVector guid(); +}; + +class ASF::File::FilePropertiesObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); +}; + +class ASF::File::StreamPropertiesObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); +}; + +class ASF::File::ContentDescriptionObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::ExtendedContentDescriptionObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::MetadataObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::MetadataLibraryObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::HeaderExtensionObject : public ASF::File::BaseObject +{ +public: + List objects; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +void ASF::File::BaseObject::parse(ASF::File *file, unsigned int size) +{ + data.clear(); + if (size > 24 && size <= (unsigned int)(file->length())) + data = file->readBlock(size - 24); + else + data = ByteVector::null; +} + +ByteVector ASF::File::BaseObject::render(ASF::File * /*file*/) +{ + return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data; +} + +ASF::File::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) +{ +} + +ByteVector ASF::File::UnknownObject::guid() +{ + return myGuid; +} + +ByteVector ASF::File::FilePropertiesObject::guid() +{ + return filePropertiesGuid; +} + +void ASF::File::FilePropertiesObject::parse(ASF::File *file, uint size) +{ + BaseObject::parse(file, size); + file->d->properties->setLength((int)(data.mid(40, 8).toLongLong(false) / 10000000L - data.mid(56, 8).toLongLong(false) / 1000L)); +} + +ByteVector ASF::File::StreamPropertiesObject::guid() +{ + return streamPropertiesGuid; +} + +void ASF::File::StreamPropertiesObject::parse(ASF::File *file, uint size) +{ + BaseObject::parse(file, size); + file->d->properties->setChannels(data.mid(56, 2).toShort(false)); + file->d->properties->setSampleRate(data.mid(58, 4).toUInt(false)); + file->d->properties->setBitrate(data.mid(62, 4).toUInt(false) * 8 / 1000); +} + +ByteVector ASF::File::ContentDescriptionObject::guid() +{ + return contentDescriptionGuid; +} + +void ASF::File::ContentDescriptionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->contentDescriptionObject = this; + int titleLength = file->readWORD(); + int artistLength = file->readWORD(); + int copyrightLength = file->readWORD(); + int commentLength = file->readWORD(); + int ratingLength = file->readWORD(); + file->d->tag->setTitle(file->readString(titleLength)); + file->d->tag->setArtist(file->readString(artistLength)); + file->d->tag->setCopyright(file->readString(copyrightLength)); + file->d->tag->setComment(file->readString(commentLength)); + file->d->tag->setRating(file->readString(ratingLength)); +} + +ByteVector ASF::File::ContentDescriptionObject::render(ASF::File *file) +{ + ByteVector v1 = file->renderString(file->d->tag->title()); + ByteVector v2 = file->renderString(file->d->tag->artist()); + ByteVector v3 = file->renderString(file->d->tag->copyright()); + ByteVector v4 = file->renderString(file->d->tag->comment()); + ByteVector v5 = file->renderString(file->d->tag->rating()); + data.clear(); + data.append(ByteVector::fromShort(v1.size(), false)); + data.append(ByteVector::fromShort(v2.size(), false)); + data.append(ByteVector::fromShort(v3.size(), false)); + data.append(ByteVector::fromShort(v4.size(), false)); + data.append(ByteVector::fromShort(v5.size(), false)); + data.append(v1); + data.append(v2); + data.append(v3); + data.append(v4); + data.append(v5); + return BaseObject::render(file); +} + +ByteVector ASF::File::ExtendedContentDescriptionObject::guid() +{ + return extendedContentDescriptionGuid; +} + +void ASF::File::ExtendedContentDescriptionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->extendedContentDescriptionObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector ASF::File::ExtendedContentDescriptionObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector ASF::File::MetadataObject::guid() +{ + return metadataGuid; +} + +void ASF::File::MetadataObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->metadataObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 1); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector ASF::File::MetadataObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector ASF::File::MetadataLibraryObject::guid() +{ + return metadataLibraryGuid; +} + +void ASF::File::MetadataLibraryObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->metadataLibraryObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 2); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector ASF::File::MetadataLibraryObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector ASF::File::HeaderExtensionObject::guid() +{ + return headerExtensionGuid; +} + +void ASF::File::HeaderExtensionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->headerExtensionObject = this; + file->seek(18, File::Current); + long long dataSize = file->readDWORD(); + long long dataPos = 0; + while(dataPos < dataSize) { + ByteVector guid = file->readBlock(16); + long long size = file->readQWORD(); + BaseObject *obj; + if(guid == metadataGuid) { + obj = new MetadataObject(); + } + else if(guid == metadataLibraryGuid) { + obj = new MetadataLibraryObject(); + } + else { + obj = new UnknownObject(guid); + } + obj->parse(file, size); + objects.append(obj); + dataPos += size; + } +} + +ByteVector ASF::File::HeaderExtensionObject::render(ASF::File *file) +{ + data.clear(); + for(unsigned int i = 0; i < objects.size(); i++) { + data.append(objects[i]->render(file)); + } + data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data; + return BaseObject::render(file); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) + : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +ASF::File::~File() +{ + for(unsigned int i = 0; i < d->objects.size(); i++) { + delete d->objects[i]; + } + if(d->tag) { + delete d->tag; + } + if(d->properties) { + delete d->properties; + } + delete d; +} + +ASF::Tag *ASF::File::tag() const +{ + return d->tag; +} + +ASF::Properties *ASF::File::audioProperties() const +{ + return d->properties; +} + +void ASF::File::read(bool /*readProperties*/, Properties::ReadStyle /*propertiesStyle*/) +{ + if(!isValid()) + return; + + ByteVector guid = readBlock(16); + if(guid != headerGuid) { + debug("ASF: Not an ASF file."); + return; + } + + d->tag = new ASF::Tag(); + d->properties = new ASF::Properties(); + + d->size = readQWORD(); + int numObjects = readDWORD(); + seek(2, Current); + + for(int i = 0; i < numObjects; i++) { + ByteVector guid = readBlock(16); + long size = (long)readQWORD(); + BaseObject *obj; + if(guid == filePropertiesGuid) { + obj = new FilePropertiesObject(); + } + else if(guid == streamPropertiesGuid) { + obj = new StreamPropertiesObject(); + } + else if(guid == contentDescriptionGuid) { + obj = new ContentDescriptionObject(); + } + else if(guid == extendedContentDescriptionGuid) { + obj = new ExtendedContentDescriptionObject(); + } + else if(guid == headerExtensionGuid) { + obj = new HeaderExtensionObject(); + } + else { + obj = new UnknownObject(guid); + } + obj->parse(this, size); + d->objects.append(obj); + } +} + +bool ASF::File::save() +{ + if(readOnly()) { + debug("ASF: File is read-only."); + return false; + } + + if(!d->contentDescriptionObject) { + d->contentDescriptionObject = new ContentDescriptionObject(); + d->objects.append(d->contentDescriptionObject); + } + if(!d->extendedContentDescriptionObject) { + d->extendedContentDescriptionObject = new ExtendedContentDescriptionObject(); + d->objects.append(d->extendedContentDescriptionObject); + } + if(!d->headerExtensionObject) { + d->headerExtensionObject = new HeaderExtensionObject(); + d->objects.append(d->headerExtensionObject); + } + if(!d->metadataObject) { + d->metadataObject = new MetadataObject(); + d->headerExtensionObject->objects.append(d->metadataObject); + } + if(!d->metadataLibraryObject) { + d->metadataLibraryObject = new MetadataLibraryObject(); + d->headerExtensionObject->objects.append(d->metadataLibraryObject); + } + + ASF::AttributeListMap::ConstIterator it = d->tag->attributeListMap().begin(); + for(; it != d->tag->attributeListMap().end(); it++) { + const String &name = it->first; + const AttributeList &attributes = it->second; + bool inExtendedContentDescriptionObject = false; + bool inMetadataObject = false; + for(unsigned int j = 0; j < attributes.size(); j++) { + const Attribute &attribute = attributes[j]; + bool largeValue = attribute.dataSize() > 65535; + if(!inExtendedContentDescriptionObject && !largeValue && attribute.language() == 0 && attribute.stream() == 0) { + d->extendedContentDescriptionObject->attributeData.append(attribute.render(name)); + inExtendedContentDescriptionObject = true; + } + else if(!inMetadataObject && !largeValue && attribute.language() == 0 && attribute.stream() != 0) { + d->metadataObject->attributeData.append(attribute.render(name, 1)); + inMetadataObject = true; + } + else { + d->metadataLibraryObject->attributeData.append(attribute.render(name, 2)); + } + } + } + + ByteVector data; + for(unsigned int i = 0; i < d->objects.size(); i++) { + data.append(d->objects[i]->render(this)); + } + data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data; + insert(data, 0, d->size); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +int ASF::File::readBYTE() +{ + ByteVector v = readBlock(1); + return v[0]; +} + +int ASF::File::readWORD() +{ + ByteVector v = readBlock(2); + return v.toUShort(false); +} + +unsigned int ASF::File::readDWORD() +{ + ByteVector v = readBlock(4); + return v.toUInt(false); +} + +long long ASF::File::readQWORD() +{ + ByteVector v = readBlock(8); + return v.toLongLong(false); +} + +String ASF::File::readString(int length) +{ + ByteVector data = readBlock(length); + unsigned int size = data.size(); + while (size >= 2) { + if(data[size - 1] != '\0' || data[size - 2] != '\0') { + break; + } + size -= 2; + } + if(size != data.size()) { + data.resize(size); + } + return String(data, String::UTF16LE); +} + +ByteVector ASF::File::renderString(const String &str, bool includeLength) +{ + ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false); + if(includeLength) { + data = ByteVector::fromShort(data.size(), false) + data; + } + return data; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asffile.h b/Plugins/PluginNowPlaying/taglib/asf/asffile.h new file mode 100644 index 00000000..9242aa68 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asffile.h @@ -0,0 +1,120 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFFILE_H +#define TAGLIB_ASFFILE_H + +#include "tag.h" +#include "tfile.h" +#include "taglib_export.h" +#include "asfproperties.h" +#include "asftag.h" + +namespace TagLib { + + //! An implementation of ASF (WMA) metadata + namespace ASF { + + /*! + * This implements and provides an interface for ASF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to ASF files. + */ + class TAGLIB_EXPORT File : public TagLib::File + { + public: + + /*! + * Contructs an ASF 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 In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the ASF tag of the file. + * + * ASF::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the ASF::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + virtual Tag *tag() const; + + /*! + * Returns the ASF audio properties for this file. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + private: + + int readBYTE(); + int readWORD(); + unsigned int readDWORD(); + long long readQWORD(); + static ByteVector renderString(const String &str, bool includeLength = false); + String readString(int len); + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + friend class Attribute; + friend class Picture; + + class BaseObject; + class UnknownObject; + class FilePropertiesObject; + class StreamPropertiesObject; + class ContentDescriptionObject; + class ExtendedContentDescriptionObject; + class HeaderExtensionObject; + class MetadataObject; + class MetadataLibraryObject; + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asfpicture.cpp b/Plugins/PluginNowPlaying/taglib/asf/asfpicture.cpp new file mode 100644 index 00000000..551229b5 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asfpicture.cpp @@ -0,0 +1,185 @@ +/************************************************************************** + copyright : (C) 2010 by Anton Sergunov + email : setosha@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_ASF + +#include +#include +#include "asfattribute.h" +#include "asffile.h" +#include "asfpicture.h" + +using namespace TagLib; + +class ASF::Picture::PicturePriavte : public RefCounter +{ +public: + bool valid; + Type type; + String mimeType; + String description; + ByteVector picture; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Picture class members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Picture::Picture() +{ + d = new PicturePriavte(); + d->valid = true; +} + +ASF::Picture::Picture(const Picture& other) + : d(other.d) +{ + d->ref(); +} + +ASF::Picture::~Picture() +{ + if(d->deref()) + delete d; +} + +bool ASF::Picture::isValid() const +{ + return d->valid; +} + +String ASF::Picture::mimeType() const +{ + return d->mimeType; +} + +void ASF::Picture::setMimeType(const String &value) +{ + d->mimeType = value; +} + +ASF::Picture::Type ASF::Picture::type() const +{ + return d->type; +} + +void ASF::Picture::setType(const ASF::Picture::Type& t) +{ + d->type = t; +} + +String ASF::Picture::description() const +{ + return d->description; +} + +void ASF::Picture::setDescription(const String &desc) +{ + d->description = desc; +} + +ByteVector ASF::Picture::picture() const +{ + return d->picture; +} + +void ASF::Picture::setPicture(const ByteVector &p) +{ + d->picture = p; +} + +int ASF::Picture::dataSize() const +{ + return + 9 + (d->mimeType.length() + d->description.length()) * 2 + + d->picture.size(); +} + +ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other) +{ + if(other.d != d) { + if(d->deref()) + delete d; + d = other.d; + d->ref(); + } + return *this; +} + +ByteVector ASF::Picture::render() const +{ + if(!isValid()) + return ByteVector::null; + return + ByteVector((char)d->type) + + ByteVector::fromUInt(d->picture.size(), false) + + ASF::File::renderString(d->mimeType) + + ASF::File::renderString(d->description) + + d->picture; +} + +void ASF::Picture::parse(const ByteVector& bytes) +{ + d->valid = false; + if(bytes.size() < 9) + return; + int pos = 0; + d->type = (Type)bytes[0]; ++pos; + uint dataLen = bytes.mid(pos, 4).toUInt(false); pos+=4; + + const ByteVector nullStringTerminator(2, 0); + + int endPos = bytes.find(nullStringTerminator, pos, 2); + if(endPos < 0) + return; + d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE); + pos = endPos+2; + + endPos = bytes.find(nullStringTerminator, pos, 2); + if(endPos < 0) + return; + d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE); + pos = endPos+2; + + if(dataLen + pos != bytes.size()) + return; + + d->picture = bytes.mid(pos, dataLen); + d->valid = true; + return; +} + +ASF::Picture ASF::Picture::fromInvalid() +{ + Picture ret; + ret.d->valid = false; + return ret; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asfpicture.h b/Plugins/PluginNowPlaying/taglib/asf/asfpicture.h new file mode 100644 index 00000000..5c1bfbfd --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asfpicture.h @@ -0,0 +1,217 @@ +/************************************************************************** + copyright : (C) 2010 by Anton Sergunov + email : setosha@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef ASFPICTURE_H +#define ASFPICTURE_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "attachedpictureframe.h" + +namespace TagLib +{ + namespace ASF + { + + //! An ASF attached picture interface implementation + + /*! + * This is an implementation of ASF attached pictures interface. Pictures may be + * included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture + * attribute in a single tag). These pictures are usually in either JPEG or + * PNG format. + * \see Attribute::toPicture() + * \see Attribute::Attribute(const Picture& picture) + */ + class TAGLIB_EXPORT Picture { + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + /*! + * Constructs an empty picture. + */ + Picture(); + + /*! + * Construct an picture as a copy of \a other. + */ + Picture(const Picture& other); + + /*! + * Destroys the picture. + */ + virtual ~Picture(); + + /*! + * Copies the contents of \a other into this picture. + */ + Picture& operator=(const Picture& other); + + /*! + * Returns true if Picture stores valid picture + */ + bool isValid() const; + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + void setMimeType(const String &value); + + /*! + * Returns the type of the image. + * + * \see Type + * \see setType() + */ + Type type() const; + + /*! + * Sets the type for the image. + * + * \see Type + * \see type() + */ + void setType(const ASF::Picture::Type& t); + + /*! + * Returns a text description of the image. + * + * \see setDescription() + */ + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + * + * \see description() + */ + void setDescription(const String &desc); + + /*! + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ + ByteVector picture() const; + + /*! + * Sets the image data to \a p. \a p should be of the type specified in + * this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ + void setPicture(const ByteVector &p); + + /*! + * Returns picture as binary raw data \a value + */ + ByteVector render() const; + + /*! + * Returns picture as binary raw data \a value + */ + int dataSize() const; + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + void parse(const ByteVector& ); + static Picture fromInvalid(); + friend class Attribute; +#endif + private: + struct PicturePriavte; + PicturePriavte *d; + }; + } +} + +#endif // ASFPICTURE_H diff --git a/Plugins/PluginNowPlaying/taglib/asf/asfproperties.cpp b/Plugins/PluginNowPlaying/taglib/asf/asfproperties.cpp new file mode 100644 index 00000000..02d2d942 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asfproperties.cpp @@ -0,0 +1,107 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_ASF + +#include +#include +#include "asfproperties.h" + +using namespace TagLib; + +class ASF::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0) {} + int length; + int bitrate; + int sampleRate; + int channels; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Properties::Properties() : AudioProperties(AudioProperties::Average) +{ + d = new PropertiesPrivate; +} + +ASF::Properties::~Properties() +{ + if(d) + delete d; +} + +int ASF::Properties::length() const +{ + return d->length; +} + +int ASF::Properties::bitrate() const +{ + return d->bitrate; +} + +int ASF::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int ASF::Properties::channels() const +{ + return d->channels; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void ASF::Properties::setLength(int length) +{ + d->length = length; +} + +void ASF::Properties::setBitrate(int length) +{ + d->bitrate = length; +} + +void ASF::Properties::setSampleRate(int length) +{ + d->sampleRate = length; +} + +void ASF::Properties::setChannels(int length) +{ + d->channels = length; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asfproperties.h b/Plugins/PluginNowPlaying/taglib/asf/asfproperties.h new file mode 100644 index 00000000..290eac77 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asfproperties.h @@ -0,0 +1,74 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFPROPERTIES_H +#define TAGLIB_ASFPROPERTIES_H + +#include "audioproperties.h" +#include "tstring.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ASF { + + //! An implementation of ASF audio properties + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + + /*! + * Create an instance of ASF::Properties. + */ + Properties(); + + /*! + * Destroys this ASF::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + +#ifndef DO_NOT_DOCUMENT + void setLength(int value); + void setBitrate(int value); + void setSampleRate(int value); + void setChannels(int value); +#endif + + private: + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asftag.cpp b/Plugins/PluginNowPlaying/taglib/asf/asftag.cpp new file mode 100644 index 00000000..c77646e1 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asftag.cpp @@ -0,0 +1,201 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_ASF + +#include "asftag.h" + +using namespace TagLib; + +class ASF::Tag::TagPrivate +{ +public: + String title; + String artist; + String copyright; + String comment; + String rating; + AttributeListMap attributeListMap; +}; + +ASF::Tag::Tag() +: TagLib::Tag() +{ + d = new TagPrivate; +} + +ASF::Tag::~Tag() +{ + if(d) + delete d; +} + +String ASF::Tag::title() const +{ + return d->title; +} + +String ASF::Tag::artist() const +{ + return d->artist; +} + +String ASF::Tag::album() const +{ + if(d->attributeListMap.contains("WM/AlbumTitle")) + return d->attributeListMap["WM/AlbumTitle"][0].toString(); + return String::null; +} + +String ASF::Tag::copyright() const +{ + return d->copyright; +} + +String ASF::Tag::comment() const +{ + return d->comment; +} + +String ASF::Tag::rating() const +{ + return d->rating; +} + +unsigned int ASF::Tag::year() const +{ + if(d->attributeListMap.contains("WM/Year")) + return d->attributeListMap["WM/Year"][0].toString().toInt(); + return 0; +} + +unsigned int ASF::Tag::track() const +{ + if(d->attributeListMap.contains("WM/TrackNumber")) { + const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0]; + if(attr.type() == ASF::Attribute::DWordType) + return attr.toUInt(); + else + return attr.toString().toInt(); + } + if(d->attributeListMap.contains("WM/Track")) + return d->attributeListMap["WM/Track"][0].toUInt(); + return 0; +} + +String ASF::Tag::genre() const +{ + if(d->attributeListMap.contains("WM/Genre")) + return d->attributeListMap["WM/Genre"][0].toString(); + return String::null; +} + +void ASF::Tag::setTitle(const String &value) +{ + d->title = value; +} + +void ASF::Tag::setArtist(const String &value) +{ + d->artist = value; +} + +void ASF::Tag::setCopyright(const String &value) +{ + d->copyright = value; +} + +void ASF::Tag::setComment(const String &value) +{ + d->comment = value; +} + +void ASF::Tag::setRating(const String &value) +{ + d->rating = value; +} + +void ASF::Tag::setAlbum(const String &value) +{ + setAttribute("WM/AlbumTitle", value); +} + +void ASF::Tag::setGenre(const String &value) +{ + setAttribute("WM/Genre", value); +} + +void ASF::Tag::setYear(uint value) +{ + setAttribute("WM/Year", String::number(value)); +} + +void ASF::Tag::setTrack(uint value) +{ + setAttribute("WM/TrackNumber", String::number(value)); +} + +ASF::AttributeListMap& ASF::Tag::attributeListMap() +{ + return d->attributeListMap; +} + +void ASF::Tag::removeItem(const String &key) +{ + AttributeListMap::Iterator it = d->attributeListMap.find(key); + if(it != d->attributeListMap.end()) + d->attributeListMap.erase(it); +} + +void ASF::Tag::setAttribute(const String &name, const Attribute &attribute) +{ + AttributeList value; + value.append(attribute); + d->attributeListMap.insert(name, value); +} + +void ASF::Tag::addAttribute(const String &name, const Attribute &attribute) +{ + if(d->attributeListMap.contains(name)) { + d->attributeListMap[name].append(attribute); + } + else { + setAttribute(name, attribute); + } +} + +bool ASF::Tag::isEmpty() const +{ + return TagLib::Tag::isEmpty() && + copyright().isEmpty() && + rating().isEmpty() && + d->attributeListMap.isEmpty(); +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/asf/asftag.h b/Plugins/PluginNowPlaying/taglib/asf/asftag.h new file mode 100644 index 00000000..a6c49df5 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/asf/asftag.h @@ -0,0 +1,186 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFTAG_H +#define TAGLIB_ASFTAG_H + +#include "tag.h" +#include "tlist.h" +#include "tmap.h" +#include "taglib_export.h" +#include "asfattribute.h" + +namespace TagLib { + + namespace ASF { + + typedef List AttributeList; + typedef Map AttributeListMap; + + class TAGLIB_EXPORT Tag : public TagLib::Tag { + + friend class File; + + public: + + Tag(); + + virtual ~Tag(); + + /*! + * Returns the track name. + */ + virtual String title() const; + + /*! + * Returns the artist name. + */ + virtual String artist() const; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const; + + /*! + * Returns the track comment. + */ + virtual String comment() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const; + + /*! + * Returns the rating. + */ + virtual String rating() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String copyright() const; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual uint year() const; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual uint track() const; + + /*! + * Sets the title to \a s. + */ + virtual void setTitle(const String &s); + + /*! + * Sets the artist to \a s. + */ + virtual void setArtist(const String &s); + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s); + + /*! + * Sets the comment to \a s. + */ + virtual void setComment(const String &s); + + /*! + * Sets the rating to \a s. + */ + virtual void setRating(const String &s); + + /*! + * Sets the copyright to \a s. + */ + virtual void setCopyright(const String &s); + + /*! + * Sets the genre to \a s. + */ + virtual void setGenre(const String &s); + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(uint i); + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(uint i); + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Returns a reference to the item list map. This is an AttributeListMap of + * all of the items in the tag. + * + * This is the most powerfull structure for accessing the items of the tag. + */ + AttributeListMap &attributeListMap(); + + /*! + * Removes the \a key attribute from the tag + */ + void removeItem(const String &name); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be replaced. + */ + void setAttribute(const String &name, const Attribute &attribute); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be added to the list. + */ + void addAttribute(const String &name, const Attribute &attribute); + + private: + + class TagPrivate; + TagPrivate *d; + }; + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/audioproperties.cpp b/Plugins/PluginNowPlaying/taglib/audioproperties.cpp new file mode 100644 index 00000000..298b97da --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/audioproperties.cpp @@ -0,0 +1,51 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "audioproperties.h" + +using namespace TagLib; + +class AudioProperties::AudioPropertiesPrivate +{ + +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +AudioProperties::~AudioProperties() +{ + +} + +//////////////////////////////////////////////////////////////////////////////// +// protected methods +//////////////////////////////////////////////////////////////////////////////// + +AudioProperties::AudioProperties(ReadStyle) +{ + +} diff --git a/Plugins/PluginNowPlaying/taglib/audioproperties.h b/Plugins/PluginNowPlaying/taglib/audioproperties.h new file mode 100644 index 00000000..e9844fa0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/audioproperties.h @@ -0,0 +1,110 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIOPROPERTIES_H +#define TAGLIB_AUDIOPROPERTIES_H + +#include "taglib_export.h" + +namespace TagLib { + + //! A simple, abstract interface to common audio properties + + /*! + * The values here are common to most audio formats. For more specific, codec + * dependant values, please see see the subclasses APIs. This is meant to + * compliment the TagLib::File and TagLib::Tag APIs in providing a simple + * interface that is sufficient for most applications. + */ + + class TAGLIB_EXPORT AudioProperties + { + public: + + /*! + * Reading audio properties from a file can sometimes be very time consuming + * and for the most accurate results can often involve reading the entire + * file. Because in many situations speed is critical or the accuracy of the + * values is not particularly important this allows the level of desired + * accuracy to be set. + */ + enum ReadStyle { + //! Read as little of the file as possible + Fast, + //! Read more of the file and make better values guesses + Average, + //! Read as much of the file as needed to report accurate values + Accurate + }; + + /*! + * Destroys this AudioProperties instance. + */ + virtual ~AudioProperties(); + + /*! + * Returns the length of the file in seconds. + */ + virtual int length() const = 0; + + /*! + * Returns the most appropriate bit rate for the file in kb/s. For constant + * bitrate formats this is simply the bitrate of the file. For variable + * bitrate formats this is either the average or nominal bitrate. + */ + virtual int bitrate() const = 0; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const = 0; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const = 0; + + protected: + + /*! + * Construct an audio properties instance. This is protected as this class + * should not be instantiated directly, but should be instantiated via its + * subclasses and can be fetched from the FileRef or File APIs. + * + * \see ReadStyle + */ + AudioProperties(ReadStyle style); + + private: + AudioProperties(const AudioProperties &); + AudioProperties &operator=(const AudioProperties &); + + class AudioPropertiesPrivate; + AudioPropertiesPrivate *d; + }; + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/config.h b/Plugins/PluginNowPlaying/taglib/config.h new file mode 100644 index 00000000..a1cd1701 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/config.h @@ -0,0 +1,2 @@ +#define WITH_ASF 1 +#define WITH_MP4 1 diff --git a/Plugins/PluginNowPlaying/taglib/fileref.cpp b/Plugins/PluginNowPlaying/taglib/fileref.cpp new file mode 100644 index 00000000..595e0d60 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/fileref.cpp @@ -0,0 +1,266 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + (added APE file support) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "fileref.h" +#include "asffile.h" +#include "mpegfile.h" +#include "vorbisfile.h" +#include "flacfile.h" +#include "oggflacfile.h" +#include "mpcfile.h" +#include "mp4file.h" +#include "wavpackfile.h" +//#include "speexfile.h" +//#include "trueaudiofile.h" +//#include "aifffile.h" +//#include "wavfile.h" +#include "apefile.h" + +using namespace TagLib; + +class FileRef::FileRefPrivate : public RefCounter +{ +public: + FileRefPrivate(File *f) : RefCounter(), file(f) {} + ~FileRefPrivate() { + delete file; + } + + File *file; + static List fileTypeResolvers; +}; + +List FileRef::FileRefPrivate::fileTypeResolvers; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FileRef::FileRef() +{ + d = new FileRefPrivate(0); +} + +FileRef::FileRef(FileName fileName, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) +{ + d = new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle)); +} + +FileRef::FileRef(File *file) +{ + d = new FileRefPrivate(file); +} + +FileRef::FileRef(const FileRef &ref) : d(ref.d) +{ + d->ref(); +} + +FileRef::~FileRef() +{ + if(d->deref()) + delete d; +} + +Tag *FileRef::tag() const +{ + if(isNull()) { + debug("FileRef::tag() - Called without a valid file."); + return 0; + } + return d->file->tag(); +} + +AudioProperties *FileRef::audioProperties() const +{ + if(isNull()) { + debug("FileRef::audioProperties() - Called without a valid file."); + return 0; + } + return d->file->audioProperties(); +} + +File *FileRef::file() const +{ + return d->file; +} + +bool FileRef::save() +{ + if(isNull()) { + debug("FileRef::save() - Called without a valid file."); + return false; + } + return d->file->save(); +} + +const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static +{ + FileRefPrivate::fileTypeResolvers.prepend(resolver); + return resolver; +} + +StringList FileRef::defaultFileExtensions() +{ + StringList l; + + l.append("ogg"); + l.append("flac"); + l.append("oga"); + l.append("mp3"); + l.append("mpc"); + l.append("wv"); +//l.append("spx"); +//l.append("tta"); +#ifdef TAGLIB_WITH_MP4 + l.append("m4a"); + l.append("m4b"); + l.append("m4p"); + l.append("3g2"); + l.append("mp4"); +#endif +#ifdef TAGLIB_WITH_ASF + l.append("wma"); + l.append("asf"); +#endif +//l.append("aif"); +//l.append("aiff"); +//l.append("wav"); + l.append("ape"); + + return l; +} + +bool FileRef::isNull() const +{ + return !d->file || !d->file->isValid(); +} + +FileRef &FileRef::operator=(const FileRef &ref) +{ + if(&ref == this) + return *this; + + if(d->deref()) + delete d; + + d = ref.d; + d->ref(); + + return *this; +} + +bool FileRef::operator==(const FileRef &ref) const +{ + return ref.d->file == d->file; +} + +bool FileRef::operator!=(const FileRef &ref) const +{ + return ref.d->file != d->file; +} + +File *FileRef::create(FileName fileName, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) // static +{ + + List::ConstIterator it = FileRefPrivate::fileTypeResolvers.begin(); + + for(; it != FileRefPrivate::fileTypeResolvers.end(); ++it) { + File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle); + if(file) + return file; + } + + // Ok, this is really dumb for now, but it works for testing. + + String s; + +#ifdef _WIN32 + s = (wcslen((const wchar_t *) fileName) > 0) ? String((const wchar_t *) fileName) : String((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 + // that a default file type resolver is created. + + int pos = s.rfind("."); + if(pos != -1) { + String ext = s.substr(pos + 1).upper(); + if(ext == "MP3") + return new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "OGG") + return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "OGA") { + /* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */ + File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle); + if (file->isValid()) + return file; + delete file; + return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle); + } + if(ext == "FLAC") + return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "MPC") + return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "WV") + return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle); +// if(ext == "SPX") +// return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle); +// if(ext == "TTA") +// return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle); +#ifdef TAGLIB_WITH_MP4 + if(ext == "M4A" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2") + return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle); +#endif +#ifdef TAGLIB_WITH_ASF + if(ext == "WMA" || ext == "ASF") + return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle); +#endif +// if(ext == "AIF" || ext == "AIFF") +// return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle); +// if(ext == "WAV") +// return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "APE") + return new APE::File(fileName, readAudioProperties, audioPropertiesStyle); + } + + return 0; +} diff --git a/Plugins/PluginNowPlaying/taglib/fileref.h b/Plugins/PluginNowPlaying/taglib/fileref.h new file mode 100644 index 00000000..0f0c21a4 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/fileref.h @@ -0,0 +1,263 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FILEREF_H +#define TAGLIB_FILEREF_H + +#include "tfile.h" +#include "tstringlist.h" + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + class Tag; + + //! This class provides a simple abstraction for creating and handling files + + /*! + * FileRef exists to provide a minimal, generic and value-based wrapper around + * a File. It is lightweight and implicitly shared, and as such suitable for + * pass-by-value use. This hides some of the uglier details of TagLib::File + * and the non-generic portions of the concrete file implementations. + * + * This class is useful in a "simple usage" situation where it is desirable + * to be able to get and set some of the tag information that is similar + * across file types. + * + * Also note that it is probably a good idea to plug this into your mime + * type system rather than using the constructor that accepts a file name using + * the FileTypeResolver. + * + * \see FileTypeResolver + * \see addFileTypeResolver() + */ + + class TAGLIB_EXPORT FileRef + { + public: + + //! A class for pluggable file type resolution. + + /*! + * This class is used to add extend TagLib's very basic file name based file + * type resolution. + * + * This can be accomplished with: + * + * \code + * + * class MyFileTypeResolver : FileTypeResolver + * { + * TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) + * { + * if(someCheckForAnMP3File(fileName)) + * return new TagLib::MPEG::File(fileName); + * return 0; + * } + * } + * + * FileRef::addFileTypeResolver(new MyFileTypeResolver); + * + * \endcode + * + * Naturally a less contrived example would be slightly more complex. This + * can be used to plug in mime-type detection systems or to add new file types + * to TagLib. + */ + + class TAGLIB_EXPORT FileTypeResolver + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + /*! + * This method must be overridden to provide an additional file type + * resolver. If the resolver is able to determine the file type it should + * return a valid File object; if not it should return 0. + * + * \note The created file is then owned by the FileRef and should not be + * deleted. Deletion will happen automatically when the FileRef passes + * out of scope. + */ + virtual File *createFile(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average) const = 0; + }; + + /*! + * Creates a null FileRef. + */ + FileRef(); + + /*! + * Create a FileRef from \a fileName. If \a readAudioProperties is true then + * the audio properties will be read using \a audioPropertiesStyle. If + * \a readAudioProperties is false then \a audioPropertiesStyle will be + * ignored. + * + * Also see the note in the class documentation about why you may not want to + * use this method in your application. + */ + explicit FileRef(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average); + + /*! + * Contruct a FileRef using \a file. The FileRef now takes ownership of the + * pointer and will delete the File when it passes out of scope. + */ + explicit FileRef(File *file); + + /*! + * Make a copy of \a ref. + */ + FileRef(const FileRef &ref); + + /*! + * Destroys this FileRef instance. + */ + virtual ~FileRef(); + + /*! + * Returns a pointer to represented file's tag. + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + * + * \warning Do not cast it to any subclasses of \class Tag. + * Use tag returning methods of appropriate subclasses of \class File instead. + * + * \see File::tag() + */ + Tag *tag() const; + + /*! + * Returns the audio properties for this FileRef. If no audio properties + * were read then this will returns a null pointer. + */ + AudioProperties *audioProperties() const; + + /*! + * Returns a pointer to the file represented by this handler class. + * + * As a general rule this call should be avoided since if you need to work + * with file objects directly, you are probably better served instantiating + * the File subclasses (i.e. MPEG::File) manually and working with their APIs. + * + * This handle exists to provide a minimal, generic and value-based + * wrapper around a File. Accessing the file directly generally indicates + * a moving away from this simplicity (and into things beyond the scope of + * FileRef). + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + */ + File *file() const; + + /*! + * Saves the file. Returns true on success. + */ + bool save(); + + /*! + * Adds a FileTypeResolver to the list of those used by TagLib. Each + * additional FileTypeResolver is added to the front of a list of resolvers + * that are tried. If the FileTypeResolver returns zero the next resolver + * is tried. + * + * Returns a pointer to the added resolver (the same one that's passed in -- + * this is mostly so that static inialializers have something to use for + * assignment). + * + * \see FileTypeResolver + */ + static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver); + + /*! + * As is mentioned elsewhere in this class's documentation, the default file + * type resolution code provided by TagLib only works by comparing file + * extensions. + * + * This method returns the list of file extensions that are used by default. + * + * The extensions are all returned in lowercase, though the comparison used + * by TagLib for resolution is case-insensitive. + * + * \note This does not account for any additional file type resolvers that + * are plugged in. Also note that this is not intended to replace a propper + * mime-type resolution system, but is just here for reference. + * + * \see FileTypeResolver + */ + static StringList defaultFileExtensions(); + + /*! + * Returns true if the file (and as such other pointers) are null. + */ + bool isNull() const; + + /*! + * Assign the file pointed to by \a ref to this FileRef. + */ + FileRef &operator=(const FileRef &ref); + + /*! + * Returns true if this FileRef and \a ref point to the same File object. + */ + bool operator==(const FileRef &ref) const; + + /*! + * Returns true if this FileRef and \a ref do not point to the same File + * object. + */ + bool operator!=(const FileRef &ref) const; + + /*! + * A simple implementation of file type guessing. If \a readAudioProperties + * is true then the audio properties will be read using + * \a audioPropertiesStyle. If \a readAudioProperties is false then + * \a audioPropertiesStyle will be ignored. + * + * \note You generally shouldn't use this method, but instead the constructor + * directly. + * + * \deprecated + */ + static File *create(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); + + + private: + class FileRefPrivate; + FileRefPrivate *d; + }; + +} // namespace TagLib + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacfile.cpp b/Plugins/PluginNowPlaying/taglib/flac/flacfile.cpp new file mode 100644 index 00000000..c8cc1fb8 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacfile.cpp @@ -0,0 +1,499 @@ +/*************************************************************************** + copyright : (C) 2003-2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "flacpicture.h" +#include "flacfile.h" +#include "flacmetadatablock.h" +#include "flacunknownmetadatablock.h" + +using namespace TagLib; + +namespace +{ + enum { XiphIndex = 0, ID3v2Index = 1, ID3v1Index = 2 }; + enum { MinPaddingLength = 4096 }; + enum { LastBlockFlag = 0x80 }; +} + +class FLAC::File::FilePrivate +{ +public: + FilePrivate() : + ID3v2FrameFactory(ID3v2::FrameFactory::instance()), + ID3v2Location(-1), + ID3v2OriginalSize(0), + ID3v1Location(-1), + properties(0), + flacStart(0), + streamStart(0), + streamLength(0), + scanned(false), + hasXiphComment(false), + hasID3v2(false), + hasID3v1(false) + { + } + + ~FilePrivate() + { + for(uint i = 0; i < blocks.size(); i++) { + delete blocks[i]; + } + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + long ID3v2Location; + uint ID3v2OriginalSize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; + ByteVector streamInfoData; + ByteVector xiphCommentData; + List blocks; + + long flacStart; + long streamStart; + long streamLength; + bool scanned; + + bool hasXiphComment; + bool hasID3v2; + bool hasID3v1; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FLAC::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate; + d->ID3v2FrameFactory = frameFactory; + read(readProperties, propertiesStyle); +} + +FLAC::File::~File() +{ + delete d; +} + +TagLib::Tag *FLAC::File::tag() const +{ + return &d->tag; +} + +FLAC::Properties *FLAC::File::audioProperties() const +{ + return d->properties; +} + + +bool FLAC::File::save() +{ + if(readOnly()) { + debug("FLAC::File::save() - Cannot save to a read only file."); + return false; + } + + if(!isValid()) { + debug("FLAC::File::save() -- Trying to save invalid file."); + return false; + } + + // Create new vorbis comments + + Tag::duplicate(&d->tag, xiphComment(true), true); + + d->xiphCommentData = xiphComment()->render(false); + + // Replace metadata blocks + + bool foundVorbisCommentBlock = false; + List newBlocks; + for(uint i = 0; i < d->blocks.size(); i++) { + MetadataBlock *block = d->blocks[i]; + if(block->code() == MetadataBlock::VorbisComment) { + // Set the new Vorbis Comment block + block = new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData); + foundVorbisCommentBlock = true; + } + if(block->code() == MetadataBlock::Padding) { + continue; + } + newBlocks.append(block); + } + if(!foundVorbisCommentBlock) { + newBlocks.append(new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData)); + foundVorbisCommentBlock = true; + } + d->blocks = newBlocks; + + // Render data for the metadata blocks + + ByteVector data; + for(uint i = 0; i < newBlocks.size(); i++) { + FLAC::MetadataBlock *block = newBlocks[i]; + ByteVector blockData = block->render(); + ByteVector blockHeader = ByteVector::fromUInt(blockData.size()); + blockHeader[0] = block->code(); + data.append(blockHeader); + data.append(blockData); + } + + // Adjust the padding block(s) + + long originalLength = d->streamStart - d->flacStart; + int paddingLength = originalLength - data.size() - 4; + if (paddingLength < 0) { + paddingLength = MinPaddingLength; + } + ByteVector padding = ByteVector::fromUInt(paddingLength); + padding.resize(paddingLength + 4); + padding[0] = FLAC::MetadataBlock::Padding | LastBlockFlag; + data.append(padding); + + // Write the data to the file + + insert(data, d->flacStart, originalLength); + d->hasXiphComment = true; + + // Update ID3 tags + + if(ID3v2Tag()) { + if(d->hasID3v2) { + if(d->ID3v2Location < d->flacStart) + debug("FLAC::File::save() -- This can't be right -- an ID3v2 tag after the " + "start of the FLAC bytestream? Not writing the ID3v2 tag."); + else + insert(ID3v2Tag()->render(), d->ID3v2Location, d->ID3v2OriginalSize); + } + else + insert(ID3v2Tag()->render(), 0, 0); + } + + if(ID3v1Tag()) { + seek(-128, End); + writeBlock(ID3v1Tag()->render()); + } + + return true; +} + +ID3v2::Tag *FLAC::File::ID3v2Tag(bool create) +{ + if(!create || d->tag[ID3v2Index]) + return static_cast(d->tag[ID3v2Index]); + + d->tag.set(ID3v2Index, new ID3v2::Tag); + return static_cast(d->tag[ID3v2Index]); +} + +ID3v1::Tag *FLAC::File::ID3v1Tag(bool create) +{ + return d->tag.access(ID3v1Index, create); +} + +Ogg::XiphComment *FLAC::File::xiphComment(bool create) +{ + return d->tag.access(XiphIndex, create); +} + +void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + + d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory)); + + d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize(); + + if(ID3v2Tag()->header()->tagSize() <= 0) + d->tag.set(ID3v2Index, 0); + else + d->hasID3v2 = true; + } + + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + d->hasID3v1 = true; + } + + // Look for FLAC metadata, including vorbis comments + + scan(); + + if(!isValid()) + return; + + if(d->hasXiphComment) + d->tag.set(XiphIndex, new Ogg::XiphComment(xiphCommentData())); + else + d->tag.set(XiphIndex, new Ogg::XiphComment); + + if(readProperties) + d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle); +} + +ByteVector FLAC::File::streamInfoData() +{ + return isValid() ? d->streamInfoData : ByteVector(); +} + +ByteVector FLAC::File::xiphCommentData() const +{ + return (isValid() && d->hasXiphComment) ? d->xiphCommentData : ByteVector(); +} + +long FLAC::File::streamLength() +{ + return d->streamLength; +} + +void FLAC::File::scan() +{ + // Scan the metadata pages + + if(d->scanned) + return; + + if(!isValid()) + return; + + long nextBlockOffset; + + if(d->hasID3v2) + nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize); + else + nextBlockOffset = find("fLaC"); + + if(nextBlockOffset < 0) { + debug("FLAC::File::scan() -- FLAC stream not found"); + setValid(false); + return; + } + + nextBlockOffset += 4; + d->flacStart = nextBlockOffset; + + seek(nextBlockOffset); + + ByteVector header = readBlock(4); + + // Header format (from spec): + // <1> Last-metadata-block flag + // <7> BLOCK_TYPE + // 0 : STREAMINFO + // 1 : PADDING + // .. + // 4 : VORBIS_COMMENT + // .. + // <24> Length of metadata to follow + + char blockType = header[0] & 0x7f; + bool isLastBlock = (header[0] & 0x80) != 0; + uint length = header.mid(1, 3).toUInt(); + + // First block should be the stream_info metadata + + if(blockType != MetadataBlock::StreamInfo) { + debug("FLAC::File::scan() -- invalid FLAC stream"); + setValid(false); + return; + } + + d->streamInfoData = readBlock(length); + d->blocks.append(new UnknownMetadataBlock(blockType, d->streamInfoData)); + nextBlockOffset += length + 4; + + // Search through the remaining metadata + while(!isLastBlock) { + + header = readBlock(4); + blockType = header[0] & 0x7f; + isLastBlock = (header[0] & 0x80) != 0; + length = header.mid(1, 3).toUInt(); + + ByteVector data = readBlock(length); + if(data.size() != length) { + debug("FLAC::File::scan() -- FLAC stream corrupted"); + setValid(false); + return; + } + + MetadataBlock *block = 0; + + // Found the vorbis-comment + if(blockType == MetadataBlock::VorbisComment) { + if(!d->hasXiphComment) { + d->xiphCommentData = data; + d->hasXiphComment = true; + } + else { + debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, using the first one"); + } + } + else if(blockType == MetadataBlock::Picture) { + FLAC::Picture *picture = new FLAC::Picture(); + if(picture->parse(data)) { + block = picture; + } + else { + debug("FLAC::File::scan() -- invalid picture found, discarting"); + delete picture; + } + } + + if(!block) { + block = new UnknownMetadataBlock(blockType, data); + } + if(block->code() != MetadataBlock::Padding) { + d->blocks.append(block); + } + else { + delete block; + } + + nextBlockOffset += length + 4; + + if(nextBlockOffset >= File::length()) { + debug("FLAC::File::scan() -- FLAC stream corrupted"); + setValid(false); + return; + } + seek(nextBlockOffset); + } + + // End of metadata, now comes the datastream + + d->streamStart = nextBlockOffset; + d->streamLength = File::length() - d->streamStart; + + if(d->hasID3v1) + d->streamLength -= 128; + + d->scanned = true; +} + +long FLAC::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} + +long FLAC::File::findID3v2() +{ + if(!isValid()) + return -1; + + seek(0); + + if(readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} + +List FLAC::File::pictureList() +{ + List pictures; + for(uint i = 0; i < d->blocks.size(); i++) { + Picture *picture = dynamic_cast(d->blocks[i]); + if(picture) { + pictures.append(picture); + } + } + return pictures; +} + +void FLAC::File::addPicture(Picture *picture) +{ + d->blocks.append(picture); +} + +void FLAC::File::removePictures() +{ + List newBlocks; + for(uint i = 0; i < d->blocks.size(); i++) { + Picture *picture = dynamic_cast(d->blocks[i]); + if(picture) { + delete picture; + } + else { + newBlocks.append(d->blocks[i]); + } + } + d->blocks = newBlocks; +} + diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacfile.h b/Plugins/PluginNowPlaying/taglib/flac/flacfile.h new file mode 100644 index 00000000..64e67bc0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacfile.h @@ -0,0 +1,222 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACFILE_H +#define TAGLIB_FLACFILE_H + +#include "taglib_export.h" +#include "tfile.h" +#include "tlist.h" + +#include "flacpicture.h" +#include "flacproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v2 { class FrameFactory; class Tag; } + namespace ID3v1 { class Tag; } + namespace Ogg { class XiphComment; } + + //! An implementation of FLAC metadata + + /*! + * This is implementation of FLAC metadata for non-Ogg FLAC files. At some + * point when Ogg / FLAC is more common there will be a similar implementation + * under the Ogg hiearchy. + * + * This supports ID3v1, ID3v2 and Xiph style comments as well as reading stream + * properties from the file. + */ + + namespace FLAC { + + //! An implementation of TagLib::File with FLAC specific methods + + /*! + * This implements and provides an interface for FLAC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to FLAC files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * 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. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * 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. + */ + // BIC: merge with the above constructor + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be a union of XiphComment, + * ID3v1 and ID3v2 tags. + * + * \see ID3v2Tag() + * \see ID3v1Tag() + * \see XiphComment() + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the FLAC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. This will primarily save the XiphComment, but + * will also keep any old ID3-tags up to date. If the file + * has no XiphComment, one will be constructed from the ID3-tags. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist. + * + * \note The Tag is still owned by the FLAC::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. + * + * \note The Tag is still owned by the FLAC::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the XiphComment for the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid XiphComment. If \a create is true it will create + * a XiphComment if one does not exist. + * + * \note The Tag is still owned by the FLAC::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + Ogg::XiphComment *xiphComment(bool create = false); + + /*! + * Set the ID3v2::FrameFactory to something other than the default. This + * can be used to specify the way that ID3v2 frames will be interpreted + * when + * + * \see ID3v2FrameFactory + */ + void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Returns the block of data used by FLAC::Properties for parsing the + * stream properties. + * + * \deprecated This method will not be public in a future release. + */ + ByteVector streamInfoData(); // BIC: remove + + /*! + * Returns the length of the audio-stream, used by FLAC::Properties for + * calculating the bitrate. + * + * \deprecated This method will not be public in a future release. + */ + long streamLength(); // BIC: remove + + /*! + * Returns a list of pictures attached to the FLAC file. + */ + List pictureList(); + + /*! + * Remove all attached images. + */ + void removePictures(); + + /*! + * Add a new picture to the file. The file takes ownership of the + * picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ + void addPicture(Picture *picture); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findID3v2(); + long findID3v1(); + ByteVector xiphCommentData() const; + long findPaddingBreak(long nextPageOffset, long targetOffset, bool *isLast); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.cpp b/Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.cpp new file mode 100644 index 00000000..0671fc3a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.cpp @@ -0,0 +1,51 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "flacmetadatablock.h" + +using namespace TagLib; + +class FLAC::MetadataBlock::MetadataBlockPrivate +{ +public: + MetadataBlockPrivate() {} + +}; + +FLAC::MetadataBlock::MetadataBlock() +{ + d = 0; +} + +FLAC::MetadataBlock::~MetadataBlock() +{ +} + diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.h b/Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.h new file mode 100644 index 00000000..41bca318 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.h @@ -0,0 +1,75 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACMETADATABLOCK_H +#define TAGLIB_FLACMETADATABLOCK_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT MetadataBlock + { + public: + MetadataBlock(); + virtual ~MetadataBlock(); + + enum BlockType { + StreamInfo = 0, + Padding, + Application, + SeekTable, + VorbisComment, + CueSheet, + Picture + }; + + /*! + * Returns the FLAC metadata block type. + */ + virtual int code() const = 0; + + /*! + * Render the content of the block. + */ + virtual ByteVector render() const = 0; + + private: + MetadataBlock(const MetadataBlock &item); + MetadataBlock &operator=(const MetadataBlock &item); + + class MetadataBlockPrivate; + MetadataBlockPrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacpicture.cpp b/Plugins/PluginNowPlaying/taglib/flac/flacpicture.cpp new file mode 100644 index 00000000..38967199 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacpicture.cpp @@ -0,0 +1,221 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "flacpicture.h" + +using namespace TagLib; + +class FLAC::Picture::PicturePrivate +{ +public: + PicturePrivate() : + type(FLAC::Picture::Other), + width(0), + height(0), + colorDepth(0), + numColors(0) + {} + + Type type; + String mimeType; + String description; + int width; + int height; + int colorDepth; + int numColors; + ByteVector data; +}; + +FLAC::Picture::Picture() +{ + d = new PicturePrivate; +} + +FLAC::Picture::Picture(const ByteVector &data) +{ + d = new PicturePrivate; + parse(data); +} + +FLAC::Picture::~Picture() +{ + delete d; +} + +int FLAC::Picture::code() const +{ + return FLAC::MetadataBlock::Picture; +} + +bool FLAC::Picture::parse(const ByteVector &data) +{ + if(data.size() < 32) { + debug("A picture block must contain at least 5 bytes."); + return false; + } + + int pos = 0; + d->type = FLAC::Picture::Type(data.mid(pos, 4).toUInt()); + pos += 4; + uint mimeTypeLength = data.mid(pos, 4).toUInt(); + pos += 4; + if(pos + mimeTypeLength + 24 > data.size()) { + debug("Invalid picture block."); + return false; + } + d->mimeType = String(data.mid(pos, mimeTypeLength), String::UTF8); + pos += mimeTypeLength; + uint descriptionLength = data.mid(pos, 4).toUInt(); + pos += 4; + if(pos + descriptionLength + 20 > data.size()) { + debug("Invalid picture block."); + return false; + } + d->description = String(data.mid(pos, descriptionLength), String::UTF8); + pos += descriptionLength; + d->width = data.mid(pos, 4).toUInt(); + pos += 4; + d->height = data.mid(pos, 4).toUInt(); + pos += 4; + d->colorDepth = data.mid(pos, 4).toUInt(); + pos += 4; + d->numColors = data.mid(pos, 4).toUInt(); + pos += 4; + uint dataLength = data.mid(pos, 4).toUInt(); + pos += 4; + if(pos + dataLength > data.size()) { + debug("Invalid picture block."); + return false; + } + d->data = data.mid(pos, dataLength); + + return true; +} + +ByteVector FLAC::Picture::render() const +{ + ByteVector result; + result.append(ByteVector::fromUInt(d->type)); + ByteVector mimeTypeData = d->mimeType.data(String::UTF8); + result.append(ByteVector::fromUInt(mimeTypeData.size())); + result.append(mimeTypeData); + ByteVector descriptionData = d->description.data(String::UTF8); + result.append(ByteVector::fromUInt(descriptionData.size())); + result.append(descriptionData); + result.append(ByteVector::fromUInt(d->width)); + result.append(ByteVector::fromUInt(d->height)); + result.append(ByteVector::fromUInt(d->colorDepth)); + result.append(ByteVector::fromUInt(d->numColors)); + result.append(ByteVector::fromUInt(d->data.size())); + result.append(d->data); + return result; +} + +FLAC::Picture::Type FLAC::Picture::type() const +{ + return d->type; +} + +void FLAC::Picture::setType(FLAC::Picture::Type type) +{ + d->type = type; +} + +String FLAC::Picture::mimeType() const +{ + return d->mimeType; +} + +void FLAC::Picture::setMimeType(const String &mimeType) +{ + d->mimeType = mimeType; +} + +String FLAC::Picture::description() const +{ + return d->description; +} + +void FLAC::Picture::setDescription(const String &description) +{ + d->description = description; +} + +int FLAC::Picture::width() const +{ + return d->width; +} + +void FLAC::Picture::setWidth(int width) +{ + d->width = width; +} + +int FLAC::Picture::height() const +{ + return d->height; +} + +void FLAC::Picture::setHeight(int height) +{ + d->height = height; +} + +int FLAC::Picture::colorDepth() const +{ + return d->colorDepth; +} + +void FLAC::Picture::setColorDepth(int colorDepth) +{ + d->colorDepth = colorDepth; +} + +int FLAC::Picture::numColors() const +{ + return d->numColors; +} + +void FLAC::Picture::setNumColors(int numColors) +{ + d->numColors = numColors; +} + +ByteVector FLAC::Picture::data() const +{ + return d->data; +} + +void FLAC::Picture::setData(const ByteVector &data) +{ + d->data = data; +} + diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacpicture.h b/Plugins/PluginNowPlaying/taglib/flac/flacpicture.h new file mode 100644 index 00000000..b6def57a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacpicture.h @@ -0,0 +1,208 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACPICTURE_H +#define TAGLIB_FLACPICTURE_H + +#include "tlist.h" +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "flacmetadatablock.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT Picture : public MetadataBlock + { + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + Picture(); + Picture(const ByteVector &data); + ~Picture(); + + /*! + * Returns the type of the image. + */ + Type type() const; + + /*! + * Sets the type of the image. + */ + void setType(Type type); + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + void setMimeType(const String &m); + + /*! + * Returns a text description of the image. + */ + + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + */ + + void setDescription(const String &desc); + + /*! + * Returns the width of the image. + */ + int width() const; + + /*! + * Sets the width of the image. + */ + void setWidth(int w); + + /*! + * Returns the height of the image. + */ + int height() const; + + /*! + * Sets the height of the image. + */ + void setHeight(int h); + + /*! + * Returns the color depth (in bits-per-pixel) of the image. + */ + int colorDepth() const; + + /*! + * Sets the color depth (in bits-per-pixel) of the image. + */ + void setColorDepth(int depth); + + /*! + * Returns the number of colors used on the image.. + */ + int numColors() const; + + /*! + * Sets the number of colors used on the image (for indexed images). + */ + void setNumColors(int numColors); + + /*! + * Returns the image data. + */ + ByteVector data() const; + + /*! + * Sets the image data. + */ + void setData(const ByteVector &data); + + /*! + * Returns the FLAC metadata block type. + */ + int code() const; + + /*! + * Render the content to the FLAC picture block format. + */ + ByteVector render() const; + + /*! + * Parse the picture data in the FLAC picture block format. + */ + bool parse(const ByteVector &rawData); + + private: + Picture(const Picture &item); + Picture &operator=(const Picture &item); + + class PicturePrivate; + PicturePrivate *d; + }; + + typedef List PictureList; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacproperties.cpp b/Plugins/PluginNowPlaying/taglib/flac/flacproperties.cpp new file mode 100644 index 00000000..d36d26ec --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacproperties.cpp @@ -0,0 +1,158 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "flacproperties.h" +#include "flacfile.h" + +using namespace TagLib; + +class FLAC::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(ByteVector d, long st, ReadStyle s) : + data(d), + streamLength(st), + style(s), + length(0), + bitrate(0), + sampleRate(0), + sampleWidth(0), + channels(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int sampleWidth; + int channels; + ByteVector signature; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +FLAC::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file->streamInfoData(), file->streamLength(), style); + read(); +} + +FLAC::Properties::~Properties() +{ + delete d; +} + +int FLAC::Properties::length() const +{ + return d->length; +} + +int FLAC::Properties::bitrate() const +{ + return d->bitrate; +} + +int FLAC::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int FLAC::Properties::sampleWidth() const +{ + return d->sampleWidth; +} + +int FLAC::Properties::channels() const +{ + return d->channels; +} + +ByteVector FLAC::Properties::signature() const +{ + return d->signature; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void FLAC::Properties::read() +{ + if(d->data.size() < 18) { + debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes."); + return; + } + + int pos = 0; + + // Minimum block size (in samples) + pos += 2; + + // Maximum block size (in samples) + pos += 2; + + // Minimum frame size (in bytes) + pos += 3; + + // Maximum frame size (in bytes) + pos += 3; + + uint flags = d->data.mid(pos, 4).toUInt(true); + d->sampleRate = flags >> 12; + d->channels = ((flags >> 9) & 7) + 1; + d->sampleWidth = ((flags >> 4) & 31) + 1; + + // The last 4 bits are the most significant 4 bits for the 36 bit + // stream length in samples. (Audio files measured in days) + + uint highLength =d->sampleRate > 0 ? (((flags & 0xf) << 28) / d->sampleRate) << 4 : 0; + pos += 4; + + d->length = d->sampleRate > 0 ? + (d->data.mid(pos, 4).toUInt(true)) / d->sampleRate + highLength : 0; + pos += 4; + + // Uncompressed bitrate: + + //d->bitrate = ((d->sampleRate * d->channels) / 1000) * d->sampleWidth; + + // Real bitrate: + + d->bitrate = d->length > 0 ? ((d->streamLength * 8UL) / d->length) / 1000 : 0; + + d->signature = d->data.mid(pos, 32); +} diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacproperties.h b/Plugins/PluginNowPlaying/taglib/flac/flacproperties.h new file mode 100644 index 00000000..5bba6417 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacproperties.h @@ -0,0 +1,98 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACPROPERTIES_H +#define TAGLIB_FLACPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace FLAC { + + class File; + + //! An implementation of audio property reading for FLAC + + /*! + * This reads the data from an FLAC stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of FLAC::Properties with the data read from the + * ByteVector \a data. + */ + // BIC: switch to const reference + Properties(ByteVector data, long streamLength, ReadStyle style = Average); + + /*! + * Create an instance of FLAC::Properties with the data read from the + * FLAC::File \a file. + */ + // BIC: remove + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this FLAC::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns the sample width as read from the FLAC identification + * header. + */ + int sampleWidth() const; + + /*! + * Returns the MD5 signature of the uncompressed audio stream as read + * from the stream info header header. + */ + ByteVector signature() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.cpp b/Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.cpp new file mode 100644 index 00000000..96e3447f --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.cpp @@ -0,0 +1,83 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include "flacunknownmetadatablock.h" + +using namespace TagLib; + +class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate +{ +public: + UnknownMetadataBlockPrivate() : code(0) {} + + int code; + ByteVector data; +}; + +FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data) +{ + d = new UnknownMetadataBlockPrivate; + d->code = code; + //debug(String(data.toHex())); + d->data = data; +} + +FLAC::UnknownMetadataBlock::~UnknownMetadataBlock() +{ + delete d; +} + +int FLAC::UnknownMetadataBlock::code() const +{ + return d->code; +} + +void FLAC::UnknownMetadataBlock::setCode(int code) +{ + d->code = code; +} + +ByteVector FLAC::UnknownMetadataBlock::data() const +{ + return d->data; +} + +void FLAC::UnknownMetadataBlock::setData(const ByteVector &data) +{ + d->data = data; +} + +ByteVector FLAC::UnknownMetadataBlock::render() const +{ + return d->data; +} + diff --git a/Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.h b/Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.h new file mode 100644 index 00000000..3030254e --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/flac/flacunknownmetadatablock.h @@ -0,0 +1,81 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACUNKNOWNMETADATABLOCK_H +#define TAGLIB_FLACUNKNOWNMETADATABLOCK_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "flacmetadatablock.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock + { + public: + UnknownMetadataBlock(int blockType, const ByteVector &data); + ~UnknownMetadataBlock(); + + /*! + * Returns the FLAC metadata block type. + */ + int code() const; + + /*! + * Sets the FLAC metadata block type. + */ + void setCode(int code); + + /*! + * Returns the FLAC metadata block type. + */ + ByteVector data() const; + + /*! + * Sets the FLAC metadata block type. + */ + void setData(const ByteVector &data); + + /*! + * Render the content of the block. + */ + ByteVector render() const; + + private: + UnknownMetadataBlock(const MetadataBlock &item); + UnknownMetadataBlock &operator=(const MetadataBlock &item); + + class UnknownMetadataBlockPrivate; + UnknownMetadataBlockPrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4atom.cpp b/Plugins/PluginNowPlaying/taglib/mp4/mp4atom.cpp new file mode 100644 index 00000000..26d6d25a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4atom.cpp @@ -0,0 +1,197 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_MP4 + +#include +#include +#include "mp4atom.h" + +using namespace TagLib; + +const char *MP4::Atom::containers[10] = { + "moov", "udta", "mdia", "meta", "ilst", + "stbl", "minf", "moof", "traf", "trak", +}; + +MP4::Atom::Atom(File *file) +{ + offset = file->tell(); + ByteVector header = file->readBlock(8); + if (header.size() != 8) { + // The atom header must be 8 bytes long, otherwise there is either + // trailing garbage or the file is truncated + debug("MP4: Couldn't read 8 bytes of data for atom header"); + length = 0; + file->seek(0, File::End); + return; + } + + length = header.mid(0, 4).toUInt(); + + if (length == 1) { + long long longLength = file->readBlock(8).toLongLong(); + if (longLength >= 8 && longLength <= 0xFFFFFFFF) { + // The atom has a 64-bit length, but it's actually a 32-bit value + length = (long)longLength; + } + else { + debug("MP4: 64-bit atoms are not supported"); + length = 0; + file->seek(0, File::End); + return; + } + } + if (length < 8) { + debug("MP4: Invalid atom size"); + length = 0; + file->seek(0, File::End); + return; + } + + name = header.mid(4, 4); + + for(int i = 0; i < numContainers; i++) { + if(name == containers[i]) { + if(name == "meta") { + file->seek(4, File::Current); + } + while(file->tell() < offset + length) { + MP4::Atom *child = new MP4::Atom(file); + children.append(child); + if (child->length == 0) + return; + } + return; + } + } + + file->seek(offset + length); +} + +MP4::Atom::~Atom() +{ + for(unsigned int i = 0; i < children.size(); i++) { + delete children[i]; + } + children.clear(); +} + +MP4::Atom * +MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4) +{ + if(name1 == 0) { + return this; + } + for(unsigned int i = 0; i < children.size(); i++) { + if(children[i]->name == name1) { + return children[i]->find(name2, name3, name4); + } + } + return 0; +} + +MP4::AtomList +MP4::Atom::findall(const char *name, bool recursive) +{ + MP4::AtomList result; + for(unsigned int i = 0; i < children.size(); i++) { + if(children[i]->name == name) { + result.append(children[i]); + } + if(recursive) { + result.append(children[i]->findall(name, recursive)); + } + } + return result; +} + +bool +MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3) +{ + path.append(this); + if(name1 == 0) { + return true; + } + for(unsigned int i = 0; i < children.size(); i++) { + if(children[i]->name == name1) { + return children[i]->path(path, name2, name3); + } + } + return false; +} + +MP4::Atoms::Atoms(File *file) +{ + file->seek(0, File::End); + long end = file->tell(); + file->seek(0); + while(file->tell() + 8 <= end) { + MP4::Atom *atom = new MP4::Atom(file); + atoms.append(atom); + if (atom->length == 0) + break; + } +} + +MP4::Atoms::~Atoms() +{ + for(unsigned int i = 0; i < atoms.size(); i++) { + delete atoms[i]; + } + atoms.clear(); +} + +MP4::Atom * +MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4) +{ + for(unsigned int i = 0; i < atoms.size(); i++) { + if(atoms[i]->name == name1) { + return atoms[i]->find(name2, name3, name4); + } + } + return 0; +} + +MP4::AtomList +MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4) +{ + MP4::AtomList path; + for(unsigned int i = 0; i < atoms.size(); i++) { + if(atoms[i]->name == name1) { + if(!atoms[i]->path(path, name2, name3, name4)) { + path.clear(); + } + return path; + } + } + return path; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4atom.h b/Plugins/PluginNowPlaying/taglib/mp4/mp4atom.h new file mode 100644 index 00000000..7d9dac28 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4atom.h @@ -0,0 +1,77 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +// This file is not part of the public API! + +#ifndef DO_NOT_DOCUMENT + +#ifndef TAGLIB_MP4ATOM_H +#define TAGLIB_MP4ATOM_H + +#include "tfile.h" +#include "tlist.h" + +namespace TagLib { + + namespace MP4 { + + class Atom; + typedef TagLib::List AtomList; + + class Atom + { + public: + Atom(File *file); + ~Atom(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0); + AtomList findall(const char *name, bool recursive = false); + long offset; + long length; + TagLib::ByteVector name; + AtomList children; + private: + static const int numContainers = 10; + static const char *containers[10]; + }; + + //! Root-level atoms + class Atoms + { + public: + Atoms(File *file); + ~Atoms(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + AtomList path(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + AtomList atoms; + }; + + } + +} + +#endif + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.cpp b/Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.cpp new file mode 100644 index 00000000..86555fc1 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.cpp @@ -0,0 +1,89 @@ +/************************************************************************** + copyright : (C) 2009 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_MP4 + +#include +#include +#include "mp4coverart.h" + +using namespace TagLib; + +class MP4::CoverArt::CoverArtPrivate : public RefCounter +{ +public: + CoverArtPrivate() : RefCounter(), format(MP4::CoverArt::JPEG) {} + + Format format; + ByteVector data; +}; + +MP4::CoverArt::CoverArt(Format format, const ByteVector &data) +{ + d = new CoverArtPrivate; + d->format = format; + d->data = data; +} + +MP4::CoverArt::CoverArt(const CoverArt &item) : d(item.d) +{ + d->ref(); +} + +MP4::CoverArt & +MP4::CoverArt::operator=(const CoverArt &item) +{ + if(d->deref()) { + delete d; + } + d = item.d; + d->ref(); + return *this; +} + +MP4::CoverArt::~CoverArt() +{ + if(d->deref()) { + delete d; + } +} + +MP4::CoverArt::Format +MP4::CoverArt::format() const +{ + return d->format; +} + +ByteVector +MP4::CoverArt::data() const +{ + return d->data; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.h b/Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.h new file mode 100644 index 00000000..26c4f9d9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.h @@ -0,0 +1,71 @@ +/************************************************************************** + copyright : (C) 2009 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4COVERART_H +#define TAGLIB_MP4COVERART_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace MP4 { + + class TAGLIB_EXPORT CoverArt + { + public: + /*! + * This describes the image type. + */ + enum Format { + JPEG = 0x0D, + PNG = 0x0E + }; + + CoverArt(Format format, const ByteVector &data); + ~CoverArt(); + + CoverArt(const CoverArt &item); + CoverArt &operator=(const CoverArt &item); + + //! Format of the image + Format format() const; + + //! The image data + ByteVector data() const; + + private: + class CoverArtPrivate; + CoverArtPrivate *d; + }; + + typedef List CoverArtList; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4file.cpp b/Plugins/PluginNowPlaying/taglib/mp4/mp4file.cpp new file mode 100644 index 00000000..2d59a8e5 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4file.cpp @@ -0,0 +1,145 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_MP4 + +#include +#include +#include "mp4atom.h" +#include "mp4tag.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::File::FilePrivate +{ +public: + FilePrivate() : tag(0), atoms(0), properties(0) + { + } + + ~FilePrivate() + { + if(atoms) { + delete atoms; + atoms = 0; + } + if(tag) { + delete tag; + tag = 0; + } + if(properties) { + delete properties; + properties = 0; + } + } + + MP4::Tag *tag; + MP4::Atoms *atoms; + MP4::Properties *properties; +}; + +MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle audioPropertiesStyle) + : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, audioPropertiesStyle); +} + +MP4::File::~File() +{ + delete d; +} + +MP4::Tag * +MP4::File::tag() const +{ + return d->tag; +} + +MP4::Properties * +MP4::File::audioProperties() const +{ + return d->properties; +} + +bool +MP4::File::checkValid(const MP4::AtomList &list) +{ + for(uint i = 0; i < list.size(); i++) { + if(list[i]->length == 0) + return false; + if(!checkValid(list[i]->children)) + return false; + } + return true; +} + +void +MP4::File::read(bool readProperties, Properties::ReadStyle audioPropertiesStyle) +{ + if(!isValid()) + return; + + d->atoms = new Atoms(this); + if (!checkValid(d->atoms->atoms)) { + setValid(false); + return; + } + + // must have a moov atom, otherwise consider it invalid + MP4::Atom *moov = d->atoms->find("moov"); + if(!moov) { + setValid(false); + return; + } + + d->tag = new Tag(this, d->atoms); + if(readProperties) { + d->properties = new Properties(this, d->atoms, audioPropertiesStyle); + } +} + +bool +MP4::File::save() +{ + if(readOnly()) { + debug("MP4::File::save() -- File is read only."); + return false; + } + + if(!isValid()) { + debug("MP4::File::save() -- Trying to save invalid file."); + return false; + } + + return d->tag->save(); +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4file.h b/Plugins/PluginNowPlaying/taglib/mp4/mp4file.h new file mode 100644 index 00000000..5c28d774 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4file.h @@ -0,0 +1,103 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4FILE_H +#define TAGLIB_MP4FILE_H + +#include "tag.h" +#include "tfile.h" +#include "taglib_export.h" +#include "mp4properties.h" +#include "mp4tag.h" + +namespace TagLib { + + //! An implementation of MP4 (AAC, ALAC, ...) metadata + namespace MP4 { + + class Atoms; + + /*! + * This implements and provides an interface for MP4 files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to MP4 files. + */ + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * Contructs a MP4 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 In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle audioPropertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the MP4 tag of the file. + * + * MP4::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the MP4::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + Tag *tag() const; + + /*! + * Returns the MP4 audio properties for this file. + */ + Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + bool save(); + + private: + + void read(bool readProperties, Properties::ReadStyle audioPropertiesStyle); + bool checkValid(const MP4::AtomList &list); + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4item.cpp b/Plugins/PluginNowPlaying/taglib/mp4/mp4item.cpp new file mode 100644 index 00000000..7dcf5946 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4item.cpp @@ -0,0 +1,149 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_MP4 + +#include +#include +#include "mp4item.h" + +using namespace TagLib; + +class MP4::Item::ItemPrivate : public RefCounter +{ +public: + ItemPrivate() : RefCounter(), valid(true) {} + + bool valid; + union { + bool m_bool; + int m_int; + IntPair m_intPair; + }; + StringList m_stringList; + MP4::CoverArtList m_coverArtList; +}; + +MP4::Item::Item() +{ + d = new ItemPrivate; + d->valid = false; +} + +MP4::Item::Item(const Item &item) : d(item.d) +{ + d->ref(); +} + +MP4::Item & +MP4::Item::operator=(const Item &item) +{ + if(d->deref()) { + delete d; + } + d = item.d; + d->ref(); + return *this; +} + +MP4::Item::~Item() +{ + if(d->deref()) { + delete d; + } +} + +MP4::Item::Item(bool value) +{ + d = new ItemPrivate; + d->m_bool = value; +} + +MP4::Item::Item(int value) +{ + d = new ItemPrivate; + d->m_int = value; +} + +MP4::Item::Item(int value1, int value2) +{ + d = new ItemPrivate; + d->m_intPair.first = value1; + d->m_intPair.second = value2; +} + +MP4::Item::Item(const StringList &value) +{ + d = new ItemPrivate; + d->m_stringList = value; +} + +MP4::Item::Item(const MP4::CoverArtList &value) +{ + d = new ItemPrivate; + d->m_coverArtList = value; +} + +bool +MP4::Item::toBool() const +{ + return d->m_bool; +} + +int +MP4::Item::toInt() const +{ + return d->m_int; +} + +MP4::Item::IntPair +MP4::Item::toIntPair() const +{ + return d->m_intPair; +} + +StringList +MP4::Item::toStringList() const +{ + return d->m_stringList; +} + +MP4::CoverArtList +MP4::Item::toCoverArtList() const +{ + return d->m_coverArtList; +} + +bool +MP4::Item::isValid() const +{ + return d->valid; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4item.h b/Plugins/PluginNowPlaying/taglib/mp4/mp4item.h new file mode 100644 index 00000000..3158b4dd --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4item.h @@ -0,0 +1,72 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4ITEM_H +#define TAGLIB_MP4ITEM_H + +#include "tstringlist.h" +#include "mp4coverart.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace MP4 { + + class TAGLIB_EXPORT Item + { + public: + struct IntPair { + int first, second; + }; + + Item(); + Item(const Item &item); + Item &operator=(const Item &item); + ~Item(); + + Item(int value); + Item(bool value); + Item(int first, int second); + Item(const StringList &value); + Item(const CoverArtList &value); + + int toInt() const; + bool toBool() const; + IntPair toIntPair() const; + StringList toStringList() const; + CoverArtList toCoverArtList() const; + + bool isValid() const; + + private: + class ItemPrivate; + ItemPrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4properties.cpp b/Plugins/PluginNowPlaying/taglib/mp4/mp4properties.cpp new file mode 100644 index 00000000..a62bda99 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4properties.cpp @@ -0,0 +1,169 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_MP4 + +#include +#include +#include "mp4file.h" +#include "mp4atom.h" +#include "mp4properties.h" + +using namespace TagLib; + +class MP4::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; +}; + +MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) + : AudioProperties(style) +{ + d = new PropertiesPrivate; + + MP4::Atom *moov = atoms->find("moov"); + if(!moov) { + debug("MP4: Atom 'moov' not found"); + return; + } + + MP4::Atom *trak = 0; + ByteVector data; + + MP4::AtomList trakList = moov->findall("trak"); + for (unsigned int i = 0; i < trakList.size(); i++) { + trak = trakList[i]; + MP4::Atom *hdlr = trak->find("mdia", "hdlr"); + if(!hdlr) { + debug("MP4: Atom 'trak.mdia.hdlr' not found"); + return; + } + file->seek(hdlr->offset); + data = file->readBlock(hdlr->length); + if(data.mid(16, 4) == "soun") { + break; + } + trak = 0; + } + if (!trak) { + debug("MP4: No audio tracks"); + return; + } + + MP4::Atom *mdhd = trak->find("mdia", "mdhd"); + if(!mdhd) { + debug("MP4: Atom 'trak.mdia.mdhd' not found"); + return; + } + + file->seek(mdhd->offset); + data = file->readBlock(mdhd->length); + if(data[8] == 0) { + unsigned int unit = data.mid(20, 4).toUInt(); + unsigned int length = data.mid(24, 4).toUInt(); + d->length = length / unit; + } + else { + long long unit = data.mid(28, 8).toLongLong(); + long long length = data.mid(36, 8).toLongLong(); + d->length = int(length / unit); + } + + MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd"); + if(!atom) { + return; + } + + file->seek(atom->offset); + data = file->readBlock(atom->length); + if(data.mid(20, 4) == "mp4a") { + d->channels = data.mid(40, 2).toShort(); + d->bitsPerSample = data.mid(42, 2).toShort(); + d->sampleRate = data.mid(46, 4).toUInt(); + if(data.mid(56, 4) == "esds" && data[64] == 0x03) { + long pos = 65; + if(data.mid(pos, 3) == "\x80\x80\x80") { + pos += 3; + } + pos += 4; + if(data[pos] == 0x04) { + pos += 1; + if(data.mid(pos, 3) == "\x80\x80\x80") { + pos += 3; + } + pos += 10; + d->bitrate = (data.mid(pos, 4).toUInt() + 500) / 1000; + } + } + } +} + +MP4::Properties::~Properties() +{ + delete d; +} + +int +MP4::Properties::channels() const +{ + return d->channels; +} + +int +MP4::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int +MP4::Properties::length() const +{ + return d->length; +} + +int +MP4::Properties::bitrate() const +{ + return d->bitrate; +} + +int +MP4::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4properties.h b/Plugins/PluginNowPlaying/taglib/mp4/mp4properties.h new file mode 100644 index 00000000..ef813850 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4properties.h @@ -0,0 +1,61 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4PROPERTIES_H +#define TAGLIB_MP4PROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace MP4 { + + class Atoms; + class File; + + //! An implementation of MP4 audio properties + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + Properties(File *file, Atoms *atoms, ReadStyle style = Average); + virtual ~Properties(); + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + virtual int bitsPerSample() const; + + private: + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4tag.cpp b/Plugins/PluginNowPlaying/taglib/mp4/mp4tag.cpp new file mode 100644 index 00000000..d7933dbb --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4tag.cpp @@ -0,0 +1,636 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_MP4 + +#include +#include +#include "mp4atom.h" +#include "mp4tag.h" +#include "id3v1genres.h" + +using namespace TagLib; + +class MP4::Tag::TagPrivate +{ +public: + TagPrivate() : file(0), atoms(0) {} + ~TagPrivate() {} + TagLib::File *file; + Atoms *atoms; + ItemListMap items; +}; + +MP4::Tag::Tag(TagLib::File *file, MP4::Atoms *atoms) +{ + d = new TagPrivate; + d->file = file; + d->atoms = atoms; + + MP4::Atom *ilst = atoms->find("moov", "udta", "meta", "ilst"); + if(!ilst) { + //debug("Atom moov.udta.meta.ilst not found."); + return; + } + + for(unsigned int i = 0; i < ilst->children.size(); i++) { + MP4::Atom *atom = ilst->children[i]; + file->seek(atom->offset + 8); + if(atom->name == "----") { + parseFreeForm(atom, file); + } + else if(atom->name == "trkn" || atom->name == "disk") { + parseIntPair(atom, file); + } + else if(atom->name == "cpil" || atom->name == "pgap" || atom->name == "pcst") { + parseBool(atom, file); + } + else if(atom->name == "tmpo") { + parseInt(atom, file); + } + else if(atom->name == "gnre") { + parseGnre(atom, file); + } + else if(atom->name == "covr") { + parseCovr(atom, file); + } + else { + parseText(atom, file); + } + } +} + +MP4::Tag::~Tag() +{ + delete d; +} + +ByteVectorList +MP4::Tag::parseData(MP4::Atom *atom, TagLib::File *file, int expectedFlags, bool freeForm) +{ + ByteVectorList result; + ByteVector data = file->readBlock(atom->length - 8); + int i = 0; + unsigned int pos = 0; + while(pos < data.size()) { + int length = data.mid(pos, 4).toUInt(); + ByteVector name = data.mid(pos + 4, 4); + int flags = data.mid(pos + 8, 4).toUInt(); + if(freeForm && i < 2) { + if(i == 0 && name != "mean") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\""); + return result; + } + else if(i == 1 && name != "name") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"name\""); + return result; + } + result.append(data.mid(pos + 12, length - 12)); + } + else { + if(name != "data") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\""); + return result; + } + if(expectedFlags == -1 || flags == expectedFlags) { + result.append(data.mid(pos + 16, length - 16)); + } + } + pos += length; + i++; + } + return result; +} + +void +MP4::Tag::parseInt(MP4::Atom *atom, TagLib::File *file) +{ + ByteVectorList data = parseData(atom, file); + if(data.size()) { + d->items.insert(atom->name, (int)data[0].toShort()); + } +} + +void +MP4::Tag::parseGnre(MP4::Atom *atom, TagLib::File *file) +{ + ByteVectorList data = parseData(atom, file); + if(data.size()) { + int idx = (int)data[0].toShort(); + if(!d->items.contains("\251gen") && idx > 0) { + d->items.insert("\251gen", StringList(ID3v1::genre(idx - 1))); + } + } +} + +void +MP4::Tag::parseIntPair(MP4::Atom *atom, TagLib::File *file) +{ + ByteVectorList data = parseData(atom, file); + if(data.size()) { + int a = data[0].mid(2, 2).toShort(); + int b = data[0].mid(4, 2).toShort(); + d->items.insert(atom->name, MP4::Item(a, b)); + } +} + +void +MP4::Tag::parseBool(MP4::Atom *atom, TagLib::File *file) +{ + ByteVectorList data = parseData(atom, file); + if(data.size()) { + bool value = data[0].size() ? data[0][0] != '\0' : false; + d->items.insert(atom->name, value); + } +} + +void +MP4::Tag::parseText(MP4::Atom *atom, TagLib::File *file, int expectedFlags) +{ + ByteVectorList data = parseData(atom, file, expectedFlags); + if(data.size()) { + StringList value; + for(unsigned int i = 0; i < data.size(); i++) { + value.append(String(data[i], String::UTF8)); + } + d->items.insert(atom->name, value); + } +} + +void +MP4::Tag::parseFreeForm(MP4::Atom *atom, TagLib::File *file) +{ + ByteVectorList data = parseData(atom, file, 1, true); + if(data.size() > 2) { + StringList value; + for(unsigned int i = 2; i < data.size(); i++) { + value.append(String(data[i], String::UTF8)); + } + String name = "----:" + data[0] + ':' + data[1]; + d->items.insert(name, value); + } +} + +void +MP4::Tag::parseCovr(MP4::Atom *atom, TagLib::File *file) +{ + MP4::CoverArtList value; + ByteVector data = file->readBlock(atom->length - 8); + unsigned int pos = 0; + while(pos < data.size()) { + int length = data.mid(pos, 4).toUInt(); + ByteVector name = data.mid(pos + 4, 4); + int flags = data.mid(pos + 8, 4).toUInt(); + if(name != "data") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\""); + break; + } + if(flags == MP4::CoverArt::PNG || flags == MP4::CoverArt::JPEG) { + value.append(MP4::CoverArt(MP4::CoverArt::Format(flags), + data.mid(pos + 16, length - 16))); + } + pos += length; + } + if(value.size() > 0) + d->items.insert(atom->name, value); +} + +ByteVector +MP4::Tag::padIlst(const ByteVector &data, int length) +{ + if (length == -1) { + length = ((data.size() + 1023) & ~1023) - data.size(); + } + return renderAtom("free", ByteVector(length, '\1')); +} + +ByteVector +MP4::Tag::renderAtom(const ByteVector &name, const ByteVector &data) +{ + return ByteVector::fromUInt(data.size() + 8) + name + data; +} + +ByteVector +MP4::Tag::renderData(const ByteVector &name, int flags, const ByteVectorList &data) +{ + ByteVector result; + for(unsigned int i = 0; i < data.size(); i++) { + result.append(renderAtom("data", ByteVector::fromUInt(flags) + ByteVector(4, '\0') + data[i])); + } + return renderAtom(name, result); +} + +ByteVector +MP4::Tag::renderBool(const ByteVector &name, MP4::Item &item) +{ + ByteVectorList data; + data.append(ByteVector(1, item.toBool() ? '\1' : '\0')); + return renderData(name, 0x15, data); +} + +ByteVector +MP4::Tag::renderInt(const ByteVector &name, MP4::Item &item) +{ + ByteVectorList data; + data.append(ByteVector::fromShort(item.toInt())); + return renderData(name, 0x15, data); +} + +ByteVector +MP4::Tag::renderIntPair(const ByteVector &name, MP4::Item &item) +{ + ByteVectorList data; + data.append(ByteVector(2, '\0') + + ByteVector::fromShort(item.toIntPair().first) + + ByteVector::fromShort(item.toIntPair().second) + + ByteVector(2, '\0')); + return renderData(name, 0x00, data); +} + +ByteVector +MP4::Tag::renderIntPairNoTrailing(const ByteVector &name, MP4::Item &item) +{ + ByteVectorList data; + data.append(ByteVector(2, '\0') + + ByteVector::fromShort(item.toIntPair().first) + + ByteVector::fromShort(item.toIntPair().second)); + return renderData(name, 0x00, data); +} + +ByteVector +MP4::Tag::renderText(const ByteVector &name, MP4::Item &item, int flags) +{ + ByteVectorList data; + StringList value = item.toStringList(); + for(unsigned int i = 0; i < value.size(); i++) { + data.append(value[i].data(String::UTF8)); + } + return renderData(name, flags, data); +} + +ByteVector +MP4::Tag::renderCovr(const ByteVector &name, MP4::Item &item) +{ + ByteVector data; + MP4::CoverArtList value = item.toCoverArtList(); + for(unsigned int i = 0; i < value.size(); i++) { + data.append(renderAtom("data", ByteVector::fromUInt(value[i].format()) + + ByteVector(4, '\0') + value[i].data())); + } + return renderAtom(name, data); +} + +ByteVector +MP4::Tag::renderFreeForm(const String &name, MP4::Item &item) +{ + StringList header = StringList::split(name, ":"); + if (header.size() != 3) { + debug("MP4: Invalid free-form item name \"" + name + "\""); + return ByteVector::null; + } + ByteVector data; + data.append(renderAtom("mean", ByteVector::fromUInt(0) + header[1].data(String::UTF8))); + data.append(renderAtom("name", ByteVector::fromUInt(0) + header[2].data(String::UTF8))); + StringList value = item.toStringList(); + for(unsigned int i = 0; i < value.size(); i++) { + data.append(renderAtom("data", ByteVector::fromUInt(1) + ByteVector(4, '\0') + value[i].data(String::UTF8))); + } + return renderAtom("----", data); +} + +bool +MP4::Tag::save() +{ + ByteVector data; + for(MP4::ItemListMap::Iterator i = d->items.begin(); i != d->items.end(); i++) { + const String name = i->first; + if(name.startsWith("----")) { + data.append(renderFreeForm(name, i->second)); + } + else if(name == "trkn") { + data.append(renderIntPair(name.data(String::Latin1), i->second)); + } + else if(name == "disk") { + data.append(renderIntPairNoTrailing(name.data(String::Latin1), i->second)); + } + else if(name == "cpil" || name == "pgap" || name == "pcst") { + data.append(renderBool(name.data(String::Latin1), i->second)); + } + else if(name == "tmpo") { + data.append(renderInt(name.data(String::Latin1), i->second)); + } + else if(name == "covr") { + data.append(renderCovr(name.data(String::Latin1), i->second)); + } + else if(name.size() == 4){ + data.append(renderText(name.data(String::Latin1), i->second)); + } + else { + debug("MP4: Unknown item name \"" + name + "\""); + } + } + data = renderAtom("ilst", data); + + AtomList path = d->atoms->path("moov", "udta", "meta", "ilst"); + if(path.size() == 4) { + saveExisting(data, path); + } + else { + saveNew(data); + } + + return true; +} + +void +MP4::Tag::updateParents(AtomList &path, long delta, int ignore) +{ + for(unsigned int i = 0; i < path.size() - ignore; i++) { + d->file->seek(path[i]->offset); + long size = d->file->readBlock(4).toUInt(); + // 64-bit + if (size == 1) { + d->file->seek(4, File::Current); // Skip name + long long longSize = d->file->readBlock(8).toLongLong(); + // Seek the offset of the 64-bit size + d->file->seek(path[i]->offset + 8); + d->file->writeBlock(ByteVector::fromLongLong(longSize + delta)); + } + // 32-bit + else { + d->file->seek(path[i]->offset); + d->file->writeBlock(ByteVector::fromUInt(size + delta)); + } + } +} + +void +MP4::Tag::updateOffsets(long delta, long offset) +{ + MP4::Atom *moov = d->atoms->find("moov"); + if(moov) { + MP4::AtomList stco = moov->findall("stco", true); + for(unsigned int i = 0; i < stco.size(); i++) { + MP4::Atom *atom = stco[i]; + if(atom->offset > offset) { + atom->offset += delta; + } + d->file->seek(atom->offset + 12); + ByteVector data = d->file->readBlock(atom->length - 12); + unsigned int count = data.mid(0, 4).toUInt(); + d->file->seek(atom->offset + 16); + int pos = 4; + while(count--) { + long o = data.mid(pos, 4).toUInt(); + if(o > offset) { + o += delta; + } + d->file->writeBlock(ByteVector::fromUInt(o)); + pos += 4; + } + } + + MP4::AtomList co64 = moov->findall("co64", true); + for(unsigned int i = 0; i < co64.size(); i++) { + MP4::Atom *atom = co64[i]; + if(atom->offset > offset) { + atom->offset += delta; + } + d->file->seek(atom->offset + 12); + ByteVector data = d->file->readBlock(atom->length - 12); + unsigned int count = data.mid(0, 4).toUInt(); + d->file->seek(atom->offset + 16); + int pos = 4; + while(count--) { + long long o = data.mid(pos, 8).toLongLong(); + if(o > offset) { + o += delta; + } + d->file->writeBlock(ByteVector::fromLongLong(o)); + pos += 8; + } + } + } + + MP4::Atom *moof = d->atoms->find("moof"); + if(moof) { + MP4::AtomList tfhd = moof->findall("tfhd", true); + for(unsigned int i = 0; i < tfhd.size(); i++) { + MP4::Atom *atom = tfhd[i]; + if(atom->offset > offset) { + atom->offset += delta; + } + d->file->seek(atom->offset + 9); + ByteVector data = d->file->readBlock(atom->offset - 9); + unsigned int flags = (ByteVector(1, '\0') + data.mid(0, 3)).toUInt(); + if(flags & 1) { + long long o = data.mid(7, 8).toLongLong(); + if(o > offset) { + o += delta; + } + d->file->seek(atom->offset + 16); + d->file->writeBlock(ByteVector::fromLongLong(o)); + } + } + } +} + +void +MP4::Tag::saveNew(ByteVector &data) +{ + data = renderAtom("meta", TagLib::ByteVector(4, '\0') + + renderAtom("hdlr", TagLib::ByteVector(8, '\0') + TagLib::ByteVector("mdirappl") + TagLib::ByteVector(9, '\0')) + + data + padIlst(data)); + + AtomList path = d->atoms->path("moov", "udta"); + if(path.size() != 2) { + path = d->atoms->path("moov"); + data = renderAtom("udta", data); + } + + long offset = path[path.size() - 1]->offset + 8; + d->file->insert(data, offset, 0); + + updateParents(path, data.size()); + updateOffsets(data.size(), offset); +} + +void +MP4::Tag::saveExisting(ByteVector &data, AtomList &path) +{ + MP4::Atom *ilst = path[path.size() - 1]; + long offset = ilst->offset; + long length = ilst->length; + + MP4::Atom *meta = path[path.size() - 2]; + AtomList::Iterator index = meta->children.find(ilst); + + // check if there is an atom before 'ilst', and possibly use it as padding + if(index != meta->children.begin()) { + AtomList::Iterator prevIndex = index; + prevIndex--; + MP4::Atom *prev = *prevIndex; + if(prev->name == "free") { + offset = prev->offset; + length += prev->length; + } + } + // check if there is an atom after 'ilst', and possibly use it as padding + AtomList::Iterator nextIndex = index; + nextIndex++; + if(nextIndex != meta->children.end()) { + MP4::Atom *next = *nextIndex; + if(next->name == "free") { + length += next->length; + } + } + + long delta = data.size() - length; + if(delta > 0 || (delta < 0 && delta > -8)) { + data.append(padIlst(data)); + delta = data.size() - length; + } + else if(delta < 0) { + data.append(padIlst(data, -delta - 8)); + delta = 0; + } + + d->file->insert(data, offset, length); + + if(delta) { + updateParents(path, delta, 1); + updateOffsets(delta, offset); + } +} + +String +MP4::Tag::title() const +{ + if(d->items.contains("\251nam")) + return d->items["\251nam"].toStringList().toString(", "); + return String::null; +} + +String +MP4::Tag::artist() const +{ + if(d->items.contains("\251ART")) + return d->items["\251ART"].toStringList().toString(", "); + return String::null; +} + +String +MP4::Tag::album() const +{ + if(d->items.contains("\251alb")) + return d->items["\251alb"].toStringList().toString(", "); + return String::null; +} + +String +MP4::Tag::comment() const +{ + if(d->items.contains("\251cmt")) + return d->items["\251cmt"].toStringList().toString(", "); + return String::null; +} + +String +MP4::Tag::genre() const +{ + if(d->items.contains("\251gen")) + return d->items["\251gen"].toStringList().toString(", "); + return String::null; +} + +unsigned int +MP4::Tag::year() const +{ + if(d->items.contains("\251day")) + return d->items["\251day"].toStringList().toString().toInt(); + return 0; +} + +unsigned int +MP4::Tag::track() const +{ + if(d->items.contains("trkn")) + return d->items["trkn"].toIntPair().first; + return 0; +} + +void +MP4::Tag::setTitle(const String &value) +{ + d->items["\251nam"] = StringList(value); +} + +void +MP4::Tag::setArtist(const String &value) +{ + d->items["\251ART"] = StringList(value); +} + +void +MP4::Tag::setAlbum(const String &value) +{ + d->items["\251alb"] = StringList(value); +} + +void +MP4::Tag::setComment(const String &value) +{ + d->items["\251cmt"] = StringList(value); +} + +void +MP4::Tag::setGenre(const String &value) +{ + d->items["\251gen"] = StringList(value); +} + +void +MP4::Tag::setYear(uint value) +{ + d->items["\251day"] = StringList(String::number(value)); +} + +void +MP4::Tag::setTrack(uint value) +{ + d->items["trkn"] = MP4::Item(value, 0); +} + +MP4::ItemListMap & +MP4::Tag::itemListMap() +{ + return d->items; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mp4/mp4tag.h b/Plugins/PluginNowPlaying/taglib/mp4/mp4tag.h new file mode 100644 index 00000000..3e6d667f --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mp4/mp4tag.h @@ -0,0 +1,104 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4TAG_H +#define TAGLIB_MP4TAG_H + +#include "tag.h" +#include "tbytevectorlist.h" +#include "tfile.h" +#include "tmap.h" +#include "tstringlist.h" +#include "taglib_export.h" +#include "mp4atom.h" +#include "mp4item.h" + +namespace TagLib { + + namespace MP4 { + + typedef TagLib::Map ItemListMap; + + class TAGLIB_EXPORT Tag: public TagLib::Tag + { + public: + Tag(TagLib::File *file, Atoms *atoms); + ~Tag(); + bool save(); + + String title() const; + String artist() const; + String album() const; + String comment() const; + String genre() const; + uint year() const; + uint track() const; + + void setTitle(const String &value); + void setArtist(const String &value); + void setAlbum(const String &value); + void setComment(const String &value); + void setGenre(const String &value); + void setYear(uint value); + void setTrack(uint value); + + ItemListMap &itemListMap(); + + private: + TagLib::ByteVectorList parseData(Atom *atom, TagLib::File *file, int expectedFlags = -1, bool freeForm = false); + void parseText(Atom *atom, TagLib::File *file, int expectedFlags = 1); + void parseFreeForm(Atom *atom, TagLib::File *file); + void parseInt(Atom *atom, TagLib::File *file); + void parseGnre(Atom *atom, TagLib::File *file); + void parseIntPair(Atom *atom, TagLib::File *file); + void parseBool(Atom *atom, TagLib::File *file); + void parseCovr(Atom *atom, TagLib::File *file); + + TagLib::ByteVector padIlst(const ByteVector &data, int length = -1); + TagLib::ByteVector renderAtom(const ByteVector &name, const TagLib::ByteVector &data); + TagLib::ByteVector renderData(const ByteVector &name, int flags, const TagLib::ByteVectorList &data); + TagLib::ByteVector renderText(const ByteVector &name, Item &item, int flags = 1); + TagLib::ByteVector renderFreeForm(const String &name, Item &item); + TagLib::ByteVector renderBool(const ByteVector &name, Item &item); + TagLib::ByteVector renderInt(const ByteVector &name, Item &item); + TagLib::ByteVector renderIntPair(const ByteVector &name, Item &item); + TagLib::ByteVector renderIntPairNoTrailing(const ByteVector &name, Item &item); + TagLib::ByteVector renderCovr(const ByteVector &name, Item &item); + + void updateParents(AtomList &path, long delta, int ignore = 0); + void updateOffsets(long delta, long offset); + + void saveNew(TagLib::ByteVector &data); + void saveExisting(TagLib::ByteVector &data, AtomList &path); + + class TagPrivate; + TagPrivate *d; + }; + + } + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpc/mpcfile.cpp b/Plugins/PluginNowPlaying/taglib/mpc/mpcfile.cpp new file mode 100644 index 00000000..9e9d6b88 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpc/mpcfile.cpp @@ -0,0 +1,325 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "mpcfile.h" +#include "id3v1tag.h" +#include "id3v2header.h" +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +namespace +{ + enum { APEIndex, ID3v1Index }; +} + +class MPC::File::FilePrivate +{ +public: + FilePrivate() : + APELocation(-1), + APESize(0), + ID3v1Location(-1), + ID3v2Header(0), + ID3v2Location(-1), + ID3v2Size(0), + properties(0), + scanned(false), + hasAPE(false), + hasID3v1(false), + hasID3v2(false) {} + + ~FilePrivate() + { + delete ID3v2Header; + delete properties; + } + + long APELocation; + uint APESize; + + long ID3v1Location; + + ID3v2::Header *ID3v2Header; + long ID3v2Location; + uint ID3v2Size; + + TagUnion tag; + + Properties *properties; + bool scanned; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasAPE; + bool hasID3v1; + bool hasID3v2; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPC::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +MPC::File::~File() +{ + delete d; +} + +TagLib::Tag *MPC::File::tag() const +{ + return &d->tag; +} + +MPC::Properties *MPC::File::audioProperties() const +{ + return d->properties; +} + +bool MPC::File::save() +{ + if(readOnly()) { + debug("MPC::File::save() -- File is read only."); + return false; + } + + // Possibly strip ID3v2 tag + + if(d->hasID3v2 && !d->ID3v2Header) { + removeBlock(d->ID3v2Location, d->ID3v2Size); + d->hasID3v2 = false; + if(d->hasID3v1) + d->ID3v1Location -= d->ID3v2Size; + if(d->hasAPE) + d->APELocation -= d->ID3v2Size; + } + + // Update ID3v1 tag + + if(ID3v1Tag()) { + if(d->hasID3v1) { + seek(d->ID3v1Location); + writeBlock(ID3v1Tag()->render()); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + writeBlock(ID3v1Tag()->render()); + d->hasID3v1 = true; + } + } else + if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->hasID3v1 = false; + if(d->hasAPE) { + if(d->APELocation > d->ID3v1Location) + d->APELocation -= 128; + } + } + + // Update APE tag + + if(APETag()) { + if(d->hasAPE) + insert(APETag()->render(), d->APELocation, d->APESize); + else { + if(d->hasID3v1) { + insert(APETag()->render(), d->ID3v1Location, 0); + d->APESize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + d->APELocation = d->ID3v1Location; + d->ID3v1Location += d->APESize; + } + else { + seek(0, End); + d->APELocation = tell(); + writeBlock(APETag()->render()); + d->APESize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + } + } + } + else + if(d->hasAPE) { + removeBlock(d->APELocation, d->APESize); + d->hasAPE = false; + if(d->hasID3v1) { + if(d->ID3v1Location > d->APELocation) + d->ID3v1Location -= d->APESize; + } + } + + return true; +} + +ID3v1::Tag *MPC::File::ID3v1Tag(bool create) +{ + return d->tag.access(ID3v1Index, create); +} + +APE::Tag *MPC::File::APETag(bool create) +{ + return d->tag.access(APEIndex, create); +} + +void MPC::File::strip(int tags) +{ + if(tags & ID3v1) { + d->tag.set(ID3v1Index, 0); + APETag(true); + } + + if(tags & ID3v2) { + delete d->ID3v2Header; + d->ID3v2Header = 0; + } + + if(tags & APE) { + d->tag.set(APEIndex, 0); + + if(!ID3v1Tag()) + APETag(true); + } +} + +void MPC::File::remove(int tags) +{ + strip(tags); +} + + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + d->hasID3v1 = true; + } + + // Look for an APE tag + + findAPE(); + + d->APELocation = findAPE(); + + if(d->APELocation >= 0) { + d->tag.set(APEIndex, new APE::Tag(this, d->APELocation)); + + d->APESize = APETag()->footer()->completeTagSize(); + d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize; + d->hasAPE = true; + } + + if(!d->hasID3v1) + APETag(true); + + // Look for and skip an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location); + d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size())); + d->ID3v2Size = d->ID3v2Header->completeTagSize(); + d->hasID3v2 = true; + } + + if(d->hasID3v2) + seek(d->ID3v2Location + d->ID3v2Size); + else + seek(0); + + // Look for MPC metadata + + if(readProperties) { + d->properties = new Properties(readBlock(MPC::HeaderSize), + length() - d->ID3v2Size - d->APESize); + } +} + +long MPC::File::findAPE() +{ + if(!isValid()) + return -1; + + if(d->hasID3v1) + seek(-160, End); + else + seek(-32, End); + + long p = tell(); + + if(readBlock(8) == APE::Tag::fileIdentifier()) + return p; + + return -1; +} + +long MPC::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} + +long MPC::File::findID3v2() +{ + if(!isValid()) + return -1; + + seek(0); + + if(readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} diff --git a/Plugins/PluginNowPlaying/taglib/mpc/mpcfile.h b/Plugins/PluginNowPlaying/taglib/mpc/mpcfile.h new file mode 100644 index 00000000..6adc0ffb --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpc/mpcfile.h @@ -0,0 +1,175 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPCFILE_H +#define TAGLIB_MPCFILE_H + +#include "taglib_export.h" +#include "tfile.h" + +#include "mpcproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of MPC metadata + + /*! + * This is implementation of MPC metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. ID3v2 tags are invalid in MPC-files, but will be skipped + * and ignored. + */ + + namespace MPC { + + //! An implementation of TagLib::File with MPC specific methods + + /*! + * This implements and provides an interface for MPC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to MPC files. + * The only invalid tag combination supported is an ID3v1 tag after an APE tag. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches APE tags. + APE = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * 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(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * a APE tag if one does not exist. If there is already an ID3v1 tag, thes + * new APE tag will be placed before it. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \warning This will also invalidate pointers to the tags + * as their memory will be freed. + * + * \note In order to make the removal permanent save() still needs to be called. + */ + void strip(int tags = AllTags); + + /*! + * \deprecated + * \see strip + */ + void remove(int tags = AllTags); + + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findAPE(); + long findID3v1(); + long findID3v2(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.cpp b/Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.cpp new file mode 100644 index 00000000..9adc6924 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "mpcproperties.h" +#include "mpcfile.h" + +using namespace TagLib; + +class MPC::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) : + data(d), + streamLength(length), + style(s), + version(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int version; + int length; + int bitrate; + int sampleRate; + int channels; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +MPC::Properties::~Properties() +{ + delete d; +} + +int MPC::Properties::length() const +{ + return d->length; +} + +int MPC::Properties::bitrate() const +{ + return d->bitrate; +} + +int MPC::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int MPC::Properties::channels() const +{ + return d->channels; +} + +int MPC::Properties::mpcVersion() const +{ + return d->version; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +static const unsigned short sftable [4] = { 44100, 48000, 37800, 32000 }; + +void MPC::Properties::read() +{ + if(!d->data.startsWith("MP+")) + return; + + d->version = d->data[3] & 15; + + unsigned int frames; + + if(d->version >= 7) { + frames = d->data.mid(4, 4).toUInt(false); + + std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(d->data.mid(8, 4).toUInt(false))); + d->sampleRate = sftable[flags[17] * 2 + flags[16]]; + d->channels = 2; + } + else { + uint headerData = d->data.mid(0, 4).toUInt(false); + + d->bitrate = (headerData >> 23) & 0x01ff; + d->version = (headerData >> 11) & 0x03ff; + d->sampleRate = 44100; + d->channels = 2; + + if(d->version >= 5) + frames = d->data.mid(4, 4).toUInt(false); + else + frames = d->data.mid(6, 2).toUInt(false); + } + + uint samples = frames * 1152 - 576; + + d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0; + + if(!d->bitrate) + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} diff --git a/Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.h b/Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.h new file mode 100644 index 00000000..d1593458 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.h @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPCPROPERTIES_H +#define TAGLIB_MPCPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace MPC { + + class File; + + static const uint HeaderSize = 8*7; + + //! An implementation of audio property reading for MPC + + /*! + * This reads the data from an MPC stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of MPC::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this MPC::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns the version of the bitstream (SV4-SV7) + */ + int mpcVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.cpp new file mode 100644 index 00000000..7893c72c --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.cpp @@ -0,0 +1,219 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "id3v1genres.h" + +using namespace TagLib; + +namespace TagLib { + namespace ID3v1 { + + static const int genresSize = 148; + static const String genres[] = { + "Blues", + "Classic Rock", + "Country", + "Dance", + "Disco", + "Funk", + "Grunge", + "Hip-Hop", + "Jazz", + "Metal", + "New Age", + "Oldies", + "Other", + "Pop", + "R&B", + "Rap", + "Reggae", + "Rock", + "Techno", + "Industrial", + "Alternative", + "Ska", + "Death Metal", + "Pranks", + "Soundtrack", + "Euro-Techno", + "Ambient", + "Trip-Hop", + "Vocal", + "Jazz+Funk", + "Fusion", + "Trance", + "Classical", + "Instrumental", + "Acid", + "House", + "Game", + "Sound Clip", + "Gospel", + "Noise", + "Alternative Rock", + "Bass", + "Soul", + "Punk", + "Space", + "Meditative", + "Instrumental Pop", + "Instrumental Rock", + "Ethnic", + "Gothic", + "Darkwave", + "Techno-Industrial", + "Electronic", + "Pop-Folk", + "Eurodance", + "Dream", + "Southern Rock", + "Comedy", + "Cult", + "Gangsta", + "Top 40", + "Christian Rap", + "Pop/Funk", + "Jungle", + "Native American", + "Cabaret", + "New Wave", + "Psychedelic", + "Rave", + "Showtunes", + "Trailer", + "Lo-Fi", + "Tribal", + "Acid Punk", + "Acid Jazz", + "Polka", + "Retro", + "Musical", + "Rock & Roll", + "Hard Rock", + "Folk", + "Folk/Rock", + "National Folk", + "Swing", + "Fusion", + "Bebob", + "Latin", + "Revival", + "Celtic", + "Bluegrass", + "Avantgarde", + "Gothic Rock", + "Progressive Rock", + "Psychedelic Rock", + "Symphonic Rock", + "Slow Rock", + "Big Band", + "Chorus", + "Easy Listening", + "Acoustic", + "Humour", + "Speech", + "Chanson", + "Opera", + "Chamber Music", + "Sonata", + "Symphony", + "Booty Bass", + "Primus", + "Porn Groove", + "Satire", + "Slow Jam", + "Club", + "Tango", + "Samba", + "Folklore", + "Ballad", + "Power Ballad", + "Rhythmic Soul", + "Freestyle", + "Duet", + "Punk Rock", + "Drum Solo", + "A Cappella", + "Euro-House", + "Dance Hall", + "Goa", + "Drum & Bass", + "Club-House", + "Hardcore", + "Terror", + "Indie", + "BritPop", + "Negerpunk", + "Polsk Punk", + "Beat", + "Christian Gangsta Rap", + "Heavy Metal", + "Black Metal", + "Crossover", + "Contemporary Christian", + "Christian Rock", + "Merengue", + "Salsa", + "Thrash Metal", + "Anime", + "Jpop", + "Synthpop" + }; + } +} + +StringList ID3v1::genreList() +{ + static StringList l; + if(l.isEmpty()) { + for(int i = 0; i < genresSize; i++) + l.append(genres[i]); + } + return l; +} + +ID3v1::GenreMap ID3v1::genreMap() +{ + static GenreMap m; + if(m.isEmpty()) { + for(int i = 0; i < genresSize; i++) + m.insert(genres[i], i); + } + return m; +} + +String ID3v1::genre(int i) +{ + if(i >= 0 && i < genresSize) + return genres[i]; + return String::null; +} + +int ID3v1::genreIndex(const String &name) +{ + if(genreMap().contains(name)) + return genreMap()[name]; + return 255; +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.h new file mode 100644 index 00000000..271f7259 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.h @@ -0,0 +1,66 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V1GENRE_H +#define TAGLIB_ID3V1GENRE_H + +#include "tmap.h" +#include "tstringlist.h" +#include "taglib_export.h" + +namespace TagLib { + namespace ID3v1 { + + typedef Map GenreMap; + + /*! + * Returns the list of canonical ID3v1 genre names in the order that they + * are listed in the standard. + */ + StringList TAGLIB_EXPORT genreList(); + + /*! + * A "reverse mapping" that goes from the canonical ID3v1 genre name to the + * respective genre number. genreMap()["Rock"] == + */ + GenreMap TAGLIB_EXPORT genreMap(); + + /*! + * Returns the name of the genre at \a index in the ID3v1 genre list. If + * \a index is out of range -- less than zero or greater than 146 -- a null + * string will be returned. + */ + String TAGLIB_EXPORT genre(int index); + + /*! + * Returns the genre index for the (case sensitive) genre \a name. If the + * genre is not in the list 255 (which signifies an unknown genre in ID3v1) + * will be returned. + */ + int TAGLIB_EXPORT genreIndex(const String &name); + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.cpp new file mode 100644 index 00000000..4a1d69b2 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.cpp @@ -0,0 +1,248 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "id3v1tag.h" +#include "id3v1genres.h" + +using namespace TagLib; +using namespace ID3v1; + +class ID3v1::Tag::TagPrivate +{ +public: + TagPrivate() : file(0), tagOffset(-1), track(0), genre(255) {} + + File *file; + long tagOffset; + + String title; + String artist; + String album; + String year; + String comment; + uchar track; + uchar genre; + + static const StringHandler *stringHandler; +}; + +const ID3v1::StringHandler *ID3v1::Tag::TagPrivate::stringHandler = new StringHandler; + +//////////////////////////////////////////////////////////////////////////////// +// StringHandler implementation +//////////////////////////////////////////////////////////////////////////////// + +String ID3v1::StringHandler::parse(const ByteVector &data) const +{ + return String(data, String::Latin1).stripWhiteSpace(); +} + +ByteVector ID3v1::StringHandler::render(const String &s) const +{ + if(!s.isLatin1()) + { + return ByteVector(); + } + + return s.data(String::Latin1); +} + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +ID3v1::Tag::Tag() : TagLib::Tag() +{ + d = new TagPrivate; +} + +ID3v1::Tag::Tag(File *file, long tagOffset) : TagLib::Tag() +{ + d = new TagPrivate; + d->file = file; + d->tagOffset = tagOffset; + + read(); +} + +ID3v1::Tag::~Tag() +{ + delete d; +} + +ByteVector ID3v1::Tag::render() const +{ + ByteVector data; + + data.append(fileIdentifier()); + data.append(TagPrivate::stringHandler->render(d->title).resize(30)); + data.append(TagPrivate::stringHandler->render(d->artist).resize(30)); + data.append(TagPrivate::stringHandler->render(d->album).resize(30)); + data.append(TagPrivate::stringHandler->render(d->year).resize(4)); + data.append(TagPrivate::stringHandler->render(d->comment).resize(28)); + data.append(char(0)); + data.append(char(d->track)); + data.append(char(d->genre)); + + return data; +} + +ByteVector ID3v1::Tag::fileIdentifier() +{ + return ByteVector::fromCString("TAG"); +} + +String ID3v1::Tag::title() const +{ + return d->title; +} + +String ID3v1::Tag::artist() const +{ + return d->artist; +} + +String ID3v1::Tag::album() const +{ + return d->album; +} + +String ID3v1::Tag::comment() const +{ + return d->comment; +} + +String ID3v1::Tag::genre() const +{ + return ID3v1::genre(d->genre); +} + +TagLib::uint ID3v1::Tag::year() const +{ + return d->year.toInt(); +} + +TagLib::uint ID3v1::Tag::track() const +{ + return d->track; +} + +void ID3v1::Tag::setTitle(const String &s) +{ + d->title = s; +} + +void ID3v1::Tag::setArtist(const String &s) +{ + d->artist = s; +} + +void ID3v1::Tag::setAlbum(const String &s) +{ + d->album = s; +} + +void ID3v1::Tag::setComment(const String &s) +{ + d->comment = s; +} + +void ID3v1::Tag::setGenre(const String &s) +{ + d->genre = ID3v1::genreIndex(s); +} + +void ID3v1::Tag::setYear(uint i) +{ + d->year = i > 0 ? String::number(i) : String::null; +} + +void ID3v1::Tag::setTrack(uint i) +{ + d->track = i < 256 ? i : 0; +} + +void ID3v1::Tag::setStringHandler(const StringHandler *handler) +{ + delete TagPrivate::stringHandler; + TagPrivate::stringHandler = handler; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected methods +//////////////////////////////////////////////////////////////////////////////// + +void ID3v1::Tag::read() +{ + if(d->file && d->file->isValid()) { + d->file->seek(d->tagOffset); + // read the tag -- always 128 bytes + ByteVector data = d->file->readBlock(128); + + // some initial sanity checking + if(data.size() == 128 && data.startsWith("TAG")) + parse(data); + else + debug("ID3v1 tag is not valid or could not be read at the specified offset."); + } +} + +void ID3v1::Tag::parse(const ByteVector &data) +{ + int offset = 3; + + d->title = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + offset += 30; + + d->artist = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + offset += 30; + + d->album = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + offset += 30; + + d->year = TagPrivate::stringHandler->parse(data.mid(offset, 4)); + offset += 4; + + // Check for ID3v1.1 -- Note that ID3v1 *does not* support "track zero" -- this + // is not a bug in TagLib. Since a zeroed byte is what we would expect to + // indicate the end of a C-String, specifically the comment string, a value of + // zero must be assumed to be just that. + + if(data[offset + 28] == 0 && data[offset + 29] != 0) { + // ID3v1.1 detected + + d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 28)); + d->track = uchar(data[offset + 29]); + } + else + d->comment = data.mid(offset, 30); + + offset += 30; + + d->genre = uchar(data[offset]); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.h new file mode 100644 index 00000000..fad485e5 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.h @@ -0,0 +1,181 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V1TAG_H +#define TAGLIB_ID3V1TAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class File; + + //! An ID3v1 implementation + + namespace ID3v1 { + + //! A abstraction for the string to data encoding in ID3v1 tags. + + /*! + * ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In + * practice it does not. TagLib by default only supports ISO-8859-1 data + * in ID3v1 tags. + * + * However by subclassing this class and reimplementing parse() and render() + * and setting your reimplementation as the default with + * ID3v1::Tag::setStringHandler() you can define how you would like these + * transformations to be done. + * + * \warning It is advisable not to write non-ISO-8859-1 data to ID3v1 + * tags. Please consider disabling the writing of ID3v1 tags in the case + * that the data is not ISO-8859-1. + * + * \see ID3v1::Tag::setStringHandler() + */ + + class TAGLIB_EXPORT StringHandler + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + // BIC: Add virtual destructor. + + /*! + * Decode a string from \a data. The default implementation assumes that + * \a data is an ISO-8859-1 (Latin1) character array. + */ + virtual String parse(const ByteVector &data) const; + + /*! + * Encode a ByteVector with the data from \a s. The default implementation + * assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is + * does not conform to ISO-8859-1, no value is written. + * + * \warning It is recommended that you not override this method, but + * instead do not write an ID3v1 tag in the case that the data is not + * ISO-8859-1. + */ + virtual ByteVector render(const String &s) const; + }; + + //! The main class in the ID3v1 implementation + + /*! + * This is an implementation of the ID3v1 format. ID3v1 is both the simplist + * and most common of tag formats but is rather limited. Because of its + * pervasiveness and the way that applications have been written around the + * fields that it provides, the generic TagLib::Tag API is a mirror of what is + * provided by ID3v1. + * + * ID3v1 tags should generally only contain Latin1 information. However because + * many applications do not follow this rule there is now support for overriding + * the ID3v1 string handling using the ID3v1::StringHandler class. Please see + * the documentation for that class for more information. + * + * \see StringHandler + * + * \note Most fields are truncated to a maximum of 28-30 bytes. The + * truncation happens automatically when the tag is rendered. + */ + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Create an ID3v1 tag with default values. + */ + Tag(); + + /*! + * Create an ID3v1 tag and parse the data in \a file starting at + * \a tagOffset. + */ + Tag(File *file, long tagOffset); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Renders the in memory values to a ByteVector suitable for writing to + * the file. + */ + ByteVector render() const; + + /*! + * Returns the string "TAG" suitable for usage in locating the tag in a + * file. + */ + static ByteVector fileIdentifier(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual uint year() const; + virtual uint track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(uint i); + virtual void setTrack(uint i); + + /*! + * Sets the string handler that decides how the ID3v1 data will be + * converted to and from binary data. + * + * \see StringHandler + */ + static void setStringHandler(const StringHandler *handler); + + protected: + /*! + * Reads from the file specified in the constructor. + */ + void read(); + /*! + * Pareses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp new file mode 100644 index 00000000..e4e97d01 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp @@ -0,0 +1,222 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "attachedpictureframe.h" + +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class AttachedPictureFrame::AttachedPictureFramePrivate +{ +public: + AttachedPictureFramePrivate() : textEncoding(String::Latin1), + type(AttachedPictureFrame::Other) {} + + String::Type textEncoding; + String mimeType; + AttachedPictureFrame::Type type; + String description; + ByteVector data; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC") +{ + d = new AttachedPictureFramePrivate; +} + +AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data) +{ + d = new AttachedPictureFramePrivate; + setData(data); +} + +AttachedPictureFrame::~AttachedPictureFrame() +{ + delete d; +} + +String AttachedPictureFrame::toString() const +{ + String s = "[" + d->mimeType + "]"; + return d->description.isEmpty() ? s : d->description + " " + s; +} + +String::Type AttachedPictureFrame::textEncoding() const +{ + return d->textEncoding; +} + +void AttachedPictureFrame::setTextEncoding(String::Type t) +{ + d->textEncoding = t; +} + +String AttachedPictureFrame::mimeType() const +{ + return d->mimeType; +} + +void AttachedPictureFrame::setMimeType(const String &m) +{ + d->mimeType = m; +} + +AttachedPictureFrame::Type AttachedPictureFrame::type() const +{ + return d->type; +} + +void AttachedPictureFrame::setType(Type t) +{ + d->type = t; +} + +String AttachedPictureFrame::description() const +{ + return d->description; +} + +void AttachedPictureFrame::setDescription(const String &desc) +{ + d->description = desc; +} + +ByteVector AttachedPictureFrame::picture() const +{ + return d->data; +} + +void AttachedPictureFrame::setPicture(const ByteVector &p) +{ + d->data = p; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void AttachedPictureFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("A picture frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + + int pos = 1; + + d->mimeType = readStringField(data, String::Latin1, &pos); + /* Now we need at least two more bytes available */ + if (uint(pos) + 1 >= data.size()) { + debug("Truncated picture frame."); + return; + } + + d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++]; + d->description = readStringField(data, d->textEncoding, &pos); + + d->data = data.mid(pos); +} + +ByteVector AttachedPictureFrame::renderFields() const +{ + ByteVector data; + + String::Type encoding = checkEncoding(d->description, d->textEncoding); + + data.append(char(encoding)); + data.append(d->mimeType.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + data.append(char(d->type)); + data.append(d->description.data(encoding)); + data.append(textDelimiter(encoding)); + data.append(d->data); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new AttachedPictureFramePrivate; + parseFields(fieldData(data)); +} + +//////////////////////////////////////////////////////////////////////////////// +// support for ID3v2.2 PIC frames +//////////////////////////////////////////////////////////////////////////////// + +void AttachedPictureFrameV22::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("A picture frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + + int pos = 1; + + String fixedString = String(data.mid(pos, 3), String::Latin1); + pos += 3; + // convert fixed string image type to mime string + if (fixedString.upper() == "JPG") { + d->mimeType = "image/jpeg"; + } else if (fixedString.upper() == "PNG") { + d->mimeType = "image/png"; + } else { + debug("probably unsupported image type"); + d->mimeType = "image/" + fixedString; + } + + d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++]; + d->description = readStringField(data, d->textEncoding, &pos); + + d->data = data.mid(pos); +} + +AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h) +{ + // set v2.2 header to make fieldData work correctly + setHeader(h, true); + + parseFields(fieldData(data)); + + // now set the v2.4 header + Frame::Header *newHeader = new Frame::Header("APIC"); + newHeader->setFrameSize(h->frameSize()); + setHeader(newHeader, true); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.h new file mode 100644 index 00000000..55067bd2 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/attachedpictureframe.h @@ -0,0 +1,230 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ATTACHEDPICTUREFRAME_H +#define TAGLIB_ATTACHEDPICTUREFRAME_H + +#include "id3v2frame.h" +#include "id3v2header.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 attached picture frame implementation + + /*! + * This is an implementation of ID3v2 attached pictures. Pictures may be + * included in tags, one per APIC frame (but there may be multiple APIC + * frames in a single tag). These pictures are usually in either JPEG or + * PNG format. + */ + + class TAGLIB_EXPORT AttachedPictureFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + /*! + * Constructs an empty picture frame. The description, content and text + * encoding should be set manually. + */ + AttachedPictureFrame(); + + /*! + * Constructs an AttachedPicture frame based on \a data. + */ + explicit AttachedPictureFrame(const ByteVector &data); + + /*! + * Destroys the AttahcedPictureFrame instance. + */ + virtual ~AttachedPictureFrame(); + + /*! + * Returns a string containing the description and mime-type + */ + virtual String toString() const; + + /*! + * Returns the text encoding used for the description. + * + * \see setTextEncoding() + * \see description() + */ + String::Type textEncoding() const; + + /*! + * Set the text encoding used for the description. + * + * \see description() + */ + void setTextEncoding(String::Type t); + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + void setMimeType(const String &m); + + /*! + * Returns the type of the image. + * + * \see Type + * \see setType() + */ + Type type() const; + + /*! + * Sets the type for the image. + * + * \see Type + * \see type() + */ + void setType(Type t); + + /*! + * Returns a text description of the image. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ + + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ + + void setDescription(const String &desc); + + /*! + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ + ByteVector picture() const; + + /*! + * Sets the image data to \a p. \a p should be of the type specified in + * this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ + void setPicture(const ByteVector &p); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + class AttachedPictureFramePrivate; + AttachedPictureFramePrivate *d; + + private: + AttachedPictureFrame(const AttachedPictureFrame &); + AttachedPictureFrame &operator=(const AttachedPictureFrame &); + AttachedPictureFrame(const ByteVector &data, Header *h); + + }; + + //! support for ID3v2.2 PIC frames + class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame + { + protected: + virtual void parseFields(const ByteVector &data); + private: + AttachedPictureFrameV22(const ByteVector &data, Header *h); + friend class FrameFactory; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.cpp new file mode 100644 index 00000000..406598d9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.cpp @@ -0,0 +1,178 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "commentsframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class CommentsFrame::CommentsFramePrivate +{ +public: + CommentsFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + ByteVector language; + String description; + String text; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM") +{ + d = new CommentsFramePrivate; + d->textEncoding = encoding; +} + +CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data) +{ + d = new CommentsFramePrivate; + setData(data); +} + +CommentsFrame::~CommentsFrame() +{ + delete d; +} + +String CommentsFrame::toString() const +{ + return d->text; +} + +ByteVector CommentsFrame::language() const +{ + return d->language; +} + +String CommentsFrame::description() const +{ + return d->description; +} + +String CommentsFrame::text() const +{ + return d->text; +} + +void CommentsFrame::setLanguage(const ByteVector &languageEncoding) +{ + d->language = languageEncoding.mid(0, 3); +} + +void CommentsFrame::setDescription(const String &s) +{ + d->description = s; +} + +void CommentsFrame::setText(const String &s) +{ + d->text = s; +} + +String::Type CommentsFrame::textEncoding() const +{ + return d->textEncoding; +} + +void CommentsFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static +{ + ID3v2::FrameList comments = tag->frameList("COMM"); + + for(ID3v2::FrameList::ConstIterator it = comments.begin(); + it != comments.end(); + ++it) + { + CommentsFrame *frame = dynamic_cast(*it); + if(frame && frame->description() == d) + return frame; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void CommentsFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("A comment frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + d->language = data.mid(1, 3); + + int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + + if(l.size() == 2) { + d->description = String(l.front(), d->textEncoding); + d->text = String(l.back(), d->textEncoding); + } +} + +ByteVector CommentsFrame::renderFields() const +{ + ByteVector v; + + String::Type encoding = d->textEncoding; + + encoding = checkEncoding(d->description, encoding); + encoding = checkEncoding(d->text, encoding); + + v.append(char(encoding)); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); + v.append(d->text.data(encoding)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new CommentsFramePrivate(); + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.h new file mode 100644 index 00000000..def01dcf --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/commentsframe.h @@ -0,0 +1,168 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_COMMENTSFRAME_H +#define TAGLIB_COMMENTSFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 comments + + /*! + * This implements the ID3v2 comment format. An ID3v2 comment concists of + * a language encoding, a description and a single text field. + */ + + class TAGLIB_EXPORT CommentsFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty comment frame that will use the text encoding + * \a encoding. + */ + explicit CommentsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a comment based on the data in \a data. + */ + explicit CommentsFrame(const ByteVector &data); + + /*! + * Destroys this CommentFrame instance. + */ + virtual ~CommentsFrame(); + + /*! + * Returns the text of this comment. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the description of this comment. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text of this comment. + * + * \see setText() + */ + String text() const; + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Sets the description of the comment to \a s. + * + * \see decription() + */ + void setDescription(const String &s); + + /*! + * Sets the text portion of the comment to \a s. + * + * \see text() + */ + virtual void setText(const String &s); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Comments each have a unique description. This searches for a comment + * frame with the decription \a d and returns a pointer to it. If no + * frame is found that matches the given description null is returned. + * + * \see description() + */ + static CommentsFrame *findByDescription(const Tag *tag, const String &d); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + CommentsFrame(const ByteVector &data, Header *h); + CommentsFrame(const CommentsFrame &); + CommentsFrame &operator=(const CommentsFrame &); + + class CommentsFramePrivate; + CommentsFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp new file mode 100644 index 00000000..fa3509b1 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Aaron VonderHaar + email : avh4@users.sourceforge.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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include "generalencapsulatedobjectframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate +{ +public: + GeneralEncapsulatedObjectFramePrivate() : textEncoding(String::Latin1) {} + + String::Type textEncoding; + String mimeType; + String fileName; + String description; + ByteVector data; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : Frame("GEOB") +{ + d = new GeneralEncapsulatedObjectFramePrivate; +} + +GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : Frame(data) +{ + d = new GeneralEncapsulatedObjectFramePrivate; + setData(data); +} + +GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame() +{ + delete d; +} + +String GeneralEncapsulatedObjectFrame::toString() const +{ + String text = "[" + d->mimeType + "]"; + + if(!d->fileName.isEmpty()) + text += " " + d->fileName; + + if(!d->description.isEmpty()) + text += " \"" + d->description + "\""; + + return text; +} + +String::Type GeneralEncapsulatedObjectFrame::textEncoding() const +{ + return d->textEncoding; +} + +void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +String GeneralEncapsulatedObjectFrame::mimeType() const +{ + return d->mimeType; +} + +void GeneralEncapsulatedObjectFrame::setMimeType(const String &type) +{ + d->mimeType = type; +} + +String GeneralEncapsulatedObjectFrame::fileName() const +{ + return d->fileName; +} + +void GeneralEncapsulatedObjectFrame::setFileName(const String &name) +{ + d->fileName = name; +} + +String GeneralEncapsulatedObjectFrame::description() const +{ + return d->description; +} + +void GeneralEncapsulatedObjectFrame::setDescription(const String &desc) +{ + d->description = desc; +} + +ByteVector GeneralEncapsulatedObjectFrame::object() const +{ + return d->data; +} + +void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data) +{ + d->data = data; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 4) { + debug("An object frame must contain at least 4 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + + int pos = 1; + + d->mimeType = readStringField(data, String::Latin1, &pos); + d->fileName = readStringField(data, d->textEncoding, &pos); + d->description = readStringField(data, d->textEncoding, &pos); + + d->data = data.mid(pos); +} + +ByteVector GeneralEncapsulatedObjectFrame::renderFields() const +{ + ByteVector data; + + data.append(char(d->textEncoding)); + data.append(d->mimeType.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + data.append(d->fileName.data(d->textEncoding)); + data.append(textDelimiter(d->textEncoding)); + data.append(d->description.data(d->textEncoding)); + data.append(textDelimiter(d->textEncoding)); + data.append(d->data); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new GeneralEncapsulatedObjectFramePrivate; + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h new file mode 100644 index 00000000..42f854cc --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h @@ -0,0 +1,178 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Aaron VonderHaar + email : avh4@users.sourceforge.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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_GENERALENCAPSULATEDOBJECT_H +#define TAGLIB_GENERALENCAPSULATEDOBJECT_H + +#include "id3v2frame.h" +#include "id3v2header.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 general encapsulated object frame implementation + + /*! + * This is an implementation of ID3v2 general encapsulated objects. + * Arbitrary binary data may be included in tags, stored in GEOB frames. + * There may be multiple GEOB frames in a single tag. Each GEOB it + * labelled with a content description (which may be blank), a required + * mime-type, and a file name (may be blank). The content description + * uniquely identifies the GEOB frame in the tag. + */ + + class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * Constructs an empty object frame. The description, file name and text + * encoding should be set manually. + */ + GeneralEncapsulatedObjectFrame(); + + /*! + * Constructs a GeneralEncapsulatedObjectFrame frame based on \a data. + * + * \warning This is \em not data for the encapsulated object, for that use + * setObject(). This constructor is used when reading the frame from the + * disk. + */ + explicit GeneralEncapsulatedObjectFrame(const ByteVector &data); + + /*! + * Destroys the GeneralEncapsulatedObjectFrame instance. + */ + virtual ~GeneralEncapsulatedObjectFrame(); + + /*! + * Returns a string containing the description, file name and mime-type + */ + virtual String toString() const; + + /*! + * Returns the text encoding used for the description and file name. + * + * \see setTextEncoding() + * \see description() + * \see fileName() + */ + String::Type textEncoding() const; + + /*! + * Set the text encoding used for the description and file name. + * + * \see description() + * \see fileName() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns the mime type of the object. + */ + String mimeType() const; + + /*! + * Sets the mime type of the object. + */ + void setMimeType(const String &type); + + /*! + * Returns the file name of the object. + * + * \see setFileName() + */ + String fileName() const; + + /*! + * Sets the file name for the object. + * + * \see fileName() + */ + void setFileName(const String &name); + + /*! + * Returns the content description of the object. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ + + String description() const; + + /*! + * Sets the content description of the object to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ + + void setDescription(const String &desc); + + /*! + * Returns the object data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setObject() + * \see mimeType() + */ + ByteVector object() const; + + /*! + * Sets the object data to \a data. \a data should be of the type specified in + * this frame's mime-type specification. + * + * \see object() + * \see mimeType() + * \see setMimeType() + */ + void setObject(const ByteVector &object); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h); + GeneralEncapsulatedObjectFrame(const GeneralEncapsulatedObjectFrame &); + GeneralEncapsulatedObjectFrame &operator=(const GeneralEncapsulatedObjectFrame &); + + class GeneralEncapsulatedObjectFramePrivate; + GeneralEncapsulatedObjectFramePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.cpp new file mode 100644 index 00000000..cfe8c9f4 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.cpp @@ -0,0 +1,137 @@ +/*************************************************************************** + copyright : (C) 2008 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include "popularimeterframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class PopularimeterFrame::PopularimeterFramePrivate +{ +public: + PopularimeterFramePrivate() : rating(0), counter(0) {} + String email; + int rating; + TagLib::uint counter; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +PopularimeterFrame::PopularimeterFrame() : Frame("POPM") +{ + d = new PopularimeterFramePrivate; +} + +PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data) +{ + d = new PopularimeterFramePrivate; + setData(data); +} + +PopularimeterFrame::~PopularimeterFrame() +{ + delete d; +} + +String PopularimeterFrame::toString() const +{ + return d->email + " rating=" + String::number(d->rating) + " counter=" + String::number(d->counter); +} + +String PopularimeterFrame::email() const +{ + return d->email; +} + +void PopularimeterFrame::setEmail(const String &s) +{ + d->email = s; +} + +int PopularimeterFrame::rating() const +{ + return d->rating; +} + +void PopularimeterFrame::setRating(int s) +{ + d->rating = s; +} + +TagLib::uint PopularimeterFrame::counter() const +{ + return d->counter; +} + +void PopularimeterFrame::setCounter(TagLib::uint s) +{ + d->counter = s; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void PopularimeterFrame::parseFields(const ByteVector &data) +{ + int pos = 0, size = int(data.size()); + + d->email = readStringField(data, String::Latin1, &pos); + + d->rating = 0; + d->counter = 0; + if(pos < size) { + d->rating = (unsigned char)(data[pos++]); + if(pos < size) { + d->counter = data.mid(pos, 4).toUInt(); + } + } +} + +ByteVector PopularimeterFrame::renderFields() const +{ + ByteVector data; + + data.append(d->email.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + data.append(char(d->rating)); + data.append(ByteVector::fromUInt(d->counter)); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new PopularimeterFramePrivate; + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.h new file mode 100644 index 00000000..d39f1aa8 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/popularimeterframe.h @@ -0,0 +1,132 @@ +/*************************************************************************** + copyright : (C) 2008 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_POPULARIMETERFRAME_H +#define TAGLIB_POPULARIMETERFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 "popularimeter" + + /*! + * This implements the ID3v2 popularimeter (POPM frame). It concists of + * an email, a rating and an optional counter. + */ + + class TAGLIB_EXPORT PopularimeterFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty popularimeter frame. + */ + explicit PopularimeterFrame(); + + /*! + * Construct a popularimeter based on the data in \a data. + */ + explicit PopularimeterFrame(const ByteVector &data); + + /*! + * Destroys this PopularimeterFrame instance. + */ + virtual ~PopularimeterFrame(); + + /*! + * Returns the text of this popularimeter. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the email. + * + * \see setEmail() + */ + String email() const; + + /*! + * Set the email. + * + * \see email() + */ + void setEmail(const String &email); + + /*! + * Returns the rating. + * + * \see setRating() + */ + int rating() const; + + /*! + * Set the rating. + * + * \see rating() + */ + void setRating(int rating); + + /*! + * Returns the counter. + * + * \see setCounter() + */ + uint counter() const; + + /*! + * Set the counter. + * + * \see counter() + */ + void setCounter(uint counter); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PopularimeterFrame(const ByteVector &data, Header *h); + PopularimeterFrame(const PopularimeterFrame &); + PopularimeterFrame &operator=(const PopularimeterFrame &); + + class PopularimeterFramePrivate; + PopularimeterFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.cpp new file mode 100644 index 00000000..f2d2a03c --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.cpp @@ -0,0 +1,128 @@ +/*************************************************************************** + copyright : (C) 2008 by Serkan Kalyoncu + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "privateframe.h" + +using namespace TagLib; +using namespace ID3v2; + + +class PrivateFrame::PrivateFramePrivate +{ +public: + ByteVector data; + String owner; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +PrivateFrame::PrivateFrame() : Frame("PRIV") +{ + d = new PrivateFramePrivate; +} + +PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data) +{ + d = new PrivateFramePrivate; + setData(data); +} + +PrivateFrame::~PrivateFrame() +{ + delete d; +} + +String PrivateFrame::toString() const +{ + return d->owner; +} + +String PrivateFrame::owner() const +{ + return d->owner; +} + +ByteVector PrivateFrame::data() const +{ + return d->data; +} + +void PrivateFrame::setOwner(const String &s) +{ + d->owner = s; +} + +void PrivateFrame::setData(const ByteVector & data) +{ + d->data = data; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void PrivateFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 2) { + debug("A private frame must contain at least 2 bytes."); + return; + } + + // Owner identifier is assumed to be Latin1 + + const int byteAlign = 1; + const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign); + + d->owner = String(data.mid(0, endOfOwner)); + d->data = data.mid(endOfOwner + 1); +} + +ByteVector PrivateFrame::renderFields() const +{ + ByteVector v; + + v.append(d->owner.data(String::Latin1)); + v.append(textDelimiter(String::Latin1)); + v.append(d->data); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new PrivateFramePrivate(); + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.h new file mode 100644 index 00000000..06f82f32 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/privateframe.h @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2008 by Serkan Kalyoncu + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_PRIVATEFRAME_H +#define TAGLIB_PRIVATEFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 privateframe + + class TAGLIB_EXPORT PrivateFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty private frame. + */ + PrivateFrame(); + + /*! + * Construct a private frame based on the data in \a data. + * + * \note This is the constructor used when parsing the frame from a file. + */ + explicit PrivateFrame(const ByteVector &data); + + /*! + * Destroys this private frame instance. + */ + virtual ~PrivateFrame(); + + /*! + * Returns the text of this private frame, currently just the owner. + * + * \see text() + */ + virtual String toString() const; + + /*! + * \return The owner of the private frame. + * \note This should contain an email address or link to a website. + */ + String owner() const; + + /*! + * + */ + ByteVector data() const; + + /*! + * Sets the owner of the frame to \a s. + * \note This should contain an email address or link to a website. + */ + void setOwner(const String &s); + + /*! + * + */ + void setData(const ByteVector &v); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PrivateFrame(const ByteVector &data, Header *h); + + PrivateFrame(const PrivateFrame &); + PrivateFrame &operator=(const PrivateFrame &); + + class PrivateFramePrivate; + PrivateFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp new file mode 100644 index 00000000..955b3ad0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp @@ -0,0 +1,236 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "relativevolumeframe.h" + +using namespace TagLib; +using namespace ID3v2; + +static inline int bitsToBytes(int i) +{ + return i % 8 == 0 ? i / 8 : (i - i % 8) / 8 + 1; +} + +struct ChannelData +{ + ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {} + + RelativeVolumeFrame::ChannelType channelType; + short volumeAdjustment; + RelativeVolumeFrame::PeakVolume peakVolume; +}; + +class RelativeVolumeFrame::RelativeVolumeFramePrivate +{ +public: + String identification; + Map channels; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2") +{ + d = new RelativeVolumeFramePrivate; +} + +RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data) +{ + d = new RelativeVolumeFramePrivate; + setData(data); +} + +RelativeVolumeFrame::~RelativeVolumeFrame() +{ + delete d; +} + +String RelativeVolumeFrame::toString() const +{ + return d->identification; +} + +List RelativeVolumeFrame::channels() const +{ + List l; + + Map::ConstIterator it = d->channels.begin(); + for(; it != d->channels.end(); ++it) + l.append((*it).first); + + return l; +} + +// deprecated + +RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const +{ + return MasterVolume; +} + +// deprecated + +void RelativeVolumeFrame::setChannelType(ChannelType) +{ + +} + +short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const +{ + return d->channels.contains(type) ? d->channels[type].volumeAdjustment : 0; +} + +short RelativeVolumeFrame::volumeAdjustmentIndex() const +{ + return volumeAdjustmentIndex(MasterVolume); +} + +void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type) +{ + d->channels[type].volumeAdjustment = index; +} + +void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index) +{ + setVolumeAdjustmentIndex(index, MasterVolume); +} + +float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const +{ + return d->channels.contains(type) ? float(d->channels[type].volumeAdjustment) / float(512) : 0; +} + +float RelativeVolumeFrame::volumeAdjustment() const +{ + return volumeAdjustment(MasterVolume); +} + +void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type) +{ + d->channels[type].volumeAdjustment = short(adjustment * float(512)); +} + +void RelativeVolumeFrame::setVolumeAdjustment(float adjustment) +{ + setVolumeAdjustment(adjustment, MasterVolume); +} + +RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const +{ + return d->channels.contains(type) ? d->channels[type].peakVolume : PeakVolume(); +} + +RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const +{ + return peakVolume(MasterVolume); +} + +void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type) +{ + d->channels[type].peakVolume = peak; +} + +void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak) +{ + setPeakVolume(peak, MasterVolume); +} + +String RelativeVolumeFrame::identification() const +{ + return d->identification; +} + +void RelativeVolumeFrame::setIdentification(const String &s) +{ + d->identification = s; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void RelativeVolumeFrame::parseFields(const ByteVector &data) +{ + int pos = 0; + d->identification = readStringField(data, String::Latin1, &pos); + + // Each channel is at least 4 bytes. + + while(pos <= (int)data.size() - 4) { + + + ChannelType type = ChannelType(data[pos]); + pos += 1; + + ChannelData &channel = d->channels[type]; + + channel.volumeAdjustment = data.mid(pos, 2).toShort(); + pos += 2; + + channel.peakVolume.bitsRepresentingPeak = data[pos]; + pos += 1; + + int bytes = bitsToBytes(channel.peakVolume.bitsRepresentingPeak); + channel.peakVolume.peakVolume = data.mid(pos, bytes); + pos += bytes; + } +} + +ByteVector RelativeVolumeFrame::renderFields() const +{ + ByteVector data; + + data.append(d->identification.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + + Map::ConstIterator it = d->channels.begin(); + + for(; it != d->channels.end(); ++it) { + ChannelType type = (*it).first; + const ChannelData &channel = (*it).second; + + data.append(char(type)); + data.append(ByteVector::fromShort(channel.volumeAdjustment)); + data.append(char(channel.peakVolume.bitsRepresentingPeak)); + data.append(channel.peakVolume.peakVolume); + } + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new RelativeVolumeFramePrivate; + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.h new file mode 100644 index 00000000..dad4e7d4 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/relativevolumeframe.h @@ -0,0 +1,274 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RELATIVEVOLUMEFRAME_H +#define TAGLIB_RELATIVEVOLUMEFRAME_H + +#include "tlist.h" +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 relative volume adjustment frame implementation + + /*! + * This is an implementation of ID3v2 relative volume adjustment. The + * presence of this frame makes it possible to specify an increase in volume + * for an audio file or specific audio tracks in that file. + * + * Multiple relative volume adjustment frames may be present in the tag + * each with a unique identification and describing volume adjustment for + * different channel types. + */ + + class TAGLIB_EXPORT RelativeVolumeFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * This indicates the type of volume adjustment that should be applied. + */ + enum ChannelType { + //! A type not enumerated below + Other = 0x00, + //! The master volume for the track + MasterVolume = 0x01, + //! The front right audio channel + FrontRight = 0x02, + //! The front left audio channel + FrontLeft = 0x03, + //! The back right audio channel + BackRight = 0x04, + //! The back left audio channel + BackLeft = 0x05, + //! The front center audio channel + FrontCentre = 0x06, + //! The back center audio channel + BackCentre = 0x07, + //! The subwoofer audio channel + Subwoofer = 0x08 + }; + + //! Struct that stores the relevant values for ID3v2 peak volume + + /*! + * The peak volume is described as a series of bits that is padded to fill + * a block of bytes. These two values should always be updated in tandem. + */ + struct PeakVolume + { + /*! + * Constructs an empty peak volume description. + */ + PeakVolume() : bitsRepresentingPeak(0) {} + /*! + * The number of bits (in the range of 0 to 255) used to describe the + * peak volume. + */ + unsigned char bitsRepresentingPeak; + /*! + * The array of bits (represented as a series of bytes) used to describe + * the peak volume. + */ + ByteVector peakVolume; + }; + + /*! + * Constructs a RelativeVolumeFrame. The relevant data should be set + * manually. + */ + RelativeVolumeFrame(); + + /*! + * Constructs a RelativeVolumeFrame based on the contents of \a data. + */ + RelativeVolumeFrame(const ByteVector &data); + + /*! + * Destroys the RelativeVolumeFrame instance. + */ + virtual ~RelativeVolumeFrame(); + + /*! + * Returns the frame's identification. + * + * \see identification() + */ + virtual String toString() const; + + /*! + * Returns a list of channels with information currently in the frame. + */ + List channels() const; + + /*! + * \deprecated Always returns master volume. + */ + ChannelType channelType() const; + + /*! + * \deprecated This method no longer has any effect. + */ + void setChannelType(ChannelType t); + + /* + * There was a terrible API goof here, and while this can't be changed to + * the way it appears below for binary compaibility reasons, let's at + * least pretend that it looks clean. + */ + +#ifdef DOXYGEN + + /*! + * Returns the relative volume adjustment "index". As indicated by the + * ID3v2 standard this is a 16-bit signed integer that reflects the + * decibils of adjustment when divided by 512. + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustmentIndex() + * \see volumeAjustment() + */ + short volumeAdjustmentIndex(ChannelType type = MasterVolume) const; + + /*! + * Set the volume adjustment to \a index. As indicated by the ID3v2 + * standard this is a 16-bit signed integer that reflects the decibils of + * adjustment when divided by 512. + * + * By default this sets the value for the master volume. + * + * \see volumeAdjustmentIndex() + * \see setVolumeAjustment() + */ + void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume); + + /*! + * Returns the relative volume adjustment in decibels. + * + * \note Because this is actually stored internally as an "index" to this + * value the value returned by this method may not be identical to the + * value set using setVolumeAdjustment(). + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ + float volumeAdjustment(ChannelType type = MasterVolume) const; + + /*! + * Set the relative volume adjustment in decibels to \a adjustment. + * + * By default this sets the value for the master volume. + * + * \note Because this is actually stored internally as an "index" to this + * value the value set by this method may not be identical to the one + * returned by volumeAdjustment(). + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ + void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume); + + /*! + * Returns the peak volume (represented as a length and a string of bits). + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setPeakVolume() + */ + PeakVolume peakVolume(ChannelType type = MasterVolume) const; + + /*! + * Sets the peak volume to \a peak. + * + * By default this sets the value for the master volume. + * + * \see peakVolume() + */ + void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume); + +#else + + // BIC: Combine each of the following pairs of functions (or maybe just + // rework this junk altogether). + + short volumeAdjustmentIndex(ChannelType type) const; + short volumeAdjustmentIndex() const; + + void setVolumeAdjustmentIndex(short index, ChannelType type); + void setVolumeAdjustmentIndex(short index); + + float volumeAdjustment(ChannelType type) const; + float volumeAdjustment() const; + + void setVolumeAdjustment(float adjustment, ChannelType type); + void setVolumeAdjustment(float adjustment); + + PeakVolume peakVolume(ChannelType type) const; + PeakVolume peakVolume() const; + + void setPeakVolume(const PeakVolume &peak, ChannelType type); + void setPeakVolume(const PeakVolume &peak); + +#endif + + /*! + * Returns the identification for this frame. + */ + String identification() const; + + /*! + * Sets the identification of the frame to \a s. The string + * is used to identify the situation and/or device where this + * adjustment should apply. + */ + void setIdentification(const String &s); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + RelativeVolumeFrame(const ByteVector &data, Header *h); + RelativeVolumeFrame(const RelativeVolumeFrame &); + RelativeVolumeFrame &operator=(const RelativeVolumeFrame &); + + class RelativeVolumeFramePrivate; + RelativeVolumeFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.cpp new file mode 100644 index 00000000..7c2ab909 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.cpp @@ -0,0 +1,271 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "textidentificationframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class TextIdentificationFrame::TextIdentificationFramePrivate +{ +public: + TextIdentificationFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + StringList fieldList; +}; + +//////////////////////////////////////////////////////////////////////////////// +// TextIdentificationFrame public members +//////////////////////////////////////////////////////////////////////////////// + +TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) : + Frame(type) +{ + d = new TextIdentificationFramePrivate; + d->textEncoding = encoding; +} + +TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) : + Frame(data) +{ + d = new TextIdentificationFramePrivate; + setData(data); +} + +TextIdentificationFrame::~TextIdentificationFrame() +{ + delete d; +} + +void TextIdentificationFrame::setText(const StringList &l) +{ + d->fieldList = l; +} + +void TextIdentificationFrame::setText(const String &s) +{ + d->fieldList = s; +} + +String TextIdentificationFrame::toString() const +{ + return d->fieldList.toString(); +} + +StringList TextIdentificationFrame::fieldList() const +{ + return d->fieldList; +} + +String::Type TextIdentificationFrame::textEncoding() const +{ + return d->textEncoding; +} + +void TextIdentificationFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +//////////////////////////////////////////////////////////////////////////////// +// TextIdentificationFrame protected members +//////////////////////////////////////////////////////////////////////////////// + +void TextIdentificationFrame::parseFields(const ByteVector &data) +{ + // Don't try to parse invalid frames + + if(data.size() < 2) + return; + + // read the string data type (the first byte of the field data) + + d->textEncoding = String::Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + + int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + + int dataLength = data.size() - 1; + + while(dataLength > 0 && data[dataLength] == 0) + dataLength--; + + while(dataLength % byteAlign != 0) + dataLength++; + + ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign); + + d->fieldList.clear(); + + // append those split values to the list and make sure that the new string's + // type is the same specified for this frame + + for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) { + if(!(*it).isEmpty()) { + String s(*it, d->textEncoding); + d->fieldList.append(s); + } + } +} + +ByteVector TextIdentificationFrame::renderFields() const +{ + String::Type encoding = checkEncoding(d->fieldList, d->textEncoding); + + ByteVector v; + + v.append(char(encoding)); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + + // Since the field list is null delimited, if this is not the first + // element in the list, append the appropriate delimiter for this + // encoding. + + if(it != d->fieldList.begin()) + v.append(textDelimiter(encoding)); + + v.append((*it).data(encoding)); + } + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// TextIdentificationFrame private members +//////////////////////////////////////////////////////////////////////////////// + +TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new TextIdentificationFramePrivate; + parseFields(fieldData(data)); +} + +//////////////////////////////////////////////////////////////////////////////// +// UserTextIdentificationFrame public members +//////////////////////////////////////////////////////////////////////////////// + +UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : + TextIdentificationFrame("TXXX", encoding), + d(0) +{ + StringList l; + l.append(String::null); + l.append(String::null); + setText(l); +} + + +UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) : + TextIdentificationFrame(data) +{ + checkFields(); +} + +String UserTextIdentificationFrame::toString() const +{ + return "[" + description() + "] " + fieldList().toString(); +} + +String UserTextIdentificationFrame::description() const +{ + return !TextIdentificationFrame::fieldList().isEmpty() + ? TextIdentificationFrame::fieldList().front() + : String::null; +} + +StringList UserTextIdentificationFrame::fieldList() const +{ + // TODO: remove this function + + return TextIdentificationFrame::fieldList(); +} + +void UserTextIdentificationFrame::setText(const String &text) +{ + if(description().isEmpty()) + setDescription(String::null); + + TextIdentificationFrame::setText(StringList(description()).append(text)); +} + +void UserTextIdentificationFrame::setText(const StringList &fields) +{ + if(description().isEmpty()) + setDescription(String::null); + + TextIdentificationFrame::setText(StringList(description()).append(fields)); +} + +void UserTextIdentificationFrame::setDescription(const String &s) +{ + StringList l = fieldList(); + + if(l.isEmpty()) + l.append(s); + else + l[0] = s; + + TextIdentificationFrame::setText(l); +} + +UserTextIdentificationFrame *UserTextIdentificationFrame::find( + ID3v2::Tag *tag, const String &description) // static +{ + FrameList l = tag->frameList("TXXX"); + for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) { + UserTextIdentificationFrame *f = dynamic_cast(*it); + if(f && f->description() == description) + return f; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// UserTextIdentificationFrame private members +//////////////////////////////////////////////////////////////////////////////// + +UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) : + TextIdentificationFrame(data, h) +{ + checkFields(); +} + +void UserTextIdentificationFrame::checkFields() +{ + int fields = fieldList().size(); + + if(fields == 0) + setDescription(String::null); + if(fields <= 1) + setText(String::null); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.h new file mode 100644 index 00000000..418ef970 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/textidentificationframe.h @@ -0,0 +1,258 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TEXTIDENTIFICATIONFRAME_H +#define TAGLIB_TEXTIDENTIFICATIONFRAME_H + +#include "tstringlist.h" +#include "taglib_export.h" + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + class Tag; + + //! An ID3v2 text identification frame implementation + + /*! + * This is an implementation of the most common type of ID3v2 frame -- text + * identification frames. There are a number of variations on this. Those + * enumerated in the ID3v2.4 standard are: + * + *
    + *
  • TALB Album/Movie/Show title
  • + *
  • TBPM BPM (beats per minute)
  • + *
  • TCOM Composer
  • + *
  • TCON Content type
  • + *
  • TCOP Copyright message
  • + *
  • TDEN Encoding time
  • + *
  • TDLY Playlist delay
  • + *
  • TDOR Original release time
  • + *
  • TDRC Recording time
  • + *
  • TDRL Release time
  • + *
  • TDTG Tagging time
  • + *
  • TENC Encoded by
  • + *
  • TEXT Lyricist/Text writer
  • + *
  • TFLT File type
  • + *
  • TIPL Involved people list
  • + *
  • TIT1 Content group description
  • + *
  • TIT2 Title/songname/content description
  • + *
  • TIT3 Subtitle/Description refinement
  • + *
  • TKEY Initial key
  • + *
  • TLAN Language(s)
  • + *
  • TLEN Length
  • + *
  • TMCL Musician credits list
  • + *
  • TMED Media type
  • + *
  • TMOO Mood
  • + *
  • TOAL Original album/movie/show title
  • + *
  • TOFN Original filename
  • + *
  • TOLY Original lyricist(s)/text writer(s)
  • + *
  • TOPE Original artist(s)/performer(s)
  • + *
  • TOWN File owner/licensee
  • + *
  • TPE1 Lead performer(s)/Soloist(s)
  • + *
  • TPE2 Band/orchestra/accompaniment
  • + *
  • TPE3 Conductor/performer refinement
  • + *
  • TPE4 Interpreted, remixed, or otherwise modified by
  • + *
  • TPOS Part of a set
  • + *
  • TPRO Produced notice
  • + *
  • TPUB Publisher
  • + *
  • TRCK Track number/Position in set
  • + *
  • TRSN Internet radio station name
  • + *
  • TRSO Internet radio station owner
  • + *
  • TSOA Album sort order
  • + *
  • TSOP Performer sort order
  • + *
  • TSOT Title sort order
  • + *
  • TSRC ISRC (international standard recording code)
  • + *
  • TSSE Software/Hardware and settings used for encoding
  • + *
  • TSST Set subtitle
  • + *
+ * + * The ID3v2 Frames document gives a description of each of these formats + * and the expected order of strings in each. ID3v2::Header::frameID() can + * be used to determine the frame type. + * + * \note If non-Latin1 compatible strings are used with this class, even if + * the text encoding is set to Latin1, the frame will be written using UTF8 + * (with the encoding flag appropriately set in the output). + */ + + class TAGLIB_EXPORT TextIdentificationFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty frame of type \a type. Uses \a encoding as the + * default text encoding. + * + * \note In this case you must specify the text encoding as it + * resolves the ambiguity between constructors. + * + * \note Please see the note in the class description regarding Latin1. + */ + TextIdentificationFrame(const ByteVector &type, String::Type encoding); + + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit TextIdentificationFrame(const ByteVector &data); + + /*! + * Destroys this TextIdentificationFrame instance. + */ + virtual ~TextIdentificationFrame(); + + /*! + * Text identification frames are a list of string fields. + * + * This function will accept either a StringList or a String (using the + * StringList constructor that accepts a single String). + * + * \note This will not change the text encoding of the frame even if the + * strings passed in are not of the same encoding. Please use + * setEncoding(s.type()) if you wish to change the encoding of the frame. + */ + void setText(const StringList &l); + + // Reimplementations. + + virtual void setText(const String &s); + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns a list of the strings in this frame. + */ + StringList fieldList() const; + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + TextIdentificationFrame(const ByteVector &data, Header *h); + + private: + TextIdentificationFrame(const TextIdentificationFrame &); + TextIdentificationFrame &operator=(const TextIdentificationFrame &); + + class TextIdentificationFramePrivate; + TextIdentificationFramePrivate *d; + }; + + /*! + * This is a specialization of text identification frames that allows for + * user defined entries. Each entry has a description in addition to the + * normal list of fields that a text identification frame has. + * + * This description identifies the frame and must be unique. + */ + + //! An ID3v2 custom text identification frame implementationx + + class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame + { + friend class FrameFactory; + + public: + /*! + * Constructs an empty user defined text identification frame. For this to be + * a useful frame both a description and text must be set. + */ + explicit UserTextIdentificationFrame(String::Type encoding = String::Latin1); + + /*! + * Creates a frame based on \a data. + */ + explicit UserTextIdentificationFrame(const ByteVector &data); + + virtual String toString() const; + + /*! + * Returns the description for this frame. + */ + String description() const; + + /*! + * Sets the description of the frame to \a s. \a s must be unique. You can + * check for the presence of another user defined text frame of the same type + * using find() and testing for null. + */ + void setDescription(const String &s); + + StringList fieldList() const; + void setText(const String &text); + void setText(const StringList &fields); + + /*! + * Searches for the user defined text frame with the description \a description + * in \a tag. This returns null if no matching frames were found. + */ + static UserTextIdentificationFrame *find(Tag *tag, const String &description); + + private: + UserTextIdentificationFrame(const ByteVector &data, Header *h); + UserTextIdentificationFrame(const TextIdentificationFrame &); + UserTextIdentificationFrame &operator=(const UserTextIdentificationFrame &); + + void checkFields(); + + class UserTextIdentificationFramePrivate; + UserTextIdentificationFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp new file mode 100644 index 00000000..e12583ad --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp @@ -0,0 +1,118 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "uniquefileidentifierframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class UniqueFileIdentifierFrame::UniqueFileIdentifierFramePrivate +{ +public: + String owner; + ByteVector identifier; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data) : + ID3v2::Frame(data) +{ + d = new UniqueFileIdentifierFramePrivate; + setData(data); +} + +UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const String &owner, const ByteVector &id) : + ID3v2::Frame("UFID") +{ + d = new UniqueFileIdentifierFramePrivate; + d->owner = owner; + d->identifier = id; +} + +UniqueFileIdentifierFrame::~UniqueFileIdentifierFrame() +{ + delete d; +} + +String UniqueFileIdentifierFrame::owner() const +{ + return d->owner; +} + +ByteVector UniqueFileIdentifierFrame::identifier() const +{ + return d->identifier; +} + +void UniqueFileIdentifierFrame::setOwner(const String &s) +{ + d->owner = s; +} + +void UniqueFileIdentifierFrame::setIdentifier(const ByteVector &v) +{ + d->identifier = v; +} + +String UniqueFileIdentifierFrame::toString() const +{ + return String::null; +} + +void UniqueFileIdentifierFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 1) { + debug("An UFID frame must contain at least 1 byte."); + return; + } + + int pos = 0; + d->owner = readStringField(data, String::Latin1, &pos); + d->identifier = data.mid(pos); +} + +ByteVector UniqueFileIdentifierFrame::renderFields() const +{ + ByteVector data; + + data.append(d->owner.data(String::Latin1)); + data.append(char(0)); + data.append(d->identifier); + + return data; +} + +UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data, Header *h) : + Frame(h) +{ + d = new UniqueFileIdentifierFramePrivate; + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h new file mode 100644 index 00000000..1292b392 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h @@ -0,0 +1,113 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNIQUEFILEIDENTIFIERFRAME +#define TAGLIB_UNIQUEFILEIDENTIFIERFRAME + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + /*! + * This is an implementation of ID3v2 unique file identifier frames. This + * frame is used to identify the file in an arbitrary database identified + * by the owner field. + */ + + //! An implementation of ID3v2 unique identifier frames + + class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame + { + friend class FrameFactory; + + public: + /*! + * Creates a uniqe file identifier frame based on \a data. + */ + UniqueFileIdentifierFrame(const ByteVector &data); + + /*! + * Creates a unique file identifier frame with the owner \a owner and + * the identification \a id. + */ + UniqueFileIdentifierFrame(const String &owner, const ByteVector &id); + + /*! + * Destroys the frame. + */ + ~UniqueFileIdentifierFrame(); + + /*! + * Returns the owner for the frame; essentially this is the key for + * determining which identification scheme this key belongs to. This + * will usually either be an email address or URL for the person or tool + * used to create the unique identifier. + * + * \see setOwner() + */ + String owner() const; + + /*! + * Returns the unique identifier. Though sometimes this is a text string + * it also may be binary data and as much should be assumed when handling + * it. + */ + ByteVector identifier() const; + + /*! + * Sets the owner of the identification scheme to \a s. + * + * \see owner() + */ + void setOwner(const String &s); + + /*! + * Sets the unique file identifier to \a v. + * + * \see identifier() + */ + void setIdentifier(const ByteVector &v); + + virtual String toString() const; + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + UniqueFileIdentifierFrame(const UniqueFileIdentifierFrame &); + UniqueFileIdentifierFrame &operator=(UniqueFileIdentifierFrame &); + + UniqueFileIdentifierFrame(const ByteVector &data, Header *h); + + class UniqueFileIdentifierFramePrivate; + UniqueFileIdentifierFramePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.cpp new file mode 100644 index 00000000..4def028b --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "unknownframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class UnknownFrame::UnknownFramePrivate +{ +public: + ByteVector fieldData; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +UnknownFrame::UnknownFrame(const ByteVector &data) : Frame(data) +{ + d = new UnknownFramePrivate; + setData(data); +} + +UnknownFrame::~UnknownFrame() +{ + delete d; +} + +String UnknownFrame::toString() const +{ + return String::null; +} + +ByteVector UnknownFrame::data() const +{ + return d->fieldData; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void UnknownFrame::parseFields(const ByteVector &data) +{ + d->fieldData = data; +} + +ByteVector UnknownFrame::renderFields() const +{ + return d->fieldData; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +UnknownFrame::UnknownFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new UnknownFramePrivate; + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.h new file mode 100644 index 00000000..6559f4ed --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unknownframe.h @@ -0,0 +1,79 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNKNOWNFRAME_H +#define TAGLIB_UNKNOWNFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! A frame type \e unknown to TagLib. + + /*! + * This class represents a frame type not known (or more often simply + * unimplemented) in TagLib. This is here provide a basic API for + * manipulating the binary data of unknown frames and to provide a means + * of rendering such \e unknown frames. + * + * Please note that a cleaner way of handling frame types that TagLib + * does not understand is to subclass ID3v2::Frame and ID3v2::FrameFactory + * to have your frame type supported through the standard ID3v2 mechanism. + */ + + class TAGLIB_EXPORT UnknownFrame : public Frame + { + friend class FrameFactory; + + public: + UnknownFrame(const ByteVector &data); + virtual ~UnknownFrame(); + + virtual String toString() const; + + /*! + * Returns the field data (everything but the header) for this frame. + */ + ByteVector data() const; + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + UnknownFrame(const ByteVector &data, Header *h); + UnknownFrame(const UnknownFrame &); + UnknownFrame &operator=(const UnknownFrame &); + + class UnknownFramePrivate; + UnknownFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp new file mode 100644 index 00000000..0a8927e7 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp @@ -0,0 +1,162 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "unsynchronizedlyricsframe.h" +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class UnsynchronizedLyricsFrame::UnsynchronizedLyricsFramePrivate +{ +public: + UnsynchronizedLyricsFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + ByteVector language; + String description; + String text; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(String::Type encoding) : + Frame("USLT") +{ + d = new UnsynchronizedLyricsFramePrivate; + d->textEncoding = encoding; +} + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data) : + Frame(data) +{ + d = new UnsynchronizedLyricsFramePrivate; + setData(data); +} + +UnsynchronizedLyricsFrame::~UnsynchronizedLyricsFrame() +{ + delete d; +} + +String UnsynchronizedLyricsFrame::toString() const +{ + return d->text; +} + +ByteVector UnsynchronizedLyricsFrame::language() const +{ + return d->language; +} + +String UnsynchronizedLyricsFrame::description() const +{ + return d->description; +} + +String UnsynchronizedLyricsFrame::text() const +{ + return d->text; +} + +void UnsynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) +{ + d->language = languageEncoding.mid(0, 3); +} + +void UnsynchronizedLyricsFrame::setDescription(const String &s) +{ + d->description = s; +} + +void UnsynchronizedLyricsFrame::setText(const String &s) +{ + d->text = s; +} + + +String::Type UnsynchronizedLyricsFrame::textEncoding() const +{ + return d->textEncoding; +} + +void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("An unsynchronized lyrics frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + d->language = data.mid(1, 3); + + int byteAlign + = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; + + ByteVectorList l = + ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + + if(l.size() == 2) { + d->description = String(l.front(), d->textEncoding); + d->text = String(l.back(), d->textEncoding); + } +} + +ByteVector UnsynchronizedLyricsFrame::renderFields() const +{ + ByteVector v; + + v.append(char(d->textEncoding)); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(d->textEncoding)); + v.append(textDelimiter(d->textEncoding)); + v.append(d->text.data(d->textEncoding)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data, Header *h) + : Frame(h) +{ + d = new UnsynchronizedLyricsFramePrivate(); + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h new file mode 100644 index 00000000..0f8260e4 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h @@ -0,0 +1,157 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H +#define TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 unsynchronized lyrics frame + /*! + * An implementation of ID3v2 unsynchronized lyrics. + */ + class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty unsynchronized lyrics frame that will use the text encoding + * \a encoding. + */ + explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a unsynchronized lyrics frame based on the data in \a data. + */ + explicit UnsynchronizedLyricsFrame(const ByteVector &data); + + /*! + * Destroys this UnsynchronizedLyricsFrame instance. + */ + virtual ~UnsynchronizedLyricsFrame(); + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the description of this unsynchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see setText() + */ + String text() const; + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Sets the description of the unsynchronized lyrics frame to \a s. + * + * \see decription() + */ + void setDescription(const String &s); + + /*! + * Sets the text portion of the unsynchronized lyrics frame to \a s. + * + * \see text() + */ + virtual void setText(const String &s); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + UnsynchronizedLyricsFrame(const ByteVector &data, Header *h); + UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &); + UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &); + + class UnsynchronizedLyricsFramePrivate; + UnsynchronizedLyricsFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.cpp new file mode 100644 index 00000000..7756c4ad --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.cpp @@ -0,0 +1,192 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "urllinkframe.h" +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class UrlLinkFrame::UrlLinkFramePrivate +{ +public: + String url; +}; + +class UserUrlLinkFrame::UserUrlLinkFramePrivate +{ +public: + UserUrlLinkFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + String description; +}; + +UrlLinkFrame::UrlLinkFrame(const ByteVector &data) : + Frame(data) +{ + d = new UrlLinkFramePrivate; + setData(data); +} + +UrlLinkFrame::~UrlLinkFrame() +{ + delete d; +} + +void UrlLinkFrame::setUrl(const String &s) +{ + d->url = s; +} + +String UrlLinkFrame::url() const +{ + return d->url; +} + +void UrlLinkFrame::setText(const String &s) +{ + setUrl(s); +} + +String UrlLinkFrame::toString() const +{ + return url(); +} + +void UrlLinkFrame::parseFields(const ByteVector &data) +{ + d->url = String(data); +} + +ByteVector UrlLinkFrame::renderFields() const +{ + return d->url.data(String::Latin1); +} + +UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) : Frame(h) +{ + d = new UrlLinkFramePrivate; + parseFields(fieldData(data)); +} + + +UserUrlLinkFrame::UserUrlLinkFrame(String::Type encoding) : + UrlLinkFrame("WXXX") +{ + d = new UserUrlLinkFramePrivate; + d->textEncoding = encoding; +} + +UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data) : + UrlLinkFrame(data) +{ + d = new UserUrlLinkFramePrivate; + setData(data); +} + +UserUrlLinkFrame::~UserUrlLinkFrame() +{ + delete d; +} + +String UserUrlLinkFrame::toString() const +{ + return "[" + description() + "] " + url(); +} + +String::Type UserUrlLinkFrame::textEncoding() const +{ + return d->textEncoding; +} + +void UserUrlLinkFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +String UserUrlLinkFrame::description() const +{ + return d->description; +} + +void UserUrlLinkFrame::setDescription(const String &s) +{ + d->description = s; +} + +void UserUrlLinkFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 2) { + debug("A user URL link frame must contain at least 2 bytes."); + return; + } + + int pos = 0; + + d->textEncoding = String::Type(data[0]); + pos += 1; + + if(d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8) { + int offset = data.find(textDelimiter(d->textEncoding), pos); + if(offset < pos) + return; + + d->description = String(data.mid(pos, offset - pos), d->textEncoding); + pos = offset + 1; + } + else { + int len = data.mid(pos).find(textDelimiter(d->textEncoding), 0, 2); + if(len < 0) + return; + + d->description = String(data.mid(pos, len), d->textEncoding); + pos += len + 2; + } + + setUrl(String(data.mid(pos))); +} + +ByteVector UserUrlLinkFrame::renderFields() const +{ + ByteVector v; + + String::Type encoding = checkEncoding(d->description, d->textEncoding); + + v.append(char(encoding)); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); + v.append(url().data(String::Latin1)); + + return v; +} + +UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) : UrlLinkFrame(data, h) +{ + d = new UserUrlLinkFramePrivate; + parseFields(fieldData(data)); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.h new file mode 100644 index 00000000..f89faad0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/frames/urllinkframe.h @@ -0,0 +1,172 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_URLLINKFRAME_H +#define TAGLIB_URLLINKFRAME_H + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 URL frame + /*! + * An implementation of ID3v2 URL link frames. + */ + class TAGLIB_EXPORT UrlLinkFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit UrlLinkFrame(const ByteVector &data); + + /*! + * Destroys this UrlLinkFrame instance. + */ + virtual ~UrlLinkFrame(); + + /*! + * Returns the URL. + */ + virtual String url() const; + + /*! + * Sets the URL to \a s. + */ + virtual void setUrl(const String &s); + + // Reimplementations. + + virtual void setText(const String &s); + virtual String toString() const; + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + UrlLinkFrame(const ByteVector &data, Header *h); + + private: + UrlLinkFrame(const UrlLinkFrame &); + UrlLinkFrame &operator=(const UrlLinkFrame &); + + class UrlLinkFramePrivate; + UrlLinkFramePrivate *d; + }; + + //! ID3v2 User defined URL frame + + /*! + * This is a specialization of URL link frames that allows for + * user defined entries. Each entry has a description in addition to the + * normal list of fields that a URL link frame has. + * + * This description identifies the frame and must be unique. + */ + class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame + { + friend class FrameFactory; + + public: + /*! + * Constructs an empty user defined URL link frame. For this to be + * a useful frame both a description and text must be set. + */ + explicit UserUrlLinkFrame(String::Type encoding = String::Latin1); + + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit UserUrlLinkFrame(const ByteVector &data); + + /*! + * Destroys this UserUrlLinkFrame instance. + */ + virtual ~UserUrlLinkFrame(); + + // Reimplementations. + + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns the description for this frame. + */ + String description() const; + + /*! + * Sets the description of the frame to \a s. \a s must be unique. + */ + void setDescription(const String &s); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + UserUrlLinkFrame(const ByteVector &data, Header *h); + + private: + UserUrlLinkFrame(const UserUrlLinkFrame &); + UserUrlLinkFrame &operator=(const UserUrlLinkFrame &); + + class UserUrlLinkFramePrivate; + UserUrlLinkFramePrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.2.0.txt b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.2.0.txt new file mode 100644 index 00000000..a69bddd3 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.2.0.txt @@ -0,0 +1,1660 @@ + +Informal standard M. Nilsson +Document: id3v2-00.txt 26th March 1998 + + + ID3 tag version 2 + +Status of this document + + This document is an Informal standard and is released so that + implementors could have a set standard before the formal standard is + set. The formal standard will use another version number if not + identical to what is described in this document. The contents in this + document may change for clarifications but never for added or altered + functionallity. + + Distribution of this document is unlimited. + + +Abstract + + The recent gain of popularity for MPEG layer III audio files on the + internet forced a standardised way of storing information about an + audio file within itself to determinate its origin and contents. + + Today the most accepted way to do this is with the so called ID3 tag, + which is simple but very limited and in some cases very unsuitable. + The ID3 tag has very limited space in every field, very limited + numbers of fields, not expandable or upgradeable and is placed at the + end of a the file, which is unsuitable for streaming audio. This draft + is an attempt to answer these issues with a new version of the ID3 + tag. + + +1. Table of contents + + 2. Conventions in this document + 3. ID3v2 overview + 3.1. ID3v2 header + 3.2. ID3v2 frames overview + 4. Declared ID3v2 frames + 4.1. Unique file identifier + 4.2. Text information frames + 4.2.1. Text information frames - details + 4.2.2. User defined text information frame + 4.3. URL link frames + 4.3.1. URL link frames - details + 4.3.2. User defined URL link frame + 4.4. Involved people list + 4.5. Music CD Identifier + 4.6. Event timing codes + 4.7. MPEG location lookup table + 4.8. Synced tempo codes + 4.9. Unsychronised lyrics/text transcription + 4.10. Synchronised lyrics/text + 4.11. Comments + 4.12. Relative volume adjustment + 4.13. Equalisation + 4.14. Reverb + 4.15. Attached picture + 4.16. General encapsulated object + 4.17. Play counter + 4.18. Popularimeter + 4.19. Recommended buffer size + 4.20. Encrypted meta frame + 4.21. Audio encryption + 4.22. Linked information + 5. The 'unsynchronisation scheme' + 6. Copyright + 7. References + 8. Appendix + A. Appendix A - ID3-Tag Specification V1.1 + A.1. Overview + A.2. ID3v1 Implementation + A.3. Genre List + A.4. Track addition - ID3v1.1 + 9. Author's Address + + +2. Conventions in this document + + In the examples, text within "" is a text string exactly as it appears + in a file. Numbers preceded with $ are hexadecimal and numbers + preceded with % are binary. $xx is used to indicate a byte with + unknown content. %x is used to indicate a bit with unknown content. + The most significant bit (MSB) of a byte is called 'bit 7' and the + least significant bit (LSB) is called 'bit 0'. + + A tag is the whole tag described in this document. A frame is a block + of information in the tag. The tag consists of a header, frames and + optional padding. A field is a piece of information; one value, a + string etc. A numeric string is a string that consists of the + characters 0-9 only. + + +3. ID3v2 overview + + The two biggest design goals were to be able to implement ID3v2 + without disturbing old software too much and that ID3v2 should be + expandable. + + The first criterion is met by the simple fact that the MPEG [MPEG] + decoding software uses a syncsignal, embedded in the audiostream, to + 'lock on to' the audio. Since the ID3v2 tag doesn't contain a valid + syncsignal, no software will attempt to play the tag. If, for any + reason, coincidence make a syncsignal appear within the tag it will be + taken care of by the 'unsynchronisation scheme' described in section + 5. + + The second criterion has made a more noticeable impact on the design + of the ID3v2 tag. It is constructed as a container for several + information blocks, called frames, whose format need not be known to + the software that encounters them. At the start of every frame there + is an identifier that explains the frames's format and content, and a + size descriptor that allows software to skip unknown frames. + + If a total revision of the ID3v2 tag should be needed, there is a + version number and a size descriptor in the ID3v2 header. + + The ID3 tag described in this document is mainly targeted to files + encoded with MPEG-2 layer I, MPEG-2 layer II, MPEG-2 layer III and + MPEG-2.5, but may work with other types of encoded audio. + + The bitorder in ID3v2 is most significant bit first (MSB). The + byteorder in multibyte numbers is most significant byte first (e.g. + $12345678 would be encoded $12 34 56 78). + + It is permitted to include padding after all the final frame (at the + end of the ID3 tag), making the size of all the frames together + smaller than the size given in the head of the tag. A possible purpose + of this padding is to allow for adding a few additional frames or + enlarge existing frames within the tag without having to rewrite the + entire file. The value of the padding bytes must be $00. + + +3.1. ID3v2 header + + The ID3v2 tag header, which should be the first information in the + file, is 10 bytes as follows: + + ID3/file identifier "ID3" + ID3 version $02 00 + ID3 flags %xx000000 + ID3 size 4 * %0xxxxxxx + + The first three bytes of the tag are always "ID3" to indicate that + this is an ID3 tag, directly followed by the two version bytes. The + first byte of ID3 version is it's major version, while the second byte + is its revision number. All revisions are backwards compatible while + major versions are not. If software with ID3v2 and below support + should encounter version three or higher it should simply ignore the + whole tag. Version and revision will never be $FF. + + The first bit (bit 7) in the 'ID3 flags' is indicating whether or not + unsynchronisation is used (see section 5 for details); a set bit + indicates usage. + + The second bit (bit 6) is indicating whether or not compression is + used; a set bit indicates usage. Since no compression scheme has been + decided yet, the ID3 decoder (for now) should just ignore the entire + tag if the compression bit is set. + + The ID3 tag size is encoded with four bytes where the first bit (bit + 7) is set to zero in every byte, making a total of 28 bits. The zeroed + bits are ignored, so a 257 bytes long tag is represented as $00 00 02 + 01. + + The ID3 tag size is the size of the complete tag after + unsychronisation, including padding, excluding the header (total tag + size - 10). The reason to use 28 bits (representing up to 256MB) for + size description is that we don't want to run out of space here. + + A ID3v2 tag can be detected with the following pattern: + $49 44 33 yy yy xx zz zz zz zz + Where yy is less than $FF, xx is the 'flags' byte and zz is less than + $80. + + +3.2. ID3v2 frames overview + + The headers of the frames are similar in their construction. They + consist of one three character identifier (capital A-Z and 0-9) and + one three byte size field, making a total of six bytes. The header is + excluded from the size. Identifiers beginning with "X", "Y" and "Z" + are for experimental use and free for everyone to use. Have in mind + that someone else might have used the same identifier as you. All + other identifiers are either used or reserved for future use. + + The three character frame identifier is followed by a three byte size + descriptor, making a total header size of six bytes in every frame. + The size is calculated as framesize excluding frame identifier and + size descriptor (frame size - 6). + + There is no fixed order of the frames' appearance in the tag, although + it is desired that the frames are arranged in order of significance + concerning the recognition of the file. An example of such order: + UFI, MCI, TT2 ... + + A tag must contain at least one frame. A frame must be at least 1 byte + big, excluding the 6-byte header. + + If nothing else is said a string is represented as ISO-8859-1 + [ISO-8859-1] characters in the range $20 - $FF. All unicode strings + [UNICODE] use 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2). All + numeric strings are always encoded as ISO-8859-1. Terminated strings + are terminated with $00 if encoded with ISO-8859-1 and $00 00 if + encoded as unicode. If nothing else is said newline character is + forbidden. In ISO-8859-1 a new line is represented, when allowed, with + $0A only. Frames that allow different types of text encoding have a + text encoding description byte directly after the frame size. If + ISO-8859-1 is used this byte should be $00, if unicode is used it + should be $01. + + The three byte language field is used to describe the language of the + frame's content, according to ISO-639-2 [ISO-639-2]. + + All URLs [URL] may be relative, e.g. "picture.png", "../doc.txt". + + If a frame is longer than it should be, e.g. having more fields than + specified in this document, that indicates that additions to the + frame have been made in a later version of the ID3 standard. This + is reflected by the revision number in the header of the tag. + + +4. Declared ID3v2 frames + + The following frames are declared in this draft. + + 4.19 BUF Recommended buffer size + + 4.17 CNT Play counter + 4.11 COM Comments + 4.21 CRA Audio encryption + 4.20 CRM Encrypted meta frame + + 4.6 ETC Event timing codes + 4.13 EQU Equalization + + 4.16 GEO General encapsulated object + + 4.4 IPL Involved people list + + 4.22 LNK Linked information + + 4.5 MCI Music CD Identifier + 4.7 MLL MPEG location lookup table + + 4.15 PIC Attached picture + 4.18 POP Popularimeter + + 4.14 REV Reverb + 4.12 RVA Relative volume adjustment + + 4.10 SLT Synchronized lyric/text + 4.8 STC Synced tempo codes + + 4.2.1 TAL Album/Movie/Show title + 4.2.1 TBP BPM (Beats Per Minute) + 4.2.1 TCM Composer + 4.2.1 TCO Content type + 4.2.1 TCR Copyright message + 4.2.1 TDA Date + 4.2.1 TDY Playlist delay + 4.2.1 TEN Encoded by + 4.2.1 TFT File type + 4.2.1 TIM Time + 4.2.1 TKE Initial key + 4.2.1 TLA Language(s) + 4.2.1 TLE Length + 4.2.1 TMT Media type + 4.2.1 TOA Original artist(s)/performer(s) + 4.2.1 TOF Original filename + 4.2.1 TOL Original Lyricist(s)/text writer(s) + 4.2.1 TOR Original release year + 4.2.1 TOT Original album/Movie/Show title + 4.2.1 TP1 Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group + 4.2.1 TP2 Band/Orchestra/Accompaniment + 4.2.1 TP3 Conductor/Performer refinement + 4.2.1 TP4 Interpreted, remixed, or otherwise modified by + 4.2.1 TPA Part of a set + 4.2.1 TPB Publisher + 4.2.1 TRC ISRC (International Standard Recording Code) + 4.2.1 TRD Recording dates + 4.2.1 TRK Track number/Position in set + 4.2.1 TSI Size + 4.2.1 TSS Software/hardware and settings used for encoding + 4.2.1 TT1 Content group description + 4.2.1 TT2 Title/Songname/Content description + 4.2.1 TT3 Subtitle/Description refinement + 4.2.1 TXT Lyricist/text writer + 4.2.2 TXX User defined text information frame + 4.2.1 TYE Year + + 4.1 UFI Unique file identifier + 4.9 ULT Unsychronized lyric/text transcription + + 4.3.1 WAF Official audio file webpage + 4.3.1 WAR Official artist/performer webpage + 4.3.1 WAS Official audio source webpage + 4.3.1 WCM Commercial information + 4.3.1 WCP Copyright/Legal information + 4.3.1 WPB Publishers official webpage + 4.3.2 WXX User defined URL link frame + + +4.1. Unique file identifier + + This frame's purpose is to be able to identify the audio file in a + database that may contain more information relevant to the content. + Since standardisation of such a database is beyond this document, all + frames begin with a null-terminated string with a URL [URL] containing + an email address, or a link to a location where an email address can + be found, that belongs to the organisation responsible for this + specific database implementation. Questions regarding the database + should be sent to the indicated email address. The URL should not be + used for the actual database queries. If a $00 is found directly after + the 'Frame size' the whole frame should be ignored, and preferably be + removed. The 'Owner identifier' is then followed by the actual + identifier, which may be up to 64 bytes. There may be more than one + "UFI" frame in a tag, but only one with the same 'Owner identifier'. + + Unique file identifier "UFI" + Frame size $xx xx xx + Owner identifier $00 + Identifier + + +4.2. Text information frames + + The text information frames are the most important frames, containing + information like artist, album and more. There may only be one text + information frame of its kind in an tag. If the textstring is followed + by a termination ($00 (00)) all the following information should be + ignored and not be displayed. All the text information frames have the + following format: + + Text information identifier "T00" - "TZZ" , excluding "TXX", + described in 4.2.2. + Frame size $xx xx xx + Text encoding $xx + Information + + +4.2.1. Text information frames - details + + TT1 + The 'Content group description' frame is used if the sound belongs to + a larger category of sounds/music. For example, classical music is + often sorted in different musical sections (e.g. "Piano Concerto", + "Weather - Hurricane"). + + TT2 + The 'Title/Songname/Content description' frame is the actual name of + the piece (e.g. "Adagio", "Hurricane Donna"). + + TT3 + The 'Subtitle/Description refinement' frame is used for information + directly related to the contents title (e.g. "Op. 16" or "Performed + live at wembley"). + + TP1 + The 'Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group' is + used for the main artist(s). They are seperated with the "/" + character. + + TP2 + The 'Band/Orchestra/Accompaniment' frame is used for additional + information about the performers in the recording. + + TP3 + The 'Conductor' frame is used for the name of the conductor. + + TP4 + The 'Interpreted, remixed, or otherwise modified by' frame contains + more information about the people behind a remix and similar + interpretations of another existing piece. + + TCM + The 'Composer(s)' frame is intended for the name of the composer(s). + They are seperated with the "/" character. + + TXT + The 'Lyricist(s)/text writer(s)' frame is intended for the writer(s) + of the text or lyrics in the recording. They are seperated with the + "/" character. + + TLA + The 'Language(s)' frame should contain the languages of the text or + lyrics in the audio file. The language is represented with three + characters according to ISO-639-2. If more than one language is used + in the text their language codes should follow according to their + usage. + + TCO + The content type, which previously (in ID3v1.1, see appendix A) was + stored as a one byte numeric value only, is now a numeric string. You + may use one or several of the types as ID3v1.1 did or, since the + category list would be impossible to maintain with accurate and up to + date categories, define your own. + References to the ID3v1 genres can be made by, as first byte, enter + "(" followed by a number from the genres list (section A.3.) and + ended with a ")" character. This is optionally followed by a + refinement, e.g. "(21)" or "(4)Eurodisco". Several references can be + made in the same frame, e.g. "(51)(39)". If the refinement should + begin with a "(" character it should be replaced with "((", e.g. "((I + can figure out any genre)" or "(55)((I think...)". The following new + content types is defined in ID3v2 and is implemented in the same way + as the numerig content types, e.g. "(RX)". + + RX Remix + CR Cover + + TAL + The 'Album/Movie/Show title' frame is intended for the title of the + recording(/source of sound) which the audio in the file is taken from. + + TPA + The 'Part of a set' frame is a numeric string that describes which + part of a set the audio came from. This frame is used if the source + described in the "TAL" frame is divided into several mediums, e.g. a + double CD. The value may be extended with a "/" character and a + numeric string containing the total number of parts in the set. E.g. + "1/2". + + TRK + The 'Track number/Position in set' frame is a numeric string + containing the order number of the audio-file on its original + recording. This may be extended with a "/" character and a numeric + string containing the total numer of tracks/elements on the original + recording. E.g. "4/9". + + TRC + The 'ISRC' frame should contian the International Standard Recording + Code [ISRC]. + + TYE + The 'Year' frame is a numeric string with a year of the recording. + This frames is always four characters long (until the year 10000). + + TDA + The 'Date' frame is a numeric string in the DDMM format containing + the date for the recording. This field is always four characters + long. + + TIM + The 'Time' frame is a numeric string in the HHMM format containing + the time for the recording. This field is always four characters + long. + + TRD + The 'Recording dates' frame is a intended to be used as complement to + the "TYE", "TDA" and "TIM" frames. E.g. "4th-7th June, 12th June" in + combination with the "TYE" frame. + + TMT + The 'Media type' frame describes from which media the sound + originated. This may be a textstring or a reference to the predefined + media types found in the list below. References are made within "(" + and ")" and are optionally followed by a text refinement, e.g. "(MC) + with four channels". If a text refinement should begin with a "(" + character it should be replaced with "((" in the same way as in the + "TCO" frame. Predefined refinements is appended after the media type, + e.g. "(CD/S)" or "(VID/PAL/VHS)". + + DIG Other digital media + /A Analog transfer from media + + ANA Other analog media + /WAC Wax cylinder + /8CA 8-track tape cassette + + CD CD + /A Analog transfer from media + /DD DDD + /AD ADD + /AA AAD + + LD Laserdisc + /A Analog transfer from media + + TT Turntable records + /33 33.33 rpm + /45 45 rpm + /71 71.29 rpm + /76 76.59 rpm + /78 78.26 rpm + /80 80 rpm + + MD MiniDisc + /A Analog transfer from media + + DAT DAT + /A Analog transfer from media + /1 standard, 48 kHz/16 bits, linear + /2 mode 2, 32 kHz/16 bits, linear + /3 mode 3, 32 kHz/12 bits, nonlinear, low speed + /4 mode 4, 32 kHz/12 bits, 4 channels + /5 mode 5, 44.1 kHz/16 bits, linear + /6 mode 6, 44.1 kHz/16 bits, 'wide track' play + + DCC DCC + /A Analog transfer from media + + DVD DVD + /A Analog transfer from media + + TV Television + /PAL PAL + /NTSC NTSC + /SECAM SECAM + + VID Video + /PAL PAL + /NTSC NTSC + /SECAM SECAM + /VHS VHS + /SVHS S-VHS + /BETA BETAMAX + + RAD Radio + /FM FM + /AM AM + /LW LW + /MW MW + + TEL Telephone + /I ISDN + + MC MC (normal cassette) + /4 4.75 cm/s (normal speed for a two sided cassette) + /9 9.5 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + REE Reel + /9 9.5 cm/s + /19 19 cm/s + /38 38 cm/s + /76 76 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + TFT + The 'File type' frame indicates which type of audio this tag defines. + The following type and refinements are defined: + + MPG MPEG Audio + /1 MPEG 2 layer I + /2 MPEG 2 layer II + /3 MPEG 2 layer III + /2.5 MPEG 2.5 + /AAC Advanced audio compression + + but other types may be used, not for these types though. This is used + in a similar way to the predefined types in the "TMT" frame, but + without parenthesis. If this frame is not present audio type is + assumed to be "MPG". + + TBP + BPM is short for beats per minute, and is easily computed by + dividing the number of beats in a musical piece with its length. To + get a more accurate result, do the BPM calculation on the main-part + only. To acquire best result measure the time between each beat and + calculate individual BPM for each beat and use the median value as + result. BPM is an integer and represented as a numerical string. + + TCR + The 'Copyright message' frame, which must begin with a year and a + space character (making five characters), is intended for the + copyright holder of the original sound, not the audio file itself. The + absence of this frame means only that the copyright information is + unavailable or has been removed, and must not be interpreted to mean + that the sound is public domain. Every time this field is displayed + the field must be preceded with "Copyright " (C) " ", where (C) is one + character showing a C in a circle. + + TPB + The 'Publisher' frame simply contains the name of the label or + publisher. + + TEN + The 'Encoded by' frame contains the name of the person or + organisation that encoded the audio file. This field may contain a + copyright message, if the audio file also is copyrighted by the + encoder. + + TSS + The 'Software/hardware and settings used for encoding' frame + includes the used audio encoder and its settings when the file was + encoded. Hardware refers to hardware encoders, not the computer on + which a program was run. + + TOF + The 'Original filename' frame contains the preferred filename for the + file, since some media doesn't allow the desired length of the + filename. The filename is case sensitive and includes its suffix. + + TLE + The 'Length' frame contains the length of the audiofile in + milliseconds, represented as a numeric string. + + TSI + The 'Size' frame contains the size of the audiofile in bytes + excluding the tag, represented as a numeric string. + + TDY + The 'Playlist delay' defines the numbers of milliseconds of silence + between every song in a playlist. The player should use the "ETC" + frame, if present, to skip initial silence and silence at the end of + the audio to match the 'Playlist delay' time. The time is represented + as a numeric string. + + TKE + The 'Initial key' frame contains the musical key in which the sound + starts. It is represented as a string with a maximum length of three + characters. The ground keys are represented with "A","B","C","D","E", + "F" and "G" and halfkeys represented with "b" and "#". Minor is + represented as "m". Example "Cbm". Off key is represented with an "o" + only. + + TOT + The 'Original album/Movie/Show title' frame is intended for the title + of the original recording(/source of sound), if for example the music + in the file should be a cover of a previously released song. + + TOA + The 'Original artist(s)/performer(s)' frame is intended for the + performer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The + performers are seperated with the "/" character. + + TOL + The 'Original Lyricist(s)/text writer(s)' frame is intended for the + text writer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The text + writers are seperated with the "/" character. + + TOR + The 'Original release year' frame is intended for the year when the + original recording, if for example the music in the file should be a + cover of a previously released song, was released. The field is + formatted as in the "TDY" frame. + + +4.2.2. User defined text information frame + + This frame is intended for one-string text information concerning the + audiofile in a similar way to the other "T"xx frames. The frame body + consists of a description of the string, represented as a terminated + string, followed by the actual string. There may be more than one + "TXX" frame in each tag, but only one with the same description. + + User defined... "TXX" + Frame size $xx xx xx + Text encoding $xx + Description $00 (00) + Value + + +4.3. URL link frames + + With these frames dynamic data such as webpages with touring + information, price information or plain ordinary news can be added to + the tag. There may only be one URL [URL] link frame of its kind in an + tag, except when stated otherwise in the frame description. If the + textstring is followed by a termination ($00 (00)) all the following + information should be ignored and not be displayed. All URL link + frames have the following format: + + URL link frame "W00" - "WZZ" , excluding "WXX" + (described in 4.3.2.) + Frame size $xx xx xx + URL + + +4.3.1. URL link frames - details + + WAF + The 'Official audio file webpage' frame is a URL pointing at a file + specific webpage. + + WAR + The 'Official artist/performer webpage' frame is a URL pointing at + the artists official webpage. There may be more than one "WAR" frame + in a tag if the audio contains more than one performer. + + WAS + The 'Official audio source webpage' frame is a URL pointing at the + official webpage for the source of the audio file, e.g. a movie. + + WCM + The 'Commercial information' frame is a URL pointing at a webpage + with information such as where the album can be bought. There may be + more than one "WCM" frame in a tag. + + WCP + The 'Copyright/Legal information' frame is a URL pointing at a + webpage where the terms of use and ownership of the file is described. + + WPB + The 'Publishers official webpage' frame is a URL pointing at the + official wepage for the publisher. + + +4.3.2. User defined URL link frame + + This frame is intended for URL [URL] links concerning the audiofile in + a similar way to the other "W"xx frames. The frame body consists of a + description of the string, represented as a terminated string, + followed by the actual URL. The URL is always encoded with ISO-8859-1 + [ISO-8859-1]. There may be more than one "WXX" frame in each tag, but + only one with the same description. + + User defined... "WXX" + Frame size $xx xx xx + Text encoding $xx + Description $00 (00) + URL + + +4.4. Involved people list + + Since there might be a lot of people contributing to an audio file in + various ways, such as musicians and technicians, the 'Text + information frames' are often insufficient to list everyone involved + in a project. The 'Involved people list' is a frame containing the + names of those involved, and how they were involved. The body simply + contains a terminated string with the involvement directly followed by + a terminated string with the involvee followed by a new involvement + and so on. There may only be one "IPL" frame in each tag. + + Involved people list "IPL" + Frame size $xx xx xx + Text encoding $xx + People list strings + + +4.5. Music CD Identifier + + This frame is intended for music that comes from a CD, so that the CD + can be identified in databases such as the CDDB [CDDB]. The frame + consists of a binary dump of the Table Of Contents, TOC, from the CD, + which is a header of 4 bytes and then 8 bytes/track on the CD making a + maximum of 804 bytes. This frame requires a present and valid "TRK" + frame. There may only be one "MCI" frame in each tag. + + Music CD identifier "MCI" + Frame size $xx xx xx + CD TOC + + +4.6. Event timing codes + + This frame allows synchronisation with key events in a song or sound. + The head is: + + Event timing codes "ETC" + Frame size $xx xx xx + Time stamp format $xx + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + Followed by a list of key events in the following format: + + Type of event $xx + Time stamp $xx (xx ...) + + The 'Time stamp' is set to zero if directly at the beginning of the + sound or after the previous event. All events should be sorted in + chronological order. The type of event is as follows: + + $00 padding (has no meaning) + $01 end of initial silence + $02 intro start + $03 mainpart start + $04 outro start + $05 outro end + $06 verse begins + $07 refrain begins + $08 interlude + $09 theme start + $0A variation + $0B key change + $0C time change + $0D unwanted noise (Snap, Crackle & Pop) + + $0E-$DF reserved for future use + + $E0-$EF not predefined sync 0-F + + $F0-$FC reserved for future use + + $FD audio end (start of silence) + $FE audio file ends + $FF one more byte of events follows (all the following bytes with + the value $FF have the same function) + + The 'Not predefined sync's ($E0-EF) are for user events. You might + want to synchronise your music to something, like setting of an + explosion on-stage, turning on your screensaver etc. + + There may only be one "ETC" frame in each tag. + + +4.7. MPEG location lookup table + + To increase performance and accuracy of jumps within a MPEG [MPEG] + audio file, frames with timecodes in different locations in the file + might be useful. The ID3 frame includes references that the software + can use to calculate positions in the file. After the frame header is + a descriptor of how much the 'frame counter' should increase for every + reference. If this value is two then the first reference points out + the second frame, the 2nd reference the 4th frame, the 3rd reference + the 6th frame etc. In a similar way the 'bytes between reference' and + 'milliseconds between reference' points out bytes and milliseconds + respectively. + + Each reference consists of two parts; a certain number of bits, as + defined in 'bits for bytes deviation', that describes the difference + between what is said in 'bytes between reference' and the reality and + a certain number of bits, as defined in 'bits for milliseconds + deviation', that describes the difference between what is said in + 'milliseconds between reference' and the reality. The number of bits + in every reference, i.e. 'bits for bytes deviation'+'bits for + milliseconds deviation', must be a multiple of four. There may only be + one "MLL" frame in each tag. + + Location lookup table "MLL" + ID3 frame size $xx xx xx + MPEG frames between reference $xx xx + Bytes between reference $xx xx xx + Milliseconds between reference $xx xx xx + Bits for bytes deviation $xx + Bits for milliseconds dev. $xx + + Then for every reference the following data is included; + + Deviation in bytes %xxx.... + Deviation in milliseconds %xxx.... + + +4.8. Synced tempo codes + + For a more accurate description of the tempo of a musical piece this + frame might be used. After the header follows one byte describing + which time stamp format should be used. Then follows one or more tempo + codes. Each tempo code consists of one tempo part and one time part. + The tempo is in BPM described with one or two bytes. If the first byte + has the value $FF, one more byte follows, which is added to the first + giving a range from 2 - 510 BPM, since $00 and $01 is reserved. $00 is + used to describe a beat-free time period, which is not the same as a + music-free time period. $01 is used to indicate one single beat-stroke + followed by a beat-free period. + + The tempo descriptor is followed by a time stamp. Every time the tempo + in the music changes, a tempo descriptor may indicate this for the + player. All tempo descriptors should be sorted in chronological order. + The first beat-stroke in a time-period is at the same time as the beat + description occurs. There may only be one "STC" frame in each tag. + + Synced tempo codes "STC" + Frame size $xx xx xx + Time stamp format $xx + Tempo data + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + +4.9. Unsychronised lyrics/text transcription + + This frame contains the lyrics of the song or a text transcription of + other vocal activities. The head includes an encoding descriptor and + a content descriptor. The body consists of the actual text. The + 'Content descriptor' is a terminated string. If no descriptor is + entered, 'Content descriptor' is $00 (00) only. Newline characters + are allowed in the text. Maximum length for the descriptor is 64 + bytes. There may be more than one lyrics/text frame in each tag, but + only one with the same language and content descriptor. + + Unsynced lyrics/text "ULT" + Frame size $xx xx xx + Text encoding $xx + Language $xx xx xx + Content descriptor $00 (00) + Lyrics/text + + +4.10. Synchronised lyrics/text + + This is another way of incorporating the words, said or sung lyrics, + in the audio file as text, this time, however, in sync with the audio. + It might also be used to describing events e.g. occurring on a stage + or on the screen in sync with the audio. The header includes a content + descriptor, represented with as terminated textstring. If no + descriptor is entered, 'Content descriptor' is $00 (00) only. + + Synced lyrics/text "SLT" + Frame size $xx xx xx + Text encoding $xx + Language $xx xx xx + Time stamp format $xx + Content type $xx + Content descriptor $00 (00) + + + Encoding: $00 ISO-8859-1 [ISO-8859-1] character set is used => $00 + is sync identifier. + $01 Unicode [UNICODE] character set is used => $00 00 is + sync identifier. + + Content type: $00 is other + $01 is lyrics + $02 is text transcription + $03 is movement/part name (e.g. "Adagio") + $04 is events (e.g. "Don Quijote enters the stage") + $05 is chord (e.g. "Bb F Fsus") + + Time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + The text that follows the frame header differs from that of the + unsynchronised lyrics/text transcription in one major way. Each + syllable (or whatever size of text is considered to be convenient by + the encoder) is a null terminated string followed by a time stamp + denoting where in the sound file it belongs. Each sync thus has the + following structure: + + Terminated text to be synced (typically a syllable) + Sync identifier (terminator to above string) $00 (00) + Time stamp $xx (xx ...) + + The 'time stamp' is set to zero or the whole sync is omitted if + located directly at the beginning of the sound. All time stamps should + be sorted in chronological order. The sync can be considered as a + validator of the subsequent string. + + Newline characters are allowed in all "SLT" frames and should be used + after every entry (name, event etc.) in a frame with the content type + $03 - $04. + + A few considerations regarding whitespace characters: Whitespace + separating words should mark the beginning of a new word, thus + occurring in front of the first syllable of a new word. This is also + valid for new line characters. A syllable followed by a comma should + not be broken apart with a sync (both the syllable and the comma + should be before the sync). + + An example: The "ULT" passage + + "Strangers in the night" $0A "Exchanging glances" + + would be "SLT" encoded as: + + "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx + " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx + xx "glan" $00 xx xx "ces" $00 xx xx + + There may be more than one "SLT" frame in each tag, but only one with + the same language and content descriptor. + + +4.11. Comments + + This frame replaces the old 30-character comment field in ID3v1. It + consists of a frame head followed by encoding, language and content + descriptors and is ended with the actual comment as a text string. + Newline characters are allowed in the comment text string. There may + be more than one comment frame in each tag, but only one with the same + language and content descriptor. + + Comment "COM" + Frame size $xx xx xx + Text encoding $xx + Language $xx xx xx + Short content description $00 (00) + The actual text + + +4.12. Relative volume adjustment + + This is a more subjective function than the previous ones. It allows + the user to say how much he wants to increase/decrease the volume on + each channel while the file is played. The purpose is to be able to + align all files to a reference volume, so that you don't have to + change the volume constantly. This frame may also be used to balance + adjust the audio. If the volume peak levels are known then this could + be described with the 'Peak volume right' and 'Peak volume left' + field. If Peakvolume is not known these fields could be left zeroed + or completely omitted. There may only be one "RVA" frame in each + tag. + + Relative volume adjustment "RVA" + Frame size $xx xx xx + Increment/decrement %000000xx + Bits used for volume descr. $xx + Relative volume change, right $xx xx (xx ...) + Relative volume change, left $xx xx (xx ...) + Peak volume right $xx xx (xx ...) + Peak volume left $xx xx (xx ...) + + In the increment/decrement field bit 0 is used to indicate the right + channel and bit 1 is used to indicate the left channel. 1 is + increment and 0 is decrement. + + The 'bits used for volume description' field is normally $10 (16 bits) + for MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value may not + be $00. The volume is always represented with whole bytes, padded in + the beginning (highest bits) when 'bits used for volume description' + is not a multiple of eight. + + +4.13. Equalisation + + This is another subjective, alignment frame. It allows the user to + predefine an equalisation curve within the audio file. There may only + be one "EQU" frame in each tag. + + Equalisation "EQU" + Frame size $xx xx xx + Adjustment bits $xx + + The 'adjustment bits' field defines the number of bits used for + representation of the adjustment. This is normally $10 (16 bits) for + MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value may not be + $00. + + This is followed by 2 bytes + ('adjustment bits' rounded up to the + nearest byte) for every equalisation band in the following format, + giving a frequency range of 0 - 32767Hz: + + Increment/decrement %x (MSB of the Frequency) + Frequency (lower 15 bits) + Adjustment $xx (xx ...) + + The increment/decrement bit is 1 for increment and 0 for decrement. + The equalisation bands should be ordered increasingly with reference + to frequency. All frequencies don't have to be declared. Adjustments + with the value $00 should be omitted. A frequency should only be + described once in the frame. + + +4.14. Reverb + + Yet another subjective one. You may here adjust echoes of different + kinds. Reverb left/right is the delay between every bounce in ms. + Reverb bounces left/right is the number of bounces that should be + made. $FF equals an infinite number of bounces. Feedback is the amount + of volume that should be returned to the next echo bounce. $00 is 0%, + $FF is 100%. If this value were $7F, there would be 50% volume + reduction on the first bounce, yet 50% on the second and so on. Left + to left means the sound from the left bounce to be played in the left + speaker, while left to right means sound from the left bounce to be + played in the right speaker. + + 'Premix left to right' is the amount of left sound to be mixed in the + right before any reverb is applied, where $00 id 0% and $FF is 100%. + 'Premix right to left' does the same thing, but right to left. Setting + both premix to $FF would result in a mono output (if the reverb is + applied symmetric). There may only be one "REV" frame in each tag. + + Reverb settings "REV" + Frame size $00 00 0C + Reverb left (ms) $xx xx + Reverb right (ms) $xx xx + Reverb bounces, left $xx + Reverb bounces, right $xx + Reverb feedback, left to left $xx + Reverb feedback, left to right $xx + Reverb feedback, right to right $xx + Reverb feedback, right to left $xx + Premix left to right $xx + Premix right to left $xx + + +4.15. Attached picture + + This frame contains a picture directly related to the audio file. + Image format is preferably "PNG" [PNG] or "JPG" [JFIF]. Description + is a short description of the picture, represented as a terminated + textstring. The description has a maximum length of 64 characters, + but may be empty. There may be several pictures attached to one file, + each in their individual "PIC" frame, but only one with the same + content descriptor. There may only be one picture with the picture + type declared as picture type $01 and $02 respectively. There is a + possibility to put only a link to the image file by using the 'image + format' "-->" and having a complete URL [URL] instead of picture data. + The use of linked files should however be used restrictively since + there is the risk of separation of files. + + Attached picture "PIC" + Frame size $xx xx xx + Text encoding $xx + Image format $xx xx xx + Picture type $xx + Description $00 (00) + Picture data + + + Picture type: $00 Other + $01 32x32 pixels 'file icon' (PNG only) + $02 Other file icon + $03 Cover (front) + $04 Cover (back) + $05 Leaflet page + $06 Media (e.g. lable side of CD) + $07 Lead artist/lead performer/soloist + $08 Artist/performer + $09 Conductor + $0A Band/Orchestra + $0B Composer + $0C Lyricist/text writer + $0D Recording Location + $0E During recording + $0F During performance + $10 Movie/video screen capture + $11 A bright coloured fish + $12 Illustration + $13 Band/artist logotype + $14 Publisher/Studio logotype + + +4.16. General encapsulated object + + In this frame any type of file can be encapsulated. After the header, + 'Frame size' and 'Encoding' follows 'MIME type' [MIME] and 'Filename' + for the encapsulated object, both represented as terminated strings + encoded with ISO 8859-1 [ISO-8859-1]. The filename is case sensitive. + Then follows a content description as terminated string, encoded as + 'Encoding'. The last thing in the frame is the actual object. The + first two strings may be omitted, leaving only their terminations. + MIME type is always an ISO-8859-1 text string. There may be more than + one "GEO" frame in each tag, but only one with the same content + descriptor. + + General encapsulated object "GEO" + Frame size $xx xx xx + Text encoding $xx + MIME type $00 + Filename $00 (00) + Content description $00 (00) + Encapsulated object + + +4.17. Play counter + + This is simply a counter of the number of times a file has been + played. The value is increased by one every time the file begins to + play. There may only be one "CNT" frame in each tag. When the counter + reaches all one's, one byte is inserted in front of the counter thus + making the counter eight bits bigger. The counter must be at least + 32-bits long to begin with. + + Play counter "CNT" + Frame size $xx xx xx + Counter $xx xx xx xx (xx ...) + + +4.18. Popularimeter + + The purpose of this frame is to specify how good an audio file is. + Many interesting applications could be found to this frame such as a + playlist that features better audiofiles more often than others or it + could be used to profile a persons taste and find other 'good' files + by comparing people's profiles. The frame is very simple. It contains + the email address to the user, one rating byte and a four byte play + counter, intended to be increased with one for every time the file is + played. The email is a terminated string. The rating is 1-255 where + 1 is worst and 255 is best. 0 is unknown. If no personal counter is + wanted it may be omitted. When the counter reaches all one's, one + byte is inserted in front of the counter thus making the counter + eight bits bigger in the same away as the play counter ("CNT"). + There may be more than one "POP" frame in each tag, but only one with + the same email address. + + Popularimeter "POP" + Frame size $xx xx xx + Email to user $00 + Rating $xx + Counter $xx xx xx xx (xx ...) + + +4.19. Recommended buffer size + + Sometimes the server from which a audio file is streamed is aware of + transmission or coding problems resulting in interruptions in the + audio stream. In these cases, the size of the buffer can be + recommended by the server using this frame. If the 'embedded info + flag' is true (1) then this indicates that an ID3 tag with the + maximum size described in 'Buffer size' may occur in the audiostream. + In such case the tag should reside between two MPEG [MPEG] frames, if + the audio is MPEG encoded. If the position of the next tag is known, + 'offset to next tag' may be used. The offset is calculated from the + end of tag in which this frame resides to the first byte of the header + in the next. This field may be omitted. Embedded tags is currently not + recommended since this could render unpredictable behaviour from + present software/hardware. The 'Buffer size' should be kept to a + minimum. There may only be one "BUF" frame in each tag. + + Recommended buffer size "BUF" + Frame size $xx xx xx + Buffer size $xx xx xx + Embedded info flag %0000000x + Offset to next tag $xx xx xx xx + + +4.20. Encrypted meta frame + + This frame contains one or more encrypted frames. This enables + protection of copyrighted information such as pictures and text, that + people might want to pay extra for. Since standardisation of such an + encryption scheme is beyond this document, all "CRM" frames begin with + a terminated string with a URL [URL] containing an email address, or a + link to a location where an email adress can be found, that belongs to + the organisation responsible for this specific encrypted meta frame. + + Questions regarding the encrypted frame should be sent to the + indicated email address. If a $00 is found directly after the 'Frame + size', the whole frame should be ignored, and preferably be removed. + The 'Owner identifier' is then followed by a short content description + and explanation as to why it's encrypted. After the + 'content/explanation' description, the actual encrypted block follows. + + When an ID3v2 decoder encounters a "CRM" frame, it should send the + datablock to the 'plugin' with the corresponding 'owner identifier' + and expect to receive either a datablock with one or several ID3v2 + frames after each other or an error. There may be more than one "CRM" + frames in a tag, but only one with the same 'owner identifier'. + + Encrypted meta frame "CRM" + Frame size $xx xx xx + Owner identifier $00 (00) + Content/explanation $00 (00) + Encrypted datablock + + +4.21. Audio encryption + + This frame indicates if the actual audio stream is encrypted, and by + whom. Since standardisation of such encrypion scheme is beyond this + document, all "CRA" frames begin with a terminated string with a + URL containing an email address, or a link to a location where an + email address can be found, that belongs to the organisation + responsible for this specific encrypted audio file. Questions + regarding the encrypted audio should be sent to the email address + specified. If a $00 is found directly after the 'Frame size' and the + audiofile indeed is encrypted, the whole file may be considered + useless. + + After the 'Owner identifier', a pointer to an unencrypted part of the + audio can be specified. The 'Preview start' and 'Preview length' is + described in frames. If no part is unencrypted, these fields should be + left zeroed. After the 'preview length' field follows optionally a + datablock required for decryption of the audio. There may be more than + one "CRA" frames in a tag, but only one with the same 'Owner + identifier'. + + Audio encryption "CRA" + Frame size $xx xx xx + Owner identifier $00 (00) + Preview start $xx xx + Preview length $xx xx + Encryption info + + +4.22. Linked information + + To keep space waste as low as possible this frame may be used to link + information from another ID3v2 tag that might reside in another audio + file or alone in a binary file. It is recommended that this method is + only used when the files are stored on a CD-ROM or other circumstances + when the risk of file seperation is low. The frame contains a frame + identifier, which is the frame that should be linked into this tag, a + URL [URL] field, where a reference to the file where the frame is + given, and additional ID data, if needed. Data should be retrieved + from the first tag found in the file to which this link points. There + may be more than one "LNK" frame in a tag, but only one with the same + contents. A linked frame is to be considered as part of the tag and + has the same restrictions as if it was a physical part of the tag + (i.e. only one "REV" frame allowed, whether it's linked or not). + + Linked information "LNK" + Frame size $xx xx xx + Frame identifier $xx xx xx + URL $00 (00) + Additional ID data + + Frames that may be linked and need no additional data are "IPL", + "MCI", "ETC", "LLT", "STC", "RVA", "EQU", "REV", "BUF", the text + information frames and the URL link frames. + + The "TXX", "PIC", "GEO", "CRM" and "CRA" frames may be linked with the + content descriptor as additional ID data. + + The "COM", "SLT" and "ULT" frames may be linked with three bytes of + language descriptor directly followed by a content descriptor as + additional ID data. + + +5. The 'unsynchronisation scheme' + + The only purpose of the 'unsychronisation scheme' is to make the ID3v2 + tag as compatible as possible with existing software. There is no use + in 'unsynchronising' tags if the file is only to be processed by new + software. Unsynchronisation may only be made with MPEG 2 layer I, II + and III and MPEG 2.5 files. + + Whenever a false synchronisation is found within the tag, one zeroed + byte is inserted after the first false synchronisation byte. The + format of a correct sync that should be altered by ID3 encoders is as + follows: + + %11111111 111xxxxx + + And should be replaced with: + + %11111111 00000000 111xxxxx + + This has the side effect that all $FF 00 combinations have to be + altered, so they won't be affected by the decoding process. Therefore + all the $FF 00 combinations have to be replaced with the $FF 00 00 + combination during the unsynchonisation. + + To indicate usage of the unsynchronisation, the first bit in 'ID3 + flags' should be set. This bit should only be set if the tag + contained a, now corrected, false synchronisation. The bit should + only be clear if the tag does not contain any false synchronisations. + + Do bear in mind, that if a compression scheme is used by the encoder, + the unsyncronisation scheme should be applied *afterwards*. When + decoding a compressed, 'unsyncronised' file, the 'unsyncronisation + scheme' should be parsed first, compression afterwards. + + +6. Copyright + + Copyright (C) Martin Nilsson 1998. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + "AS IS" basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +7. References + + [CDDB] Compact Disc Data Base + + + + [ISO-639-2] ISO/FDIS 639-2. + Codes for the representation of names of languages, Part 2: Alpha-3 + code. Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-8859-1] ISO/IEC DIS 8859-1. + 8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1. Technical committee / subcommittee: JTC 1 / SC 2 + + [ISRC] ISO 3901:1986 + International Standard Recording Code (ISRC). + Technical committee / subcommittee: TC 46 / SC 9 + + [JFIF] JPEG File Interchange Format, version 1.02 + + + + [MIME] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message Bodies", + RFC 2045, November 1996. + + + + [MPEG] ISO/IEC 11172-3:1993. + Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + Generic coding of moving pictures and associated audio information, + Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995) + + + [PNG] Portable Network Graphics, version 1.0 + + + + [UNICODE] ISO/IEC 10646-1:1993. + Universal Multiple-Octet Coded Character Set (UCS), Part 1: + Architecture and Basic Multilingual Plane. Technical committee + / subcommittee: JTC 1 / SC 2 + + + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, "Uniform Resource + Locators (URL).", RFC 1738, December 1994. + + + + +8. Appendix + + +A. Appendix A - ID3-Tag Specification V1.1 + + ID3-Tag Specification V1.1 (12 dec 1997) by Michael Mutschler + , edited for space and clarity + reasons. + + +A.1. Overview + + The ID3-Tag is an information field for MPEG Layer 3 audio files. + Since a standalone MP3 doesn't provide a method of storing other + information than those directly needed for replay reasons, the + ID3-tag was invented by Eric Kemp in 1996. + + A revision from ID3v1 to ID3v1.1 was made by Michael Mutschler to + support track number information is described in A.4. + + +A.2. ID3v1 Implementation + + The Information is stored in the last 128 bytes of an MP3. The Tag + has got the following fields, and the offsets given here, are from + 0-127. + + Field Length Offsets + Tag 3 0-2 + Songname 30 3-32 + Artist 30 33-62 + Album 30 63-92 + Year 4 93-96 + Comment 30 97-126 + Genre 1 127 + + + The string-fields contain ASCII-data, coded in ISO-Latin 1 codepage. + Strings which are smaller than the field length are padded with zero- + bytes. + + Tag: The tag is valid if this field contains the string "TAG". This + has to be uppercase! + + Songname: This field contains the title of the MP3 (string as + above). + + Artist: This field contains the artist of the MP3 (string as above). + + Album: this field contains the album where the MP3 comes from + (string as above). + + Year: this field contains the year when this song has originally + been released (string as above). + + Comment: this field contains a comment for the MP3 (string as + above). Revision to this field has been made in ID3v1.1. See + A.4. + + Genre: this byte contains the offset of a genre in a predefined + list the byte is treated as an unsigned byte. The offset is + starting from 0. See A.3. + + +A.3. Genre List + + The following genres is defined in ID3v1 + + 0.Blues + 1.Classic Rock + 2.Country + 3.Dance + 4.Disco + 5.Funk + 6.Grunge + 7.Hip-Hop + 8.Jazz + 9.Metal + 10.New Age + 11.Oldies + 12.Other + 13.Pop + 14.R&B + 15.Rap + 16.Reggae + 17.Rock + 18.Techno + 19.Industrial + 20.Alternative + 21.Ska + 22.Death Metal + 23.Pranks + 24.Soundtrack + 25.Euro-Techno + 26.Ambient + 27.Trip-Hop + 28.Vocal + 29.Jazz+Funk + 30.Fusion + 31.Trance + 32.Classical + 33.Instrumental + 34.Acid + 35.House + 36.Game + 37.Sound Clip + 38.Gospel + 39.Noise + 40.AlternRock + 41.Bass + 42.Soul + 43.Punk + 44.Space + 45.Meditative + 46.Instrumental Pop + 47.Instrumental Rock + 48.Ethnic + 49.Gothic + 50.Darkwave + 51.Techno-Industrial + 52.Electronic + 53.Pop-Folk + 54.Eurodance + 55.Dream + 56.Southern Rock + 57.Comedy + 58.Cult + 59.Gangsta + 60.Top 40 + 61.Christian Rap + 62.Pop/Funk + 63.Jungle + 64.Native American + 65.Cabaret + 66.New Wave + 67.Psychadelic + 68.Rave + 69.Showtunes + 70.Trailer + 71.Lo-Fi + 72.Tribal + 73.Acid Punk + 74.Acid Jazz + 75.Polka + 76.Retro + 77.Musical + 78.Rock & Roll + 79.Hard Rock + + The following genres are Winamp extensions + + 80.Folk + 81.Folk-Rock + 82.National Folk + 83.Swing + 84.Fast Fusion + 85.Bebob + 86.Latin + 87.Revival + 88.Celtic + 89.Bluegrass + 90.Avantgarde + 91.Gothic Rock + 92.Progressive Rock + 93.Psychedelic Rock + 94.Symphonic Rock + 95.Slow Rock + 96.Big Band + 97.Chorus + 98.Easy Listening + 99.Acoustic + 100.Humour + 101.Speech + 102.Chanson + 103.Opera + 104.Chamber Music + 105.Sonata + 106.Symphony + 107.Booty Bass + 108.Primus + 109.Porn Groove + 110.Satire + 111.Slow Jam + 112.Club + 113.Tango + 114.Samba + 115.Folklore + 116.Ballad + 117.Power Ballad + 118.Rhythmic Soul + 119.Freestyle + 120.Duet + 121.Punk Rock + 122.Drum Solo + 123.A capella + 124.Euro-House + 125.Dance Hall + + +A.4. Track addition - ID3v1.1 + + In ID3v1.1, Michael Mutschler revised the specification of the + comment field in order to implement the track number. The new format + of the comment field is a 28 character string followed by a mandatory + null ($00) character and the original album tracknumber stored as an + unsigned byte-size integer. In such cases where the 29th byte is not + the null character or when the 30th is a null character, the + tracknumber is to be considered undefined. + + +9. Author's Address + + Martin Nilsson + Rydsvägen 246 C. 30 + S-584 34 Linköping + Sweden + + Email: nilsson@id3.org + + Co-authors: + + Johan Sundström Email: johan@id3.org + + diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.3.0.txt b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.3.0.txt new file mode 100644 index 00000000..b4ed763e --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.3.0.txt @@ -0,0 +1,2022 @@ +Informal standard M. Nilsson +Document: id3v2.3.0.txt 3rd February 1999 + + + ID3 tag version 2.3.0 + +Status of this document + + This document is an informal standard and replaces the ID3v2.2.0 + standard [ID3v2]. The informal standard is released so that + implementors could have a set standard before a formal standard is + set. The formal standard will use another version or revision number + if not identical to what is described in this document. The contents + in this document may change for clarifications but never for added or + altered functionallity. + + Distribution of this document is unlimited. + + +Abstract + + This document describes the ID3v2.3.0, which is a more developed + version of the ID3v2 informal standard [ID3v2] (version 2.2.0), + evolved from the ID3 tagging system. The ID3v2 offers a flexible way + of storing information about an audio file within itself to determine + its origin and contents. The information may be technical + information, such as equalisation curves, as well as related meta + information, such as title, performer, copyright etc. + + +1. Table of contents + + 2. Conventions in this document + 3. ID3v2 overview + 3.1. ID3v2 header + 3.2. ID3v2 extended header + 3.3. ID3v2 frames overview + 3.3.1. Frame header flags + 3.3.2. Default flags + 4. Declared ID3v2 frames + 4.1. Unique file identifier + 4.2. Text information frames + 4.2.1. Text information frames - details + 4.2.2. User defined text information frame + 4.3. URL link frames + 4.3.1. URL link frames - details + 4.3.2. User defined URL link frame + 4.4. Involved people list + 4.5. Music CD Identifier + 4.6. Event timing codes + 4.7. MPEG location lookup table + 4.8. Synced tempo codes + 4.9. Unsychronised lyrics/text transcription + 4.10. Synchronised lyrics/text + 4.11. Comments + 4.12. Relative volume adjustment + 4.13. Equalisation + 4.14. Reverb + 4.15. Attached picture + 4.16. General encapsulated object + 4.17. Play counter + 4.18. Popularimeter + 4.19. Recommended buffer size + 4.20. Audio encryption + 4.21. Linked information + 4.22. Position synchronisation frame + 4.23. Terms of use + 4.24. Ownership frame + 4.25. Commercial frame + 4.26. Encryption method registration + 4.27. Group identification registration + 4.28. Private frame + 5. The 'unsynchronisation scheme' + 6. Copyright + 7. References + 8. Appendix + A. Appendix A - Genre List from ID3v1 + 9. Author's Address + + +2. Conventions in this document + + In the examples, text within "" is a text string exactly as it + appears in a file. Numbers preceded with $ are hexadecimal and + numbers preceded with % are binary. $xx is used to indicate a byte + with unknown content. %x is used to indicate a bit with unknown + content. The most significant bit (MSB) of a byte is called 'bit 7' + and the least significant bit (LSB) is called 'bit 0'. + + A tag is the whole tag described in this document. A frame is a block + of information in the tag. The tag consists of a header, frames and + optional padding. A field is a piece of information; one value, a + string etc. A numeric string is a string that consists of the + characters 0-9 only. + + +3. ID3v2 overview + + The two biggest design goals were to be able to implement ID3v2 + without disturbing old software too much and that ID3v2 should be + as flexible and expandable as possible. + + The first criterion is met by the simple fact that the MPEG [MPEG] + decoding software uses a syncsignal, embedded in the audiostream, to + 'lock on to' the audio. Since the ID3v2 tag doesn't contain a valid + syncsignal, no software will attempt to play the tag. If, for any + reason, coincidence make a syncsignal appear within the tag it will + be taken care of by the 'unsynchronisation scheme' described in + section 5. + + The second criterion has made a more noticeable impact on the design + of the ID3v2 tag. It is constructed as a container for several + information blocks, called frames, whose format need not be known to + the software that encounters them. At the start of every frame there + is an identifier that explains the frames' format and content, and a + size descriptor that allows software to skip unknown frames. + + If a total revision of the ID3v2 tag should be needed, there is a + version number and a size descriptor in the ID3v2 header. + + The ID3 tag described in this document is mainly targeted at files + encoded with MPEG-1/2 layer I, MPEG-1/2 layer II, MPEG-1/2 layer III + and MPEG-2.5, but may work with other types of encoded audio. + + The bitorder in ID3v2 is most significant bit first (MSB). The + byteorder in multibyte numbers is most significant byte first (e.g. + $12345678 would be encoded $12 34 56 78). + + It is permitted to include padding after all the final frame (at the + end of the ID3 tag), making the size of all the frames together + smaller than the size given in the head of the tag. A possible + purpose of this padding is to allow for adding a few additional + frames or enlarge existing frames within the tag without having to + rewrite the entire file. The value of the padding bytes must be $00. + + +3.1. ID3v2 header + + The ID3v2 tag header, which should be the first information in the + file, is 10 bytes as follows: + + ID3v2/file identifier "ID3" + ID3v2 version $03 00 + ID3v2 flags %abc00000 + ID3v2 size 4 * %0xxxxxxx + + The first three bytes of the tag are always "ID3" to indicate that + this is an ID3v2 tag, directly followed by the two version bytes. The + first byte of ID3v2 version is it's major version, while the second + byte is its revision number. In this case this is ID3v2.3.0. All + revisions are backwards compatible while major versions are not. If + software with ID3v2.2.0 and below support should encounter version + three or higher it should simply ignore the whole tag. Version and + revision will never be $FF. + + The version is followed by one the ID3v2 flags field, of which + currently only three flags are used. + + + a - Unsynchronisation + + Bit 7 in the 'ID3v2 flags' indicates whether or not + unsynchronisation is used (see section 5 for details); a set bit + indicates usage. + + + b - Extended header + + The second bit (bit 6) indicates whether or not the header is + followed by an extended header. The extended header is described in + section 3.2. + + + c - Experimental indicator + + The third bit (bit 5) should be used as an 'experimental + indicator'. This flag should always be set when the tag is in an + experimental stage. + + All the other flags should be cleared. If one of these undefined + flags are set that might mean that the tag is not readable for a + parser that does not know the flags function. + + The ID3v2 tag size is encoded with four bytes where the most + significant bit (bit 7) is set to zero in every byte, making a total + of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is + represented as $00 00 02 01. + + The ID3v2 tag size is the size of the complete tag after + unsychronisation, including padding, excluding the header but not + excluding the extended header (total tag size - 10). Only 28 bits + (representing up to 256MB) are used in the size description to avoid + the introducuction of 'false syncsignals'. + + An ID3v2 tag can be detected with the following pattern: + $49 44 33 yy yy xx zz zz zz zz + Where yy is less than $FF, xx is the 'flags' byte and zz is less than + $80. + + +3.2. ID3v2 extended header + + The extended header contains information that is not vital to the + correct parsing of the tag information, hence the extended header is + optional. + + Extended header size $xx xx xx xx + Extended Flags $xx xx + Size of padding $xx xx xx xx + + Where the 'Extended header size', currently 6 or 10 bytes, excludes + itself. The 'Size of padding' is simply the total tag size excluding + the frames and the headers, in other words the padding. The extended + header is considered separate from the header proper, and as such is + subject to unsynchronisation. + + The extended flags are a secondary flag set which describes further + attributes of the tag. These attributes are currently defined as + follows + + %x0000000 00000000 + + + x - CRC data present + + If this flag is set four bytes of CRC-32 data is appended to the + extended header. The CRC should be calculated before + unsynchronisation on the data between the extended header and the + padding, i.e. the frames and only the frames. + + Total frame CRC $xx xx xx xx + + +3.3. ID3v2 frame overview + + As the tag consists of a tag header and a tag body with one or more + frames, all the frames consists of a frame header followed by one or + more fields containing the actual information. The layout of the + frame header: + + Frame ID $xx xx xx xx (four characters) + Size $xx xx xx xx + Flags $xx xx + + The frame ID made out of the characters capital A-Z and 0-9. + Identifiers beginning with "X", "Y" and "Z" are for experimental use + and free for everyone to use, without the need to set the + experimental bit in the tag header. Have in mind that someone else + might have used the same identifier as you. All other identifiers are + either used or reserved for future use. + + The frame ID is followed by a size descriptor, making a total header + size of ten bytes in every frame. The size is calculated as frame + size excluding frame header (frame size - 10). + + In the frame header the size descriptor is followed by two flags + bytes. These flags are described in section 3.3.1. + + There is no fixed order of the frames' appearance in the tag, + although it is desired that the frames are arranged in order of + significance concerning the recognition of the file. An example of + such order: UFID, TIT2, MCDI, TRCK ... + + A tag must contain at least one frame. A frame must be at least 1 + byte big, excluding the header. + + If nothing else is said a string is represented as ISO-8859-1 + [ISO-8859-1] characters in the range $20 - $FF. Such strings are + represented as , or if newlines are + allowed, in the frame descriptions. All Unicode strings [UNICODE] use + 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2). Unicode strings + must begin with the Unicode BOM ($FF FE or $FE FF) to identify the + byte order. + + All numeric strings and URLs [URL] are always encoded as ISO-8859-1. + Terminated strings are terminated with $00 if encoded with ISO-8859-1 + and $00 00 if encoded as unicode. If nothing else is said newline + character is forbidden. In ISO-8859-1 a new line is represented, when + allowed, with $0A only. Frames that allow different types of text + encoding have a text encoding description byte directly after the + frame size. If ISO-8859-1 is used this byte should be $00, if Unicode + is used it should be $01. Strings dependent on encoding is + represented as , or if newlines are allowed. Any empty + Unicode strings which are NULL-terminated may have the Unicode BOM + followed by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00). + + The three byte language field is used to describe the language of the + frame's content, according to ISO-639-2 [ISO-639-2]. + + All URLs [URL] may be relative, e.g. "picture.png", "../doc.txt". + + If a frame is longer than it should be, e.g. having more fields than + specified in this document, that indicates that additions to the + frame have been made in a later version of the ID3v2 standard. This + is reflected by the revision number in the header of the tag. + + +3.3.1. Frame header flags + + In the frame header the size descriptor is followed by two flags + bytes. All unused flags must be cleared. The first byte is for + 'status messages' and the second byte is for encoding purposes. If an + unknown flag is set in the first byte the frame may not be changed + without the bit cleared. If an unknown flag is set in the second byte + it is likely to not be readable. The flags field is defined as + follows. + + %abc00000 %ijk00000 + + + a - Tag alter preservation + + This flag tells the software what to do with this frame if it is + unknown and the tag is altered in any way. This applies to all + kinds of alterations, including adding more padding and reordering + the frames. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + b - File alter preservation + + This flag tells the software what to do with this frame if it is + unknown and the file, excluding the tag, is altered. This does not + apply when the audio is completely replaced with other audio data. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + c - Read only + + This flag, if set, tells the software that the contents of this + frame is intended to be read only. Changing the contents might + break something, e.g. a signature. If the contents are changed, + without knowledge in why the frame was flagged read only and + without taking the proper means to compensate, e.g. recalculating + the signature, the bit should be cleared. + + + i - Compression + + This flag indicates whether or not the frame is compressed. + + 0 Frame is not compressed. + 1 Frame is compressed using zlib [zlib] with 4 bytes for + 'decompressed size' appended to the frame header. + + + j - Encryption + + This flag indicates wether or not the frame is enrypted. If set + one byte indicating with which method it was encrypted will be + appended to the frame header. See section 4.26. for more + information about encryption method registration. + + 0 Frame is not encrypted. + 1 Frame is encrypted. + + + k - Grouping identity + + This flag indicates whether or not this frame belongs in a group + with other frames. If set a group identifier byte is added to the + frame header. Every frame with the same group identifier belongs + to the same group. + + 0 Frame does not contain group information + 1 Frame contains group information + + + Some flags indicates that the frame header is extended with + additional information. This information will be added to the frame + header in the same order as the flags indicating the additions. I.e. + the four bytes of decompressed size will preceed the encryption + method byte. These additions to the frame header, while not included + in the frame header size but are included in the 'frame size' field, + are not subject to encryption or compression. + + +3.3.2. Default flags + + The default settings for the frames described in this document can be + divided into the following classes. The flags may be set differently + if found more suitable by the software. + + 1. Discarded if tag is altered, discarded if file is altered. + + None. + + 2. Discarded if tag is altered, preserved if file is altered. + + None. + + 3. Preserved if tag is altered, discarded if file is altered. + + AENC, ETCO, EQUA, MLLT, POSS, SYLT, SYTC, RVAD, TENC, TLEN, TSIZ + + 4. Preserved if tag is altered, preserved if file is altered. + + The rest of the frames. + + +4. Declared ID3v2 frames + + The following frames are declared in this draft. + + 4.21 AENC Audio encryption + 4.15 APIC Attached picture + + 4.11 COMM Comments + 4.25 COMR Commercial frame + + 4.26 ENCR Encryption method registration + 4.13 EQUA Equalization + 4.6 ETCO Event timing codes + + 4.16 GEOB General encapsulated object + 4.27 GRID Group identification registration + + 4.4 IPLS Involved people list + + 4.21 LINK Linked information + + 4.5 MCDI Music CD identifier + 4.7 MLLT MPEG location lookup table + + 4.24 OWNE Ownership frame + + 4.28. PRIV Private frame + 4.17 PCNT Play counter + 4.18 POPM Popularimeter + 4.22 POSS Position synchronisation frame + + 4.19 RBUF Recommended buffer size + 4.12 RVAD Relative volume adjustment + 4.14 RVRB Reverb + + 4.10 SYLT Synchronized lyric/text + 4.8 SYTC Synchronized tempo codes + + 4.2.1 TALB Album/Movie/Show title + 4.2.1 TBPM BPM (beats per minute) + 4.2.1 TCOM Composer + 4.2.1 TCON Content type + 4.2.1 TCOP Copyright message + 4.2.1 TDAT Date + 4.2.1 TDLY Playlist delay + 4.2.1 TENC Encoded by + 4.2.1 TEXT Lyricist/Text writer + 4.2.1 TFLT File type + 4.2.1 TIME Time + 4.2.1 TIT1 Content group description + 4.2.1 TIT2 Title/songname/content description + 4.2.1 TIT3 Subtitle/Description refinement + 4.2.1 TKEY Initial key + 4.2.1 TLAN Language(s) + 4.2.1 TLEN Length + 4.2.1 TMED Media type + 4.2.1 TOAL Original album/movie/show title + 4.2.1 TOFN Original filename + 4.2.1 TOLY Original lyricist(s)/text writer(s) + 4.2.1 TOPE Original artist(s)/performer(s) + 4.2.1 TORY Original release year + 4.2.1 TOWN File owner/licensee + 4.2.1 TPE1 Lead performer(s)/Soloist(s) + 4.2.1 TPE2 Band/orchestra/accompaniment + 4.2.1 TPE3 Conductor/performer refinement + 4.2.1 TPE4 Interpreted, remixed, or otherwise modified by + 4.2.1 TPOS Part of a set + 4.2.1 TPUB Publisher + 4.2.1 TRCK Track number/Position in set + 4.2.1 TRDA Recording dates + 4.2.1 TRSN Internet radio station name + 4.2.1 TRSO Internet radio station owner + 4.2.1 TSIZ Size + 4.2.1 TSRC ISRC (international standard recording code) + 4.2.1 TSSE Software/Hardware and settings used for encoding + 4.2.1 TYER Year + 4.2.2 TXXX User defined text information frame + + 4.1 UFID Unique file identifier + 4.23 USER Terms of use + 4.9 USLT Unsychronized lyric/text transcription + + 4.3.1 WCOM Commercial information + 4.3.1 WCOP Copyright/Legal information + 4.3.1 WOAF Official audio file webpage + 4.3.1 WOAR Official artist/performer webpage + 4.3.1 WOAS Official audio source webpage + 4.3.1 WORS Official internet radio station homepage + 4.3.1 WPAY Payment + 4.3.1 WPUB Publishers official webpage + 4.3.2 WXXX User defined URL link frame + + +4.1. Unique file identifier + + This frame's purpose is to be able to identify the audio file in a + database that may contain more information relevant to the content. + Since standardisation of such a database is beyond this document, all + frames begin with a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for this specific database implementation. Questions regarding the + database should be sent to the indicated email address. The URL + should not be used for the actual database queries. The string + "http://www.id3.org/dummy/ufid.html" should be used for tests. + Software that isn't told otherwise may safely remove such frames. The + 'Owner identifier' must be non-empty (more than just a termination). + The 'Owner identifier' is then followed by the actual identifier, + which may be up to 64 bytes. There may be more than one "UFID" frame + in a tag, but only one with the same 'Owner identifier'. + +
+ Owner identifier $00 + Identifier + + +4.2. Text information frames + + The text information frames are the most important frames, containing + information like artist, album and more. There may only be one text + information frame of its kind in an tag. If the textstring is + followed by a termination ($00 (00)) all the following information + should be ignored and not be displayed. All text frame identifiers + begin with "T". Only text frame identifiers begin with "T", with the + exception of the "TXXX" frame. All the text information frames have + the following format: + +
+ Text encoding $xx + Information + + +4.2.1. Text information frames - details + + TALB + The 'Album/Movie/Show title' frame is intended for the title of the + recording(/source of sound) which the audio in the file is taken + from. + + TBPM + The 'BPM' frame contains the number of beats per minute in the + mainpart of the audio. The BPM is an integer and represented as a + numerical string. + + TCOM + The 'Composer(s)' frame is intended for the name of the composer(s). + They are seperated with the "/" character. + + TCON + The 'Content type', which previously was stored as a one byte numeric + value only, is now a numeric string. You may use one or several of + the types as ID3v1.1 did or, since the category list would be + impossible to maintain with accurate and up to date categories, + define your own. + + References to the ID3v1 genres can be made by, as first byte, enter + "(" followed by a number from the genres list (appendix A.) and + ended with a ")" character. This is optionally followed by a + refinement, e.g. "(21)" or "(4)Eurodisco". Several references can be + made in the same frame, e.g. "(51)(39)". If the refinement should + begin with a "(" character it should be replaced with "((", e.g. "((I + can figure out any genre)" or "(55)((I think...)". The following new + content types is defined in ID3v2 and is implemented in the same way + as the numerig content types, e.g. "(RX)". + + RX Remix + CR Cover + + TCOP + The 'Copyright message' frame, which must begin with a year and a + space character (making five characters), is intended for the + copyright holder of the original sound, not the audio file itself. + The absence of this frame means only that the copyright information + is unavailable or has been removed, and must not be interpreted to + mean that the sound is public domain. Every time this field is + displayed the field must be preceded with "Copyright " (C) " ", where + (C) is one character showing a C in a circle. + + TDAT + The 'Date' frame is a numeric string in the DDMM format containing + the date for the recording. This field is always four characters + long. + + TDLY + The 'Playlist delay' defines the numbers of milliseconds of silence + between every song in a playlist. The player should use the "ETC" + frame, if present, to skip initial silence and silence at the end of + the audio to match the 'Playlist delay' time. The time is represented + as a numeric string. + + TENC + The 'Encoded by' frame contains the name of the person or + organisation that encoded the audio file. This field may contain a + copyright message, if the audio file also is copyrighted by the + encoder. + + TEXT + The 'Lyricist(s)/Text writer(s)' frame is intended for the writer(s) + of the text or lyrics in the recording. They are seperated with the + "/" character. + + TFLT + The 'File type' frame indicates which type of audio this tag defines. + The following type and refinements are defined: + + MPG MPEG Audio + /1 MPEG 1/2 layer I + /2 MPEG 1/2 layer II + /3 MPEG 1/2 layer III + /2.5 MPEG 2.5 + /AAC Advanced audio compression + VQF Transform-domain Weighted Interleave Vector Quantization + PCM Pulse Code Modulated audio + + but other types may be used, not for these types though. This is used + in a similar way to the predefined types in the "TMED" frame, but + without parentheses. If this frame is not present audio type is + assumed to be "MPG". + + TIME + The 'Time' frame is a numeric string in the HHMM format containing + the time for the recording. This field is always four characters + long. + + TIT1 + The 'Content group description' frame is used if the sound belongs to + a larger category of sounds/music. For example, classical music is + often sorted in different musical sections (e.g. "Piano Concerto", + "Weather - Hurricane"). + + TIT2 + The 'Title/Songname/Content description' frame is the actual name of + the piece (e.g. "Adagio", "Hurricane Donna"). + + TIT3 + The 'Subtitle/Description refinement' frame is used for information + directly related to the contents title (e.g. "Op. 16" or "Performed + live at Wembley"). + + TKEY + The 'Initial key' frame contains the musical key in which the sound + starts. It is represented as a string with a maximum length of three + characters. The ground keys are represented with "A","B","C","D","E", + "F" and "G" and halfkeys represented with "b" and "#". Minor is + represented as "m". Example "Cbm". Off key is represented with an "o" + only. + + TLAN + The 'Language(s)' frame should contain the languages of the text or + lyrics spoken or sung in the audio. The language is represented with + three characters according to ISO-639-2. If more than one language is + used in the text their language codes should follow according to + their usage. + + TLEN + The 'Length' frame contains the length of the audiofile in + milliseconds, represented as a numeric string. + + TMED + The 'Media type' frame describes from which media the sound + originated. This may be a text string or a reference to the + predefined media types found in the list below. References are made + within "(" and ")" and are optionally followed by a text refinement, + e.g. "(MC) with four channels". If a text refinement should begin + with a "(" character it should be replaced with "((" in the same way + as in the "TCO" frame. Predefined refinements is appended after the + media type, e.g. "(CD/A)" or "(VID/PAL/VHS)". + + DIG Other digital media + /A Analog transfer from media + + ANA Other analog media + /WAC Wax cylinder + /8CA 8-track tape cassette + + CD CD + /A Analog transfer from media + /DD DDD + /AD ADD + /AA AAD + + LD Laserdisc + /A Analog transfer from media + + TT Turntable records + /33 33.33 rpm + /45 45 rpm + /71 71.29 rpm + /76 76.59 rpm + /78 78.26 rpm + /80 80 rpm + + MD MiniDisc + /A Analog transfer from media + + DAT DAT + /A Analog transfer from media + /1 standard, 48 kHz/16 bits, linear + /2 mode 2, 32 kHz/16 bits, linear + /3 mode 3, 32 kHz/12 bits, nonlinear, low speed + /4 mode 4, 32 kHz/12 bits, 4 channels + /5 mode 5, 44.1 kHz/16 bits, linear + /6 mode 6, 44.1 kHz/16 bits, 'wide track' play + + DCC DCC + /A Analog transfer from media + + DVD DVD + /A Analog transfer from media + + TV Television + /PAL PAL + /NTSC NTSC + /SECAM SECAM + + VID Video + /PAL PAL + /NTSC NTSC + /SECAM SECAM + /VHS VHS + /SVHS S-VHS + /BETA BETAMAX + + RAD Radio + /FM FM + /AM AM + /LW LW + /MW MW + + TEL Telephone + /I ISDN + + MC MC (normal cassette) + /4 4.75 cm/s (normal speed for a two sided cassette) + /9 9.5 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + REE Reel + /9 9.5 cm/s + /19 19 cm/s + /38 38 cm/s + /76 76 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + TOAL + The 'Original album/movie/show title' frame is intended for the title + of the original recording (or source of sound), if for example the + music in the file should be a cover of a previously released song. + + TOFN + The 'Original filename' frame contains the preferred filename for the + file, since some media doesn't allow the desired length of the + filename. The filename is case sensitive and includes its suffix. + + TOLY + The 'Original lyricist(s)/text writer(s)' frame is intended for the + text writer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The text + writers are seperated with the "/" character. + + TOPE + The 'Original artist(s)/performer(s)' frame is intended for the + performer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The + performers are seperated with the "/" character. + + TORY + The 'Original release year' frame is intended for the year when the + original recording, if for example the music in the file should be a + cover of a previously released song, was released. The field is + formatted as in the "TYER" frame. + + TOWN + The 'File owner/licensee' frame contains the name of the owner or + licensee of the file and it's contents. + + TPE1 + The 'Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group' is + used for the main artist(s). They are seperated with the "/" + character. + + TPE2 + The 'Band/Orchestra/Accompaniment' frame is used for additional + information about the performers in the recording. + + TPE3 + The 'Conductor' frame is used for the name of the conductor. + + TPE4 + The 'Interpreted, remixed, or otherwise modified by' frame contains + more information about the people behind a remix and similar + interpretations of another existing piece. + + TPOS + The 'Part of a set' frame is a numeric string that describes which + part of a set the audio came from. This frame is used if the source + described in the "TALB" frame is divided into several mediums, e.g. a + double CD. The value may be extended with a "/" character and a + numeric string containing the total number of parts in the set. E.g. + "1/2". + + TPUB + The 'Publisher' frame simply contains the name of the label or + publisher. + + TRCK + The 'Track number/Position in set' frame is a numeric string + containing the order number of the audio-file on its original + recording. This may be extended with a "/" character and a numeric + string containing the total numer of tracks/elements on the original + recording. E.g. "4/9". + + TRDA + The 'Recording dates' frame is a intended to be used as complement to + the "TYER", "TDAT" and "TIME" frames. E.g. "4th-7th June, 12th June" + in combination with the "TYER" frame. + + TRSN + The 'Internet radio station name' frame contains the name of the + internet radio station from which the audio is streamed. + + TRSO + The 'Internet radio station owner' frame contains the name of the + owner of the internet radio station from which the audio is + streamed. + + TSIZ + The 'Size' frame contains the size of the audiofile in bytes, + excluding the ID3v2 tag, represented as a numeric string. + + TSRC + The 'ISRC' frame should contain the International Standard Recording + Code [ISRC] (12 characters). + + TSSE + The 'Software/Hardware and settings used for encoding' frame + includes the used audio encoder and its settings when the file was + encoded. Hardware refers to hardware encoders, not the computer on + which a program was run. + + TYER + The 'Year' frame is a numeric string with a year of the recording. + This frames is always four characters long (until the year 10000). + + +4.2.2. User defined text information frame + + This frame is intended for one-string text information concerning the + audiofile in a similar way to the other "T"-frames. The frame body + consists of a description of the string, represented as a terminated + string, followed by the actual string. There may be more than one + "TXXX" frame in each tag, but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + Value + + +4.3. URL link frames + + With these frames dynamic data such as webpages with touring + information, price information or plain ordinary news can be added to + the tag. There may only be one URL [URL] link frame of its kind in an + tag, except when stated otherwise in the frame description. If the + textstring is followed by a termination ($00 (00)) all the following + information should be ignored and not be displayed. All URL link + frame identifiers begins with "W". Only URL link frame identifiers + begins with "W". All URL link frames have the following format: + +
+ URL + + +4.3.1. URL link frames - details + + WCOM + The 'Commercial information' frame is a URL pointing at a webpage + with information such as where the album can be bought. There may be + more than one "WCOM" frame in a tag, but not with the same content. + + WCOP + The 'Copyright/Legal information' frame is a URL pointing at a + webpage where the terms of use and ownership of the file is + described. + + WOAF + The 'Official audio file webpage' frame is a URL pointing at a file + specific webpage. + + WOAR + The 'Official artist/performer webpage' frame is a URL pointing at + the artists official webpage. There may be more than one "WOAR" frame + in a tag if the audio contains more than one performer, but not with + the same content. + + WOAS + The 'Official audio source webpage' frame is a URL pointing at the + official webpage for the source of the audio file, e.g. a movie. + + WORS + The 'Official internet radio station homepage' contains a URL + pointing at the homepage of the internet radio station. + + WPAY + The 'Payment' frame is a URL pointing at a webpage that will handle + the process of paying for this file. + + WPUB + The 'Publishers official webpage' frame is a URL pointing at the + official wepage for the publisher. + + +4.3.2. User defined URL link frame + + This frame is intended for URL [URL] links concerning the audiofile + in a similar way to the other "W"-frames. The frame body consists + of a description of the string, represented as a terminated string, + followed by the actual URL. The URL is always encoded with ISO-8859-1 + [ISO-8859-1]. There may be more than one "WXXX" frame in each tag, + but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + URL + + +4.4. Involved people list + + Since there might be a lot of people contributing to an audio file in + various ways, such as musicians and technicians, the 'Text + information frames' are often insufficient to list everyone involved + in a project. The 'Involved people list' is a frame containing the + names of those involved, and how they were involved. The body simply + contains a terminated string with the involvement directly followed + by a terminated string with the involvee followed by a new + involvement and so on. There may only be one "IPLS" frame in each + tag. + +
+ Text encoding $xx + People list strings + + +4.5. Music CD identifier + + This frame is intended for music that comes from a CD, so that the CD + can be identified in databases such as the CDDB [CDDB]. The frame + consists of a binary dump of the Table Of Contents, TOC, from the CD, + which is a header of 4 bytes and then 8 bytes/track on the CD plus 8 + bytes for the 'lead out' making a maximum of 804 bytes. The offset to + the beginning of every track on the CD should be described with a + four bytes absolute CD-frame address per track, and not with absolute + time. This frame requires a present and valid "TRCK" frame, even if + the CD's only got one track. There may only be one "MCDI" frame in + each tag. + +
+ CD TOC + + +4.6. Event timing codes + + This frame allows synchronisation with key events in a song or sound. + The header is: + +
+ Time stamp format $xx + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + Followed by a list of key events in the following format: + + Type of event $xx + Time stamp $xx (xx ...) + + The 'Time stamp' is set to zero if directly at the beginning of the + sound or after the previous event. All events should be sorted in + chronological order. The type of event is as follows: + + $00 padding (has no meaning) + $01 end of initial silence + $02 intro start + $03 mainpart start + $04 outro start + $05 outro end + $06 verse start + $07 refrain start + $08 interlude start + $09 theme start + $0A variation start + $0B key change + $0C time change + $0D momentary unwanted noise (Snap, Crackle & Pop) + $0E sustained noise + $0F sustained noise end + $10 intro end + $11 mainpart end + $12 verse end + $13 refrain end + $14 theme end + + $15-$DF reserved for future use + + $E0-$EF not predefined sync 0-F + + $F0-$FC reserved for future use + + $FD audio end (start of silence) + $FE audio file ends + $FF one more byte of events follows (all the following bytes with + the value $FF have the same function) + + Terminating the start events such as "intro start" is not required. + The 'Not predefined sync's ($E0-EF) are for user events. You might + want to synchronise your music to something, like setting of an + explosion on-stage, turning on your screensaver etc. + + There may only be one "ETCO" frame in each tag. + + +4.7. MPEG location lookup table + + To increase performance and accuracy of jumps within a MPEG [MPEG] + audio file, frames with timecodes in different locations in the file + might be useful. The ID3v2 frame includes references that the + software can use to calculate positions in the file. After the frame + header is a descriptor of how much the 'frame counter' should + increase for every reference. If this value is two then the first + reference points out the second frame, the 2nd reference the 4th + frame, the 3rd reference the 6th frame etc. In a similar way the + 'bytes between reference' and 'milliseconds between reference' points + out bytes and milliseconds respectively. + + Each reference consists of two parts; a certain number of bits, as + defined in 'bits for bytes deviation', that describes the difference + between what is said in 'bytes between reference' and the reality and + a certain number of bits, as defined in 'bits for milliseconds + deviation', that describes the difference between what is said in + 'milliseconds between reference' and the reality. The number of bits + in every reference, i.e. 'bits for bytes deviation'+'bits for + milliseconds deviation', must be a multiple of four. There may only + be one "MLLT" frame in each tag. + +
+ MPEG frames between reference $xx xx + Bytes between reference $xx xx xx + Milliseconds between reference $xx xx xx + Bits for bytes deviation $xx + Bits for milliseconds dev. $xx + + Then for every reference the following data is included; + + Deviation in bytes %xxx.... + Deviation in milliseconds %xxx.... + + +4.8. Synchronised tempo codes + + For a more accurate description of the tempo of a musical piece this + frame might be used. After the header follows one byte describing + which time stamp format should be used. Then follows one or more + tempo codes. Each tempo code consists of one tempo part and one time + part. The tempo is in BPM described with one or two bytes. If the + first byte has the value $FF, one more byte follows, which is added + to the first giving a range from 2 - 510 BPM, since $00 and $01 is + reserved. $00 is used to describe a beat-free time period, which is + not the same as a music-free time period. $01 is used to indicate one + single beat-stroke followed by a beat-free period. + + The tempo descriptor is followed by a time stamp. Every time the + tempo in the music changes, a tempo descriptor may indicate this for + the player. All tempo descriptors should be sorted in chronological + order. The first beat-stroke in a time-period is at the same time as + the beat description occurs. There may only be one "SYTC" frame in + each tag. + +
+ Time stamp format $xx + Tempo data + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + +4.9. Unsychronised lyrics/text transcription + + This frame contains the lyrics of the song or a text transcription of + other vocal activities. The head includes an encoding descriptor and + a content descriptor. The body consists of the actual text. The + 'Content descriptor' is a terminated string. If no descriptor is + entered, 'Content descriptor' is $00 (00) only. Newline characters + are allowed in the text. There may be more than one 'Unsynchronised + lyrics/text transcription' frame in each tag, but only one with the + same language and content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Content descriptor $00 (00) + Lyrics/text + + +4.10. Synchronised lyrics/text + + This is another way of incorporating the words, said or sung lyrics, + in the audio file as text, this time, however, in sync with the + audio. It might also be used to describing events e.g. occurring on a + stage or on the screen in sync with the audio. The header includes a + content descriptor, represented with as terminated textstring. If no + descriptor is entered, 'Content descriptor' is $00 (00) only. + +
+ Text encoding $xx + Language $xx xx xx + Time stamp format $xx + Content type $xx + Content descriptor $00 (00) + + + Encoding: $00 ISO-8859-1 [ISO-8859-1] character set is used => $00 + is sync identifier. + $01 Unicode [UNICODE] character set is used => $00 00 is + sync identifier. + + Content type: $00 is other + $01 is lyrics + $02 is text transcription + $03 is movement/part name (e.g. "Adagio") + $04 is events (e.g. "Don Quijote enters the stage") + $05 is chord (e.g. "Bb F Fsus") + $06 is trivia/'pop up' information + + Time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + The text that follows the frame header differs from that of the + unsynchronised lyrics/text transcription in one major way. Each + syllable (or whatever size of text is considered to be convenient by + the encoder) is a null terminated string followed by a time stamp + denoting where in the sound file it belongs. Each sync thus has the + following structure: + + Terminated text to be synced (typically a syllable) + Sync identifier (terminator to above string) $00 (00) + Time stamp $xx (xx ...) + + The 'time stamp' is set to zero or the whole sync is omitted if + located directly at the beginning of the sound. All time stamps + should be sorted in chronological order. The sync can be considered + as a validator of the subsequent string. + + Newline ($0A) characters are allowed in all "SYLT" frames and should + be used after every entry (name, event etc.) in a frame with the + content type $03 - $04. + + A few considerations regarding whitespace characters: Whitespace + separating words should mark the beginning of a new word, thus + occurring in front of the first syllable of a new word. This is also + valid for new line characters. A syllable followed by a comma should + not be broken apart with a sync (both the syllable and the comma + should be before the sync). + + An example: The "USLT" passage + + "Strangers in the night" $0A "Exchanging glances" + + would be "SYLT" encoded as: + + "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx + " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx + xx "glan" $00 xx xx "ces" $00 xx xx + + There may be more than one "SYLT" frame in each tag, but only one + with the same language and content descriptor. + + +4.11. Comments + + This frame is indended for any kind of full text information that + does not fit in any other frame. It consists of a frame header + followed by encoding, language and content descriptors and is ended + with the actual comment as a text string. Newline characters are + allowed in the comment text string. There may be more than one + comment frame in each tag, but only one with the same language and + content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Short content descrip. $00 (00) + The actual text + + +4.12. Relative volume adjustment + + This is a more subjective function than the previous ones. It allows + the user to say how much he wants to increase/decrease the volume on + each channel while the file is played. The purpose is to be able to + align all files to a reference volume, so that you don't have to + change the volume constantly. This frame may also be used to balance + adjust the audio. If the volume peak levels are known then this could + be described with the 'Peak volume right' and 'Peak volume left' + field. If Peakvolume is not known these fields could be left zeroed + or, if no other data follows, be completely omitted. There may only + be one "RVAD" frame in each tag. + +
+ Increment/decrement %00xxxxxx + Bits used for volume descr. $xx + Relative volume change, right $xx xx (xx ...) + Relative volume change, left $xx xx (xx ...) + Peak volume right $xx xx (xx ...) + Peak volume left $xx xx (xx ...) + + In the increment/decrement field bit 0 is used to indicate the right + channel and bit 1 is used to indicate the left channel. 1 is + increment and 0 is decrement. + + The 'bits used for volume description' field is normally $10 (16 + bits) for MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value + may not be $00. The volume is always represented with whole bytes, + padded in the beginning (highest bits) when 'bits used for volume + description' is not a multiple of eight. + + This datablock is then optionally followed by a volume definition for + the left and right back channels. If this information is appended to + the frame the first two channels will be treated as front channels. + In the increment/decrement field bit 2 is used to indicate the right + back channel and bit 3 for the left back channel. + + Relative volume change, right back $xx xx (xx ...) + Relative volume change, left back $xx xx (xx ...) + Peak volume right back $xx xx (xx ...) + Peak volume left back $xx xx (xx ...) + + If the center channel adjustment is present the following is appended + to the existing frame, after the left and right back channels. The + center channel is represented by bit 4 in the increase/decrease + field. + + Relative volume change, center $xx xx (xx ...) + Peak volume center $xx xx (xx ...) + + If the bass channel adjustment is present the following is appended + to the existing frame, after the center channel. The bass channel is + represented by bit 5 in the increase/decrease field. + + Relative volume change, bass $xx xx (xx ...) + Peak volume bass $xx xx (xx ...) + + +4.13. Equalisation + + This is another subjective, alignment frame. It allows the user to + predefine an equalisation curve within the audio file. There may only + be one "EQUA" frame in each tag. + +
+ Adjustment bits $xx + + The 'adjustment bits' field defines the number of bits used for + representation of the adjustment. This is normally $10 (16 bits) for + MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value may not be + $00. + + This is followed by 2 bytes + ('adjustment bits' rounded up to the + nearest byte) for every equalisation band in the following format, + giving a frequency range of 0 - 32767Hz: + + Increment/decrement %x (MSB of the Frequency) + Frequency (lower 15 bits) + Adjustment $xx (xx ...) + + The increment/decrement bit is 1 for increment and 0 for decrement. + The equalisation bands should be ordered increasingly with reference + to frequency. All frequencies don't have to be declared. The + equalisation curve in the reading software should be interpolated + between the values in this frame. Three equal adjustments for three + subsequent frequencies. A frequency should only be described once in + the frame. + + +4.14. Reverb + + Yet another subjective one. You may here adjust echoes of different + kinds. Reverb left/right is the delay between every bounce in ms. + Reverb bounces left/right is the number of bounces that should be + made. $FF equals an infinite number of bounces. Feedback is the + amount of volume that should be returned to the next echo bounce. $00 + is 0%, $FF is 100%. If this value were $7F, there would be 50% volume + reduction on the first bounce, 50% of that on the second and so on. + Left to left means the sound from the left bounce to be played in the + left speaker, while left to right means sound from the left bounce to + be played in the right speaker. + + 'Premix left to right' is the amount of left sound to be mixed in the + right before any reverb is applied, where $00 id 0% and $FF is 100%. + 'Premix right to left' does the same thing, but right to left. + Setting both premix to $FF would result in a mono output (if the + reverb is applied symmetric). There may only be one "RVRB" frame in + each tag. + +
+ Reverb left (ms) $xx xx + Reverb right (ms) $xx xx + Reverb bounces, left $xx + Reverb bounces, right $xx + Reverb feedback, left to left $xx + Reverb feedback, left to right $xx + Reverb feedback, right to right $xx + Reverb feedback, right to left $xx + Premix left to right $xx + Premix right to left $xx + + +4.15. Attached picture + + This frame contains a picture directly related to the audio file. + Image format is the MIME type and subtype [MIME] for the image. In + the event that the MIME media type name is omitted, "image/" will be + implied. The "image/png" [PNG] or "image/jpeg" [JFIF] picture format + should be used when interoperability is wanted. Description is a + short description of the picture, represented as a terminated + textstring. The description has a maximum length of 64 characters, + but may be empty. There may be several pictures attached to one file, + each in their individual "APIC" frame, but only one with the same + content descriptor. There may only be one picture with the picture + type declared as picture type $01 and $02 respectively. There is the + possibility to put only a link to the image file by using the 'MIME + type' "-->" and having a complete URL [URL] instead of picture data. + The use of linked files should however be used sparingly since there + is the risk of separation of files. + +
+ Text encoding $xx + MIME type $00 + Picture type $xx + Description $00 (00) + Picture data + + + Picture type: $00 Other + $01 32x32 pixels 'file icon' (PNG only) + $02 Other file icon + $03 Cover (front) + $04 Cover (back) + $05 Leaflet page + $06 Media (e.g. lable side of CD) + $07 Lead artist/lead performer/soloist + $08 Artist/performer + $09 Conductor + $0A Band/Orchestra + $0B Composer + $0C Lyricist/text writer + $0D Recording Location + $0E During recording + $0F During performance + $10 Movie/video screen capture + $11 A bright coloured fish + $12 Illustration + $13 Band/artist logotype + $14 Publisher/Studio logotype + + +4.16. General encapsulated object + + In this frame any type of file can be encapsulated. After the header, + 'Frame size' and 'Encoding' follows 'MIME type' [MIME] represented as + as a terminated string encoded with ISO 8859-1 [ISO-8859-1]. The + filename is case sensitive and is encoded as 'Encoding'. Then follows + a content description as terminated string, encoded as 'Encoding'. + The last thing in the frame is the actual object. The first two + strings may be omitted, leaving only their terminations. MIME type is + always an ISO-8859-1 text string. There may be more than one "GEOB" + frame in each tag, but only one with the same content descriptor. + +
+ Text encoding $xx + MIME type $00 + Filename $00 (00) + Content description $00 (00) + Encapsulated object + + +4.17. Play counter + + This is simply a counter of the number of times a file has been + played. The value is increased by one every time the file begins to + play. There may only be one "PCNT" frame in each tag. When the + counter reaches all one's, one byte is inserted in front of the + counter thus making the counter eight bits bigger. The counter must + be at least 32-bits long to begin with. + +
+ Counter $xx xx xx xx (xx ...) + + +4.18. Popularimeter + + The purpose of this frame is to specify how good an audio file is. + Many interesting applications could be found to this frame such as a + playlist that features better audiofiles more often than others or it + could be used to profile a person's taste and find other 'good' files + by comparing people's profiles. The frame is very simple. It contains + the email address to the user, one rating byte and a four byte play + counter, intended to be increased with one for every time the file is + played. The email is a terminated string. The rating is 1-255 where + 1 is worst and 255 is best. 0 is unknown. If no personal counter is + wanted it may be omitted. When the counter reaches all one's, one + byte is inserted in front of the counter thus making the counter + eight bits bigger in the same away as the play counter ("PCNT"). + There may be more than one "POPM" frame in each tag, but only one + with the same email address. + +
+ Email to user $00 + Rating $xx + Counter $xx xx xx xx (xx ...) + + +4.19. Recommended buffer size + + Sometimes the server from which a audio file is streamed is aware of + transmission or coding problems resulting in interruptions in the + audio stream. In these cases, the size of the buffer can be + recommended by the server using this frame. If the 'embedded info + flag' is true (1) then this indicates that an ID3 tag with the + maximum size described in 'Buffer size' may occur in the audiostream. + In such case the tag should reside between two MPEG [MPEG] frames, if + the audio is MPEG encoded. If the position of the next tag is known, + 'offset to next tag' may be used. The offset is calculated from the + end of tag in which this frame resides to the first byte of the + header in the next. This field may be omitted. Embedded tags are + generally not recommended since this could render unpredictable + behaviour from present software/hardware. + + For applications like streaming audio it might be an idea to embed + tags into the audio stream though. If the clients connects to + individual connections like HTTP and there is a possibility to begin + every transmission with a tag, then this tag should include a + 'recommended buffer size' frame. If the client is connected to a + arbitrary point in the stream, such as radio or multicast, then the + 'recommended buffer size' frame should be included in every tag. + Every tag that is picked up after the initial/first tag is to be + considered as an update of the previous one. E.g. if there is a + "TIT2" frame in the first received tag and one in the second tag, + then the first should be 'replaced' with the second. + + The 'Buffer size' should be kept to a minimum. There may only be one + "RBUF" frame in each tag. + +
+ Buffer size $xx xx xx + Embedded info flag %0000000x + Offset to next tag $xx xx xx xx + + +4.20. Audio encryption + + This frame indicates if the actual audio stream is encrypted, and by + whom. Since standardisation of such encrypion scheme is beyond this + document, all "AENC" frames begin with a terminated string with a + URL containing an email address, or a link to a location where an + email address can be found, that belongs to the organisation + responsible for this specific encrypted audio file. Questions + regarding the encrypted audio should be sent to the email address + specified. If a $00 is found directly after the 'Frame size' and the + audiofile indeed is encrypted, the whole file may be considered + useless. + + After the 'Owner identifier', a pointer to an unencrypted part of the + audio can be specified. The 'Preview start' and 'Preview length' is + described in frames. If no part is unencrypted, these fields should + be left zeroed. After the 'preview length' field follows optionally a + datablock required for decryption of the audio. There may be more + than one "AENC" frames in a tag, but only one with the same 'Owner + identifier'. + +
+ Owner identifier $00 + Preview start $xx xx + Preview length $xx xx + Encryption info + + +4.21. Linked information + + To keep space waste as low as possible this frame may be used to link + information from another ID3v2 tag that might reside in another audio + file or alone in a binary file. It is recommended that this method is + only used when the files are stored on a CD-ROM or other + circumstances when the risk of file seperation is low. The frame + contains a frame identifier, which is the frame that should be linked + into this tag, a URL [URL] field, where a reference to the file where + the frame is given, and additional ID data, if needed. Data should be + retrieved from the first tag found in the file to which this link + points. There may be more than one "LINK" frame in a tag, but only + one with the same contents. A linked frame is to be considered as + part of the tag and has the same restrictions as if it was a physical + part of the tag (i.e. only one "RVRB" frame allowed, whether it's + linked or not). + +
+ Frame identifier $xx xx xx + URL $00 + ID and additional data + + Frames that may be linked and need no additional data are "IPLS", + "MCID", "ETCO", "MLLT", "SYTC", "RVAD", "EQUA", "RVRB", "RBUF", the + text information frames and the URL link frames. + + The "TXXX", "APIC", "GEOB" and "AENC" frames may be linked with + the content descriptor as additional ID data. + + The "COMM", "SYLT" and "USLT" frames may be linked with three bytes + of language descriptor directly followed by a content descriptor as + additional ID data. + + +4.22. Position synchronisation frame + + This frame delivers information to the listener of how far into the + audio stream he picked up; in effect, it states the time offset of + the first frame in the stream. The frame layout is: + + + Time stamp format $xx + Position $xx (xx ...) + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + and position is where in the audio the listener starts to receive, + i.e. the beginning of the next frame. If this frame is used in the + beginning of a file the value is always 0. There may only be one + "POSS" frame in each tag. + + +4.23. Terms of use frame + + This frame contains a brief description of the terms of use and + ownership of the file. More detailed information concerning the legal + terms might be available through the "WCOP" frame. Newlines are + allowed in the text. There may only be one "USER" frame in a tag. + +
+ Text encoding $xx + Language $xx xx xx + The actual text + + +4.24. Ownership frame + + The ownership frame might be used as a reminder of a made transaction + or, if signed, as proof. Note that the "USER" and "TOWN" frames are + good to use in conjunction with this one. The frame begins, after the + frame ID, size and encoding fields, with a 'price payed' field. The + first three characters of this field contains the currency used for + the transaction, encoded according to ISO 4217 [ISO-4217] alphabetic + currency code. Concatenated to this is the actual price payed, as a + numerical string using "." as the decimal separator. Next is an 8 + character date string (YYYYMMDD) followed by a string with the name + of the seller as the last field in the frame. There may only be one + "OWNE" frame in a tag. + +
+ Text encoding $xx + Price payed $00 + Date of purch. + Seller + + +4.25. Commercial frame + + This frame enables several competing offers in the same tag by + bundling all needed information. That makes this frame rather complex + but it's an easier solution than if one tries to achieve the same + result with several frames. The frame begins, after the frame ID, + size and encoding fields, with a price string field. A price is + constructed by one three character currency code, encoded according + to ISO 4217 [ISO-4217] alphabetic currency code, followed by a + numerical value where "." is used as decimal seperator. In the price + string several prices may be concatenated, seperated by a "/" + character, but there may only be one currency of each type. + + The price string is followed by an 8 character date string in the + format YYYYMMDD, describing for how long the price is valid. After + that is a contact URL, with which the user can contact the seller, + followed by a one byte 'received as' field. It describes how the + audio is delivered when bought according to the following list: + + $00 Other + $01 Standard CD album with other songs + $02 Compressed audio on CD + $03 File over the Internet + $04 Stream over the Internet + $05 As note sheets + $06 As note sheets in a book with other sheets + $07 Music on other media + $08 Non-musical merchandise + + Next follows a terminated string with the name of the seller followed + by a terminated string with a short description of the product. The + last thing is the ability to include a company logotype. The first of + them is the 'Picture MIME type' field containing information about + which picture format is used. In the event that the MIME media type + name is omitted, "image/" will be implied. Currently only "image/png" + and "image/jpeg" are allowed. This format string is followed by the + binary picture data. This two last fields may be omitted if no + picture is to attach. + +
+ Text encoding $xx + Price string $00 + Valid until + Contact URL $00 + Received as $xx + Name of seller $00 (00) + Description $00 (00) + Picture MIME type $00 + Seller logo + + +4.26. Encryption method registration + + To identify with which method a frame has been encrypted the + encryption method must be registered in the tag with this frame. The + 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for this specific encryption method. Questions regarding the + encryption method should be sent to the indicated email address. The + 'Method symbol' contains a value that is associated with this method + throughout the whole tag. Values below $80 are reserved. The 'Method + symbol' may optionally be followed by encryption specific data. There + may be several "ENCR" frames in a tag but only one containing the + same symbol and only one containing the same owner identifier. The + method must be used somewhere in the tag. See section 3.3.1, flag j + for more information. + +
+ Owner identifier $00 + Method symbol $xx + Encryption data + + +4.27. Group identification registration + + This frame enables grouping of otherwise unrelated frames. This can + be used when some frames are to be signed. To identify which frames + belongs to a set of frames a group identifier must be registered in + the tag with this frame. The 'Owner identifier' is a null-terminated + string with a URL [URL] containing an email address, or a link to a + location where an email address can be found, that belongs to the + organisation responsible for this grouping. Questions regarding the + grouping should be sent to the indicated email address. The 'Group + symbol' contains a value that associates the frame with this group + throughout the whole tag. Values below $80 are reserved. The 'Group + symbol' may optionally be followed by some group specific data, e.g. + a digital signature. There may be several "GRID" frames in a tag but + only one containing the same symbol and only one containing the same + owner identifier. The group symbol must be used somewhere in the tag. + See section 3.3.1, flag j for more information. + +
+ Owner identifier $00 + Group symbol $xx + Group dependent data + + +4.28. Private frame + + This frame is used to contain information from a software producer + that its program uses and does not fit into the other frames. The + frame consists of an 'Owner identifier' string and the binary data. + The 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for the frame. Questions regarding the frame should be sent to the + indicated email address. The tag may contain more than one "PRIV" + frame but only with different contents. It is recommended to keep the + number of "PRIV" frames as low as possible. + +
+ Owner identifier $00 + The private data + + +5. The 'unsynchronisation scheme' + + The only purpose of the 'unsynchronisation scheme' is to make the + ID3v2 tag as compatible as possible with existing software. There is + no use in 'unsynchronising' tags if the file is only to be processed + by new software. Unsynchronisation may only be made with MPEG 2 layer + I, II and III and MPEG 2.5 files. + + Whenever a false synchronisation is found within the tag, one zeroed + byte is inserted after the first false synchronisation byte. The + format of a correct sync that should be altered by ID3 encoders is as + follows: + + %11111111 111xxxxx + + And should be replaced with: + + %11111111 00000000 111xxxxx + + This has the side effect that all $FF 00 combinations have to be + altered, so they won't be affected by the decoding process. Therefore + all the $FF 00 combinations have to be replaced with the $FF 00 00 + combination during the unsynchronisation. + + To indicate usage of the unsynchronisation, the first bit in 'ID3 + flags' should be set. This bit should only be set if the tag + contains a, now corrected, false synchronisation. The bit should + only be clear if the tag does not contain any false synchronisations. + + Do bear in mind, that if a compression scheme is used by the encoder, + the unsynchronisation scheme should be applied *afterwards*. When + decoding a compressed, 'unsynchronised' file, the 'unsynchronisation + scheme' should be parsed first, decompression afterwards. + + If the last byte in the tag is $FF, and there is a need to eliminate + false synchronisations in the tag, at least one byte of padding + should be added. + + +6. Copyright + + Copyright (C) Martin Nilsson 1998. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + "AS IS" basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +7. References + + [CDDB] Compact Disc Data Base + + http://www.cddb.com + + [ID3v2] Martin Nilsson, "ID3v2 informal standard". + + http://www.id3lib.org/id3/id3v2-00.txt + + [ISO-639-2] ISO/FDIS 639-2. + Codes for the representation of names of languages, Part 2: Alpha-3 + code. Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-4217] ISO 4217:1995. + Codes for the representation of currencies and funds. + Technical committee / subcommittee: TC 68 + + [ISO-8859-1] ISO/IEC DIS 8859-1. + 8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1. Technical committee / subcommittee: JTC 1 / SC 2 + + [ISRC] ISO 3901:1986 + International Standard Recording Code (ISRC). + Technical committee / subcommittee: TC 46 / SC 9 + + [JFIF] JPEG File Interchange Format, version 1.02 + + http://www.w3.org/Graphics/JPEG/jfif.txt">http://www.w3.org/Graphics/JPEG/jfif.txt + + [MIME] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message Bodies", + RFC 2045, November 1996. + + ftp://ftp.isi.edu/in-notes/rfc2045.txt">ftp://ftp.isi.edu/in-notes/rfc2045.txt + + [MPEG] ISO/IEC 11172-3:1993. + Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + Generic coding of moving pictures and associated audio information, + Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995) + + + [PNG] Portable Network Graphics, version 1.0 + + http://www.w3.org/TR/REC-png-multi.html + + [UNICODE] ISO/IEC 10646-1:1993. + Universal Multiple-Octet Coded Character Set (UCS), Part 1: + Architecture and Basic Multilingual Plane. + Technical committee / subcommittee: JTC 1 / SC 2 + + http://www.unicode.org/ + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, "Uniform Resource + Locators (URL).", RFC 1738, December 1994. + + ftp://ftp.isi.edu/in-notes/rfc1738.txt + + [ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, "ZLIB + Compressed + Data Format Specification version 3.3", RFC 1950, May 1996. + + ftp://ftp.isi.edu/in-notes/rfc1950.txt + + +8. Appendix + + +A. Appendix A - Genre List from ID3v1 + + The following genres is defined in ID3v1 + + 0.Blues + 1.Classic Rock + 2.Country + 3.Dance + 4.Disco + 5.Funk + 6.Grunge + 7.Hip-Hop + 8.Jazz + 9.Metal + 10.New Age + 11.Oldies + 12.Other + 13.Pop + 14.R&B + 15.Rap + 16.Reggae + 17.Rock + 18.Techno + 19.Industrial + 20.Alternative + 21.Ska + 22.Death Metal + 23.Pranks + 24.Soundtrack + 25.Euro-Techno + 26.Ambient + 27.Trip-Hop + 28.Vocal + 29.Jazz+Funk + 30.Fusion + 31.Trance + 32.Classical + 33.Instrumental + 34.Acid + 35.House + 36.Game + 37.Sound Clip + 38.Gospel + 39.Noise + 40.AlternRock + 41.Bass + 42.Soul + 43.Punk + 44.Space + 45.Meditative + 46.Instrumental Pop + 47.Instrumental Rock + 48.Ethnic + 49.Gothic + 50.Darkwave + 51.Techno-Industrial + 52.Electronic + 53.Pop-Folk + 54.Eurodance + 55.Dream + 56.Southern Rock + 57.Comedy + 58.Cult + 59.Gangsta + 60.Top 40 + 61.Christian Rap + 62.Pop/Funk + 63.Jungle + 64.Native American + 65.Cabaret + 66.New Wave + 67.Psychadelic + 68.Rave + 69.Showtunes + 70.Trailer + 71.Lo-Fi + 72.Tribal + 73.Acid Punk + 74.Acid Jazz + 75.Polka + 76.Retro + 77.Musical + 78.Rock & Roll + 79.Hard Rock + + The following genres are Winamp extensions + + 80.Folk + 81.Folk-Rock + 82.National Folk + 83.Swing + 84.Fast Fusion + 85.Bebob + 86.Latin + 87.Revival + 88.Celtic + 89.Bluegrass + 90.Avantgarde + 91.Gothic Rock + 92.Progressive Rock + 93.Psychedelic Rock + 94.Symphonic Rock + 95.Slow Rock + 96.Big Band + 97.Chorus + 98.Easy Listening + 99.Acoustic + 100.Humour + 101.Speech + 102.Chanson + 103.Opera + 104.Chamber Music + 105.Sonata + 106.Symphony + 107.Booty Bass + 108.Primus + 109.Porn Groove + 110.Satire + 111.Slow Jam + 112.Club + 113.Tango + 114.Samba + 115.Folklore + 116.Ballad + 117.Power Ballad + 118.Rhythmic Soul + 119.Freestyle + 120.Duet + 121.Punk Rock + 122.Drum Solo + 123.Acapella + 124.Euro-House + 125.Dance Hall + + +9. Author's Address + + Written by + + Martin Nilsson + Rydsvägen 246 C. 30 + S-584 34 Linköping + Sweden + + Email: nilsson@id3.org + + + Edited by + + Dirk Mahoney + 57 Pechey Street + Chermside Q + Australia 4032 + + Email: dirk@id3.org + + + Johan Sundström + Alsättersgatan 5 A. 34 + S-584 35 Linköping + Sweden + + Email: johan@id3.org diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-frames.txt b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-frames.txt new file mode 100644 index 00000000..74a21bed --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-frames.txt @@ -0,0 +1,1734 @@ +$Id$ + +Informal standard M. Nilsson +Document: id3v2.4.0-frames.txt 1st November 2000 + + + ID3 tag version 2.4.0 - Native Frames + +Status of this document + + This document is an informal standard and replaces the ID3v2.3.0 + standard [ID3v2]. A formal standard will use another revision number + even if the content is identical to document. The contents in this + document may change for clarifications but never for added or altered + functionallity. + + Distribution of this document is unlimited. + + +Abstract + + This document describes the frames natively supported by ID3v2.4.0, + which is a revised version of the ID3v2 informal standard [ID3v2.3.0] + version 2.3.0. The ID3v2 offers a flexible way of storing audio meta + information within audio file itself. The information may be + technical information, such as equalisation curves, as well as title, + performer, copyright etc. + + ID3v2.4.0 is meant to be as close as possible to ID3v2.3.0 in order + to allow for implementations to be revised as easily as possible. + + +1. Table of contents + + 2. Conventions in this document + 3. Default flags + 4. Declared ID3v2 frames + 4.1. Unique file identifier + 4.2. Text information frames + 4.2.1. Identification frames + 4.2.2. Involved persons frames + 4.2.3. Derived and subjective properties frames + 4.2.4. Rights and license frames + 4.2.5. Other text frames + 4.2.6. User defined text information frame + 4.3. URL link frames + 4.3.1. URL link frames - details + 4.3.2. User defined URL link frame + 4.4. Music CD Identifier + 4.5. Event timing codes + 4.6. MPEG location lookup table + 4.7. Synced tempo codes + 4.8. Unsynchronised lyrics/text transcription + 4.9. Synchronised lyrics/text + 4.10. Comments + 4.11. Relative volume adjustment (2) + 4.12. Equalisation (2) + 4.13. Reverb + 4.14. Attached picture + 4.15. General encapsulated object + 4.16. Play counter + 4.17. Popularimeter + 4.18. Recommended buffer size + 4.19. Audio encryption + 4.20. Linked information + 4.21. Position synchronisation frame + 4.22. Terms of use + 4.23. Ownership frame + 4.24. Commercial frame + 4.25. Encryption method registration + 4.26. Group identification registration + 4.27. Private frame + 4.28. Signature frame + 4.29. Seek frame + 4.30. Audio seek point index + 5. Copyright + 6. References + 7. Appendix + A. Appendix A - Genre List from ID3v1 + 8. Author's Address + + +2. Conventions in this document + + Text within "" is a text string exactly as it appears in a tag. + Numbers preceded with $ are hexadecimal and numbers preceded with % + are binary. $xx is used to indicate a byte with unknown content. %x + is used to indicate a bit with unknown content. The most significant + bit (MSB) of a byte is called 'bit 7' and the least significant bit + (LSB) is called 'bit 0'. + + A tag is the whole tag described the ID3v2 main structure document + [ID3v2-strct]. A frame is a block of information in the tag. The tag + consists of a header, frames and optional padding. A field is a piece + of information; one value, a string etc. A numeric string is a string + that consists of the characters "0123456789" only. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119 [KEYWORDS]. + + +3. Default flags + + The default settings for the frames described in this document can be + divided into the following classes. The flags may be set differently + if found more suitable by the software. + + 1. Discarded if tag is altered, discarded if file is altered. + + None. + + 2. Discarded if tag is altered, preserved if file is altered. + + None. + + 3. Preserved if tag is altered, discarded if file is altered. + + ASPI, AENC, ETCO, EQU2, MLLT, POSS, SEEK, SYLT, SYTC, RVA2, TENC, + TLEN + + 4. Preserved if tag is altered, preserved if file is altered. + + The rest of the frames. + + +4. Declared ID3v2 frames + + The following frames are declared in this draft. + + 4.19 AENC Audio encryption + 4.14 APIC Attached picture + 4.30 ASPI Audio seek point index + + 4.10 COMM Comments + 4.24 COMR Commercial frame + + 4.25 ENCR Encryption method registration + 4.12 EQU2 Equalisation (2) + 4.5 ETCO Event timing codes + + 4.15 GEOB General encapsulated object + 4.26 GRID Group identification registration + + 4.20 LINK Linked information + + 4.4 MCDI Music CD identifier + 4.6 MLLT MPEG location lookup table + + 4.23 OWNE Ownership frame + + 4.27 PRIV Private frame + 4.16 PCNT Play counter + 4.17 POPM Popularimeter + 4.21 POSS Position synchronisation frame + + 4.18 RBUF Recommended buffer size + 4.11 RVA2 Relative volume adjustment (2) + 4.13 RVRB Reverb + + 4.29 SEEK Seek frame + 4.28 SIGN Signature frame + 4.9 SYLT Synchronised lyric/text + 4.7 SYTC Synchronised tempo codes + + 4.2.1 TALB Album/Movie/Show title + 4.2.3 TBPM BPM (beats per minute) + 4.2.2 TCOM Composer + 4.2.3 TCON Content type + 4.2.4 TCOP Copyright message + 4.2.5 TDEN Encoding time + 4.2.5 TDLY Playlist delay + 4.2.5 TDOR Original release time + 4.2.5 TDRC Recording time + 4.2.5 TDRL Release time + 4.2.5 TDTG Tagging time + 4.2.2 TENC Encoded by + 4.2.2 TEXT Lyricist/Text writer + 4.2.3 TFLT File type + 4.2.2 TIPL Involved people list + 4.2.1 TIT1 Content group description + 4.2.1 TIT2 Title/songname/content description + 4.2.1 TIT3 Subtitle/Description refinement + 4.2.3 TKEY Initial key + 4.2.3 TLAN Language(s) + 4.2.3 TLEN Length + 4.2.2 TMCL Musician credits list + 4.2.3 TMED Media type + 4.2.3 TMOO Mood + 4.2.1 TOAL Original album/movie/show title + 4.2.5 TOFN Original filename + 4.2.2 TOLY Original lyricist(s)/text writer(s) + 4.2.2 TOPE Original artist(s)/performer(s) + 4.2.4 TOWN File owner/licensee + 4.2.2 TPE1 Lead performer(s)/Soloist(s) + 4.2.2 TPE2 Band/orchestra/accompaniment + 4.2.2 TPE3 Conductor/performer refinement + 4.2.2 TPE4 Interpreted, remixed, or otherwise modified by + 4.2.1 TPOS Part of a set + 4.2.4 TPRO Produced notice + 4.2.4 TPUB Publisher + 4.2.1 TRCK Track number/Position in set + 4.2.4 TRSN Internet radio station name + 4.2.4 TRSO Internet radio station owner + 4.2.5 TSOA Album sort order + 4.2.5 TSOP Performer sort order + 4.2.5 TSOT Title sort order + 4.2.1 TSRC ISRC (international standard recording code) + 4.2.5 TSSE Software/Hardware and settings used for encoding + 4.2.1 TSST Set subtitle + 4.2.2 TXXX User defined text information frame + + 4.1 UFID Unique file identifier + 4.22 USER Terms of use + 4.8 USLT Unsynchronised lyric/text transcription + + 4.3.1 WCOM Commercial information + 4.3.1 WCOP Copyright/Legal information + 4.3.1 WOAF Official audio file webpage + 4.3.1 WOAR Official artist/performer webpage + 4.3.1 WOAS Official audio source webpage + 4.3.1 WORS Official Internet radio station homepage + 4.3.1 WPAY Payment + 4.3.1 WPUB Publishers official webpage + 4.3.2 WXXX User defined URL link frame + + +4.1. Unique file identifier + + This frame's purpose is to be able to identify the audio file in a + database, that may provide more information relevant to the content. + Since standardisation of such a database is beyond this document, all + UFID frames begin with an 'owner identifier' field. It is a null- + terminated string with a URL [URL] containing an email address, or a + link to a location where an email address can be found, that belongs + to the organisation responsible for this specific database + implementation. Questions regarding the database should be sent to + the indicated email address. The URL should not be used for the + actual database queries. The string + "http://www.id3.org/dummy/ufid.html" should be used for tests. The + 'Owner identifier' must be non-empty (more than just a termination). + The 'Owner identifier' is then followed by the actual identifier, + which may be up to 64 bytes. There may be more than one "UFID" frame + in a tag, but only one with the same 'Owner identifier'. + +
+ Owner identifier $00 + Identifier + + +4.2. Text information frames + + The text information frames are often the most important frames, + containing information like artist, album and more. There may only be + one text information frame of its kind in an tag. All text + information frames supports multiple strings, stored as a null + separated list, where null is reperesented by the termination code + for the charater encoding. All text frame identifiers begin with "T". + Only text frame identifiers begin with "T", with the exception of the + "TXXX" frame. All the text information frames have the following + format: + +
+ Text encoding $xx + Information + + +4.2.1. Identification frames + + TIT1 + The 'Content group description' frame is used if the sound belongs to + a larger category of sounds/music. For example, classical music is + often sorted in different musical sections (e.g. "Piano Concerto", + "Weather - Hurricane"). + + TIT2 + The 'Title/Songname/Content description' frame is the actual name of + the piece (e.g. "Adagio", "Hurricane Donna"). + + TIT3 + The 'Subtitle/Description refinement' frame is used for information + directly related to the contents title (e.g. "Op. 16" or "Performed + live at Wembley"). + + TALB + The 'Album/Movie/Show title' frame is intended for the title of the + recording (or source of sound) from which the audio in the file is + taken. + + TOAL + The 'Original album/movie/show title' frame is intended for the title + of the original recording (or source of sound), if for example the + music in the file should be a cover of a previously released song. + + TRCK + The 'Track number/Position in set' frame is a numeric string + containing the order number of the audio-file on its original + recording. This MAY be extended with a "/" character and a numeric + string containing the total number of tracks/elements on the original + recording. E.g. "4/9". + + TPOS + The 'Part of a set' frame is a numeric string that describes which + part of a set the audio came from. This frame is used if the source + described in the "TALB" frame is divided into several mediums, e.g. a + double CD. The value MAY be extended with a "/" character and a + numeric string containing the total number of parts in the set. E.g. + "1/2". + + TSST + The 'Set subtitle' frame is intended for the subtitle of the part of + a set this track belongs to. + + TSRC + The 'ISRC' frame should contain the International Standard Recording + Code [ISRC] (12 characters). + + +4.2.2. Involved persons frames + + TPE1 + The 'Lead artist/Lead performer/Soloist/Performing group' is + used for the main artist. + + TPE2 + The 'Band/Orchestra/Accompaniment' frame is used for additional + information about the performers in the recording. + + TPE3 + The 'Conductor' frame is used for the name of the conductor. + + TPE4 + The 'Interpreted, remixed, or otherwise modified by' frame contains + more information about the people behind a remix and similar + interpretations of another existing piece. + + TOPE + The 'Original artist/performer' frame is intended for the performer + of the original recording, if for example the music in the file + should be a cover of a previously released song. + + TEXT + The 'Lyricist/Text writer' frame is intended for the writer of the + text or lyrics in the recording. + + TOLY + The 'Original lyricist/text writer' frame is intended for the + text writer of the original recording, if for example the music in + the file should be a cover of a previously released song. + + TCOM + The 'Composer' frame is intended for the name of the composer. + + TMCL + The 'Musician credits list' is intended as a mapping between + instruments and the musician that played it. Every odd field is an + instrument and every even is an artist or a comma delimited list of + artists. + + TIPL + The 'Involved people list' is very similar to the musician credits + list, but maps between functions, like producer, and names. + + TENC + The 'Encoded by' frame contains the name of the person or + organisation that encoded the audio file. This field may contain a + copyright message, if the audio file also is copyrighted by the + encoder. + + +4.2.3. Derived and subjective properties frames + + TBPM + The 'BPM' frame contains the number of beats per minute in the + main part of the audio. The BPM is an integer and represented as a + numerical string. + + TLEN + The 'Length' frame contains the length of the audio file in + milliseconds, represented as a numeric string. + + TKEY + The 'Initial key' frame contains the musical key in which the sound + starts. It is represented as a string with a maximum length of three + characters. The ground keys are represented with "A","B","C","D","E", + "F" and "G" and halfkeys represented with "b" and "#". Minor is + represented as "m", e.g. "Dbm" $00. Off key is represented with an + "o" only. + + TLAN + The 'Language' frame should contain the languages of the text or + lyrics spoken or sung in the audio. The language is represented with + three characters according to ISO-639-2 [ISO-639-2]. If more than one + language is used in the text their language codes should follow + according to the amount of their usage, e.g. "eng" $00 "sve" $00. + + TCON + The 'Content type', which ID3v1 was stored as a one byte numeric + value only, is now a string. You may use one or several of the ID3v1 + types as numerical strings, or, since the category list would be + impossible to maintain with accurate and up to date categories, + define your own. Example: "21" $00 "Eurodisco" $00 + + You may also use any of the following keywords: + + RX Remix + CR Cover + + TFLT + The 'File type' frame indicates which type of audio this tag defines. + The following types and refinements are defined: + + MIME MIME type follows + MPG MPEG Audio + /1 MPEG 1/2 layer I + /2 MPEG 1/2 layer II + /3 MPEG 1/2 layer III + /2.5 MPEG 2.5 + /AAC Advanced audio compression + VQF Transform-domain Weighted Interleave Vector Quantisation + PCM Pulse Code Modulated audio + + but other types may be used, but not for these types though. This is + used in a similar way to the predefined types in the "TMED" frame, + but without parentheses. If this frame is not present audio type is + assumed to be "MPG". + + TMED + The 'Media type' frame describes from which media the sound + originated. This may be a text string or a reference to the + predefined media types found in the list below. Example: + "VID/PAL/VHS" $00. + + DIG Other digital media + /A Analogue transfer from media + + ANA Other analogue media + /WAC Wax cylinder + /8CA 8-track tape cassette + + CD CD + /A Analogue transfer from media + /DD DDD + /AD ADD + /AA AAD + + LD Laserdisc + + TT Turntable records + /33 33.33 rpm + /45 45 rpm + /71 71.29 rpm + /76 76.59 rpm + /78 78.26 rpm + /80 80 rpm + + MD MiniDisc + /A Analogue transfer from media + + DAT DAT + /A Analogue transfer from media + /1 standard, 48 kHz/16 bits, linear + /2 mode 2, 32 kHz/16 bits, linear + /3 mode 3, 32 kHz/12 bits, non-linear, low speed + /4 mode 4, 32 kHz/12 bits, 4 channels + /5 mode 5, 44.1 kHz/16 bits, linear + /6 mode 6, 44.1 kHz/16 bits, 'wide track' play + + DCC DCC + /A Analogue transfer from media + + DVD DVD + /A Analogue transfer from media + + TV Television + /PAL PAL + /NTSC NTSC + /SECAM SECAM + + VID Video + /PAL PAL + /NTSC NTSC + /SECAM SECAM + /VHS VHS + /SVHS S-VHS + /BETA BETAMAX + + RAD Radio + /FM FM + /AM AM + /LW LW + /MW MW + + TEL Telephone + /I ISDN + + MC MC (normal cassette) + /4 4.75 cm/s (normal speed for a two sided cassette) + /9 9.5 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + REE Reel + /9 9.5 cm/s + /19 19 cm/s + /38 38 cm/s + /76 76 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + TMOO + The 'Mood' frame is intended to reflect the mood of the audio with a + few keywords, e.g. "Romantic" or "Sad". + + +4.2.4. Rights and license frames + + TCOP + The 'Copyright message' frame, in which the string must begin with a + year and a space character (making five characters), is intended for + the copyright holder of the original sound, not the audio file + itself. The absence of this frame means only that the copyright + information is unavailable or has been removed, and must not be + interpreted to mean that the audio is public domain. Every time this + field is displayed the field must be preceded with "Copyright " (C) " + ", where (C) is one character showing a C in a circle. + + TPRO + The 'Produced notice' frame, in which the string must begin with a + year and a space character (making five characters), is intended for + the production copyright holder of the original sound, not the audio + file itself. The absence of this frame means only that the production + copyright information is unavailable or has been removed, and must + not be interpreted to mean that the audio is public domain. Every + time this field is displayed the field must be preceded with + "Produced " (P) " ", where (P) is one character showing a P in a + circle. + + TPUB + The 'Publisher' frame simply contains the name of the label or + publisher. + + TOWN + The 'File owner/licensee' frame contains the name of the owner or + licensee of the file and it's contents. + + TRSN + The 'Internet radio station name' frame contains the name of the + internet radio station from which the audio is streamed. + + TRSO + The 'Internet radio station owner' frame contains the name of the + owner of the internet radio station from which the audio is + streamed. + +4.2.5. Other text frames + + TOFN + The 'Original filename' frame contains the preferred filename for the + file, since some media doesn't allow the desired length of the + filename. The filename is case sensitive and includes its suffix. + + TDLY + The 'Playlist delay' defines the numbers of milliseconds of silence + that should be inserted before this audio. The value zero indicates + that this is a part of a multifile audio track that should be played + continuously. + + TDEN + The 'Encoding time' frame contains a timestamp describing when the + audio was encoded. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TDOR + The 'Original release time' frame contains a timestamp describing + when the original recording of the audio was released. Timestamp + format is described in the ID3v2 structure document [ID3v2-strct]. + + TDRC + The 'Recording time' frame contains a timestamp describing when the + audio was recorded. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TDRL + The 'Release time' frame contains a timestamp describing when the + audio was first released. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TDTG + The 'Tagging time' frame contains a timestamp describing then the + audio was tagged. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TSSE + The 'Software/Hardware and settings used for encoding' frame + includes the used audio encoder and its settings when the file was + encoded. Hardware refers to hardware encoders, not the computer on + which a program was run. + + TSOA + The 'Album sort order' frame defines a string which should be used + instead of the album name (TALB) for sorting purposes. E.g. an album + named "A Soundtrack" might preferably be sorted as "Soundtrack". + + TSOP + The 'Performer sort order' frame defines a string which should be + used instead of the performer (TPE2) for sorting purposes. + + TSOT + The 'Title sort order' frame defines a string which should be used + instead of the title (TIT2) for sorting purposes. + + +4.2.6. User defined text information frame + + This frame is intended for one-string text information concerning the + audio file in a similar way to the other "T"-frames. The frame body + consists of a description of the string, represented as a terminated + string, followed by the actual string. There may be more than one + "TXXX" frame in each tag, but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + Value + + +4.3. URL link frames + + With these frames dynamic data such as webpages with touring + information, price information or plain ordinary news can be added to + the tag. There may only be one URL [URL] link frame of its kind in an + tag, except when stated otherwise in the frame description. If the + text string is followed by a string termination, all the following + information should be ignored and not be displayed. All URL link + frame identifiers begins with "W". Only URL link frame identifiers + begins with "W", except for "WXXX". All URL link frames have the + following format: + +
+ URL + + +4.3.1. URL link frames - details + + WCOM + The 'Commercial information' frame is a URL pointing at a webpage + with information such as where the album can be bought. There may be + more than one "WCOM" frame in a tag, but not with the same content. + + WCOP + The 'Copyright/Legal information' frame is a URL pointing at a + webpage where the terms of use and ownership of the file is + described. + + WOAF + The 'Official audio file webpage' frame is a URL pointing at a file + specific webpage. + + WOAR + The 'Official artist/performer webpage' frame is a URL pointing at + the artists official webpage. There may be more than one "WOAR" frame + in a tag if the audio contains more than one performer, but not with + the same content. + + WOAS + The 'Official audio source webpage' frame is a URL pointing at the + official webpage for the source of the audio file, e.g. a movie. + + WORS + The 'Official Internet radio station homepage' contains a URL + pointing at the homepage of the internet radio station. + + WPAY + The 'Payment' frame is a URL pointing at a webpage that will handle + the process of paying for this file. + + WPUB + The 'Publishers official webpage' frame is a URL pointing at the + official webpage for the publisher. + + +4.3.2. User defined URL link frame + + This frame is intended for URL [URL] links concerning the audio file + in a similar way to the other "W"-frames. The frame body consists + of a description of the string, represented as a terminated string, + followed by the actual URL. The URL is always encoded with ISO-8859-1 + [ISO-8859-1]. There may be more than one "WXXX" frame in each tag, + but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + URL + + +4.4. Music CD identifier + + This frame is intended for music that comes from a CD, so that the CD + can be identified in databases such as the CDDB [CDDB]. The frame + consists of a binary dump of the Table Of Contents, TOC, from the CD, + which is a header of 4 bytes and then 8 bytes/track on the CD plus 8 + bytes for the 'lead out', making a maximum of 804 bytes. The offset + to the beginning of every track on the CD should be described with a + four bytes absolute CD-frame address per track, and not with absolute + time. When this frame is used the presence of a valid "TRCK" frame is + REQUIRED, even if the CD's only got one track. It is recommended that + this frame is always added to tags originating from CDs. There may + only be one "MCDI" frame in each tag. + +
+ CD TOC + + +4.5. Event timing codes + + This frame allows synchronisation with key events in the audio. The + header is: + +
+ Time stamp format $xx + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Absolute time means that every stamp contains the time from the + beginning of the file. + + Followed by a list of key events in the following format: + + Type of event $xx + Time stamp $xx (xx ...) + + The 'Time stamp' is set to zero if directly at the beginning of the + sound or after the previous event. All events MUST be sorted in + chronological order. The type of event is as follows: + + $00 padding (has no meaning) + $01 end of initial silence + $02 intro start + $03 main part start + $04 outro start + $05 outro end + $06 verse start + $07 refrain start + $08 interlude start + $09 theme start + $0A variation start + $0B key change + $0C time change + $0D momentary unwanted noise (Snap, Crackle & Pop) + $0E sustained noise + $0F sustained noise end + $10 intro end + $11 main part end + $12 verse end + $13 refrain end + $14 theme end + $15 profanity + $16 profanity end + + $17-$DF reserved for future use + + $E0-$EF not predefined synch 0-F + + $F0-$FC reserved for future use + + $FD audio end (start of silence) + $FE audio file ends + $FF one more byte of events follows (all the following bytes with + the value $FF have the same function) + + Terminating the start events such as "intro start" is OPTIONAL. The + 'Not predefined synch's ($E0-EF) are for user events. You might want + to synchronise your music to something, like setting off an explosion + on-stage, activating a screensaver etc. + + There may only be one "ETCO" frame in each tag. + + +4.6. MPEG location lookup table + + To increase performance and accuracy of jumps within a MPEG [MPEG] + audio file, frames with time codes in different locations in the file + might be useful. This ID3v2 frame includes references that the + software can use to calculate positions in the file. After the frame + header follows a descriptor of how much the 'frame counter' should be + increased for every reference. If this value is two then the first + reference points out the second frame, the 2nd reference the 4th + frame, the 3rd reference the 6th frame etc. In a similar way the + 'bytes between reference' and 'milliseconds between reference' points + out bytes and milliseconds respectively. + + Each reference consists of two parts; a certain number of bits, as + defined in 'bits for bytes deviation', that describes the difference + between what is said in 'bytes between reference' and the reality and + a certain number of bits, as defined in 'bits for milliseconds + deviation', that describes the difference between what is said in + 'milliseconds between reference' and the reality. The number of bits + in every reference, i.e. 'bits for bytes deviation'+'bits for + milliseconds deviation', must be a multiple of four. There may only + be one "MLLT" frame in each tag. + +
+ MPEG frames between reference $xx xx + Bytes between reference $xx xx xx + Milliseconds between reference $xx xx xx + Bits for bytes deviation $xx + Bits for milliseconds dev. $xx + + Then for every reference the following data is included; + + Deviation in bytes %xxx.... + Deviation in milliseconds %xxx.... + + +4.7. Synchronised tempo codes + + For a more accurate description of the tempo of a musical piece, this + frame might be used. After the header follows one byte describing + which time stamp format should be used. Then follows one or more + tempo codes. Each tempo code consists of one tempo part and one time + part. The tempo is in BPM described with one or two bytes. If the + first byte has the value $FF, one more byte follows, which is added + to the first giving a range from 2 - 510 BPM, since $00 and $01 is + reserved. $00 is used to describe a beat-free time period, which is + not the same as a music-free time period. $01 is used to indicate one + single beat-stroke followed by a beat-free period. + + The tempo descriptor is followed by a time stamp. Every time the + tempo in the music changes, a tempo descriptor may indicate this for + the player. All tempo descriptors MUST be sorted in chronological + order. The first beat-stroke in a time-period is at the same time as + the beat description occurs. There may only be one "SYTC" frame in + each tag. + +
+ Time stamp format $xx + Tempo data + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Absolute time means that every stamp contains the time from the + beginning of the file. + + +4.8. Unsynchronised lyrics/text transcription + + This frame contains the lyrics of the song or a text transcription of + other vocal activities. The head includes an encoding descriptor and + a content descriptor. The body consists of the actual text. The + 'Content descriptor' is a terminated string. If no descriptor is + entered, 'Content descriptor' is $00 (00) only. Newline characters + are allowed in the text. There may be more than one 'Unsynchronised + lyrics/text transcription' frame in each tag, but only one with the + same language and content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Content descriptor $00 (00) + Lyrics/text + + +4.9. Synchronised lyrics/text + + This is another way of incorporating the words, said or sung lyrics, + in the audio file as text, this time, however, in sync with the + audio. It might also be used to describing events e.g. occurring on a + stage or on the screen in sync with the audio. The header includes a + content descriptor, represented with as terminated text string. If no + descriptor is entered, 'Content descriptor' is $00 (00) only. + +
+ Text encoding $xx + Language $xx xx xx + Time stamp format $xx + Content type $xx + Content descriptor $00 (00) + + Content type: $00 is other + $01 is lyrics + $02 is text transcription + $03 is movement/part name (e.g. "Adagio") + $04 is events (e.g. "Don Quijote enters the stage") + $05 is chord (e.g. "Bb F Fsus") + $06 is trivia/'pop up' information + $07 is URLs to webpages + $08 is URLs to images + + Time stamp format: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Absolute time means that every stamp contains the time from the + beginning of the file. + + The text that follows the frame header differs from that of the + unsynchronised lyrics/text transcription in one major way. Each + syllable (or whatever size of text is considered to be convenient by + the encoder) is a null terminated string followed by a time stamp + denoting where in the sound file it belongs. Each sync thus has the + following structure: + + Terminated text to be synced (typically a syllable) + Sync identifier (terminator to above string) $00 (00) + Time stamp $xx (xx ...) + + The 'time stamp' is set to zero or the whole sync is omitted if + located directly at the beginning of the sound. All time stamps + should be sorted in chronological order. The sync can be considered + as a validator of the subsequent string. + + Newline characters are allowed in all "SYLT" frames and MUST be used + after every entry (name, event etc.) in a frame with the content type + $03 - $04. + + A few considerations regarding whitespace characters: Whitespace + separating words should mark the beginning of a new word, thus + occurring in front of the first syllable of a new word. This is also + valid for new line characters. A syllable followed by a comma should + not be broken apart with a sync (both the syllable and the comma + should be before the sync). + + An example: The "USLT" passage + + "Strangers in the night" $0A "Exchanging glances" + + would be "SYLT" encoded as: + + "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx + " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx + xx "glan" $00 xx xx "ces" $00 xx xx + + There may be more than one "SYLT" frame in each tag, but only one + with the same language and content descriptor. + + +4.10. Comments + + This frame is intended for any kind of full text information that + does not fit in any other frame. It consists of a frame header + followed by encoding, language and content descriptors and is ended + with the actual comment as a text string. Newline characters are + allowed in the comment text string. There may be more than one + comment frame in each tag, but only one with the same language and + content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Short content descrip. $00 (00) + The actual text + + +4.11. Relative volume adjustment (2) + + This is a more subjective frame than the previous ones. It allows the + user to say how much he wants to increase/decrease the volume on each + channel when the file is played. The purpose is to be able to align + all files to a reference volume, so that you don't have to change the + volume constantly. This frame may also be used to balance adjust the + audio. The volume adjustment is encoded as a fixed point decibel + value, 16 bit signed integer representing (adjustment*512), giving + +/- 64 dB with a precision of 0.001953125 dB. E.g. +2 dB is stored as + $04 00 and -2 dB is $FC 00. There may be more than one "RVA2" frame + in each tag, but only one with the same identification string. + +
+ Identification $00 + + The 'identification' string is used to identify the situation and/or + device where this adjustment should apply. The following is then + repeated for every channel + + Type of channel $xx + Volume adjustment $xx xx + Bits representing peak $xx + Peak volume $xx (xx ...) + + + Type of channel: $00 Other + $01 Master volume + $02 Front right + $03 Front left + $04 Back right + $05 Back left + $06 Front centre + $07 Back centre + $08 Subwoofer + + Bits representing peak can be any number between 0 and 255. 0 means + that there is no peak volume field. The peak volume field is always + padded to whole bytes, setting the most significant bits to zero. + + +4.12. Equalisation (2) + + This is another subjective, alignment frame. It allows the user to + predefine an equalisation curve within the audio file. There may be + more than one "EQU2" frame in each tag, but only one with the same + identification string. + +
+ Interpolation method $xx + Identification $00 + + The 'interpolation method' describes which method is preferred when + an interpolation between the adjustment point that follows. The + following methods are currently defined: + + $00 Band + No interpolation is made. A jump from one adjustment level to + another occurs in the middle between two adjustment points. + $01 Linear + Interpolation between adjustment points is linear. + + The 'identification' string is used to identify the situation and/or + device where this adjustment should apply. The following is then + repeated for every adjustment point + + Frequency $xx xx + Volume adjustment $xx xx + + The frequency is stored in units of 1/2 Hz, giving it a range from 0 + to 32767 Hz. + + The volume adjustment is encoded as a fixed point decibel value, 16 + bit signed integer representing (adjustment*512), giving +/- 64 dB + with a precision of 0.001953125 dB. E.g. +2 dB is stored as $04 00 + and -2 dB is $FC 00. + + Adjustment points should be ordered by frequency and one frequency + should only be described once in the frame. + + +4.13. Reverb + + Yet another subjective frame, with which you can adjust echoes of + different kinds. Reverb left/right is the delay between every bounce + in ms. Reverb bounces left/right is the number of bounces that should + be made. $FF equals an infinite number of bounces. Feedback is the + amount of volume that should be returned to the next echo bounce. $00 + is 0%, $FF is 100%. If this value were $7F, there would be 50% volume + reduction on the first bounce, 50% of that on the second and so on. + Left to left means the sound from the left bounce to be played in the + left speaker, while left to right means sound from the left bounce to + be played in the right speaker. + + 'Premix left to right' is the amount of left sound to be mixed in the + right before any reverb is applied, where $00 id 0% and $FF is 100%. + 'Premix right to left' does the same thing, but right to left. + Setting both premix to $FF would result in a mono output (if the + reverb is applied symmetric). There may only be one "RVRB" frame in + each tag. + +
+ Reverb left (ms) $xx xx + Reverb right (ms) $xx xx + Reverb bounces, left $xx + Reverb bounces, right $xx + Reverb feedback, left to left $xx + Reverb feedback, left to right $xx + Reverb feedback, right to right $xx + Reverb feedback, right to left $xx + Premix left to right $xx + Premix right to left $xx + + +4.14. Attached picture + + This frame contains a picture directly related to the audio file. + Image format is the MIME type and subtype [MIME] for the image. In + the event that the MIME media type name is omitted, "image/" will be + implied. The "image/png" [PNG] or "image/jpeg" [JFIF] picture format + should be used when interoperability is wanted. Description is a + short description of the picture, represented as a terminated + text string. There may be several pictures attached to one file, each + in their individual "APIC" frame, but only one with the same content + descriptor. There may only be one picture with the picture type + declared as picture type $01 and $02 respectively. There is the + possibility to put only a link to the image file by using the 'MIME + type' "-->" and having a complete URL [URL] instead of picture data. + The use of linked files should however be used sparingly since there + is the risk of separation of files. + +
+ Text encoding $xx + MIME type $00 + Picture type $xx + Description $00 (00) + Picture data + + + Picture type: $00 Other + $01 32x32 pixels 'file icon' (PNG only) + $02 Other file icon + $03 Cover (front) + $04 Cover (back) + $05 Leaflet page + $06 Media (e.g. label side of CD) + $07 Lead artist/lead performer/soloist + $08 Artist/performer + $09 Conductor + $0A Band/Orchestra + $0B Composer + $0C Lyricist/text writer + $0D Recording Location + $0E During recording + $0F During performance + $10 Movie/video screen capture + $11 A bright coloured fish + $12 Illustration + $13 Band/artist logotype + $14 Publisher/Studio logotype + + +4.15. General encapsulated object + + In this frame any type of file can be encapsulated. After the header, + 'Frame size' and 'Encoding' follows 'MIME type' [MIME] represented as + as a terminated string encoded with ISO 8859-1 [ISO-8859-1]. The + filename is case sensitive and is encoded as 'Encoding'. Then follows + a content description as terminated string, encoded as 'Encoding'. + The last thing in the frame is the actual object. The first two + strings may be omitted, leaving only their terminations. MIME type is + always an ISO-8859-1 text string. There may be more than one "GEOB" + frame in each tag, but only one with the same content descriptor. + +
+ Text encoding $xx + MIME type $00 + Filename $00 (00) + Content description $00 (00) + Encapsulated object + + +4.16. Play counter + + This is simply a counter of the number of times a file has been + played. The value is increased by one every time the file begins to + play. There may only be one "PCNT" frame in each tag. When the + counter reaches all one's, one byte is inserted in front of the + counter thus making the counter eight bits bigger. The counter must + be at least 32-bits long to begin with. + +
+ Counter $xx xx xx xx (xx ...) + + +4.17. Popularimeter + + The purpose of this frame is to specify how good an audio file is. + Many interesting applications could be found to this frame such as a + playlist that features better audio files more often than others or + it could be used to profile a person's taste and find other 'good' + files by comparing people's profiles. The frame contains the email + address to the user, one rating byte and a four byte play counter, + intended to be increased with one for every time the file is played. + The email is a terminated string. The rating is 1-255 where 1 is + worst and 255 is best. 0 is unknown. If no personal counter is wanted + it may be omitted. When the counter reaches all one's, one byte is + inserted in front of the counter thus making the counter eight bits + bigger in the same away as the play counter ("PCNT"). There may be + more than one "POPM" frame in each tag, but only one with the same + email address. + +
+ Email to user $00 + Rating $xx + Counter $xx xx xx xx (xx ...) + + +4.18. Recommended buffer size + + Sometimes the server from which an audio file is streamed is aware of + transmission or coding problems resulting in interruptions in the + audio stream. In these cases, the size of the buffer can be + recommended by the server using this frame. If the 'embedded info + flag' is true (1) then this indicates that an ID3 tag with the + maximum size described in 'Buffer size' may occur in the audio + stream. In such case the tag should reside between two MPEG [MPEG] + frames, if the audio is MPEG encoded. If the position of the next tag + is known, 'offset to next tag' may be used. The offset is calculated + from the end of tag in which this frame resides to the first byte of + the header in the next. This field may be omitted. Embedded tags are + generally not recommended since this could render unpredictable + behaviour from present software/hardware. + + For applications like streaming audio it might be an idea to embed + tags into the audio stream though. If the clients connects to + individual connections like HTTP and there is a possibility to begin + every transmission with a tag, then this tag should include a + 'recommended buffer size' frame. If the client is connected to a + arbitrary point in the stream, such as radio or multicast, then the + 'recommended buffer size' frame SHOULD be included in every tag. + + The 'Buffer size' should be kept to a minimum. There may only be one + "RBUF" frame in each tag. + +
+ Buffer size $xx xx xx + Embedded info flag %0000000x + Offset to next tag $xx xx xx xx + + +4.19. Audio encryption + + This frame indicates if the actual audio stream is encrypted, and by + whom. Since standardisation of such encryption scheme is beyond this + document, all "AENC" frames begin with a terminated string with a + URL containing an email address, or a link to a location where an + email address can be found, that belongs to the organisation + responsible for this specific encrypted audio file. Questions + regarding the encrypted audio should be sent to the email address + specified. If a $00 is found directly after the 'Frame size' and the + audio file indeed is encrypted, the whole file may be considered + useless. + + After the 'Owner identifier', a pointer to an unencrypted part of the + audio can be specified. The 'Preview start' and 'Preview length' is + described in frames. If no part is unencrypted, these fields should + be left zeroed. After the 'preview length' field follows optionally a + data block required for decryption of the audio. There may be more + than one "AENC" frames in a tag, but only one with the same 'Owner + identifier'. + +
+ Owner identifier $00 + Preview start $xx xx + Preview length $xx xx + Encryption info + + +4.20. Linked information + + To keep information duplication as low as possible this frame may be + used to link information from another ID3v2 tag that might reside in + another audio file or alone in a binary file. It is RECOMMENDED that + this method is only used when the files are stored on a CD-ROM or + other circumstances when the risk of file separation is low. The + frame contains a frame identifier, which is the frame that should be + linked into this tag, a URL [URL] field, where a reference to the + file where the frame is given, and additional ID data, if needed. + Data should be retrieved from the first tag found in the file to + which this link points. There may be more than one "LINK" frame in a + tag, but only one with the same contents. A linked frame is to be + considered as part of the tag and has the same restrictions as if it + was a physical part of the tag (i.e. only one "RVRB" frame allowed, + whether it's linked or not). + +
+ Frame identifier $xx xx xx xx + URL $00 + ID and additional data + + Frames that may be linked and need no additional data are "ASPI", + "ETCO", "EQU2", "MCID", "MLLT", "OWNE", "RVA2", "RVRB", "SYTC", the + text information frames and the URL link frames. + + The "AENC", "APIC", "GEOB" and "TXXX" frames may be linked with + the content descriptor as additional ID data. + + The "USER" frame may be linked with the language field as additional + ID data. + + The "PRIV" frame may be linked with the owner identifier as + additional ID data. + + The "COMM", "SYLT" and "USLT" frames may be linked with three bytes + of language descriptor directly followed by a content descriptor as + additional ID data. + + +4.21. Position synchronisation frame + + This frame delivers information to the listener of how far into the + audio stream he picked up; in effect, it states the time offset from + the first frame in the stream. The frame layout is: + + + Time stamp format $xx + Position $xx (xx ...) + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + and position is where in the audio the listener starts to receive, + i.e. the beginning of the next frame. If this frame is used in the + beginning of a file the value is always 0. There may only be one + "POSS" frame in each tag. + + +4.22. Terms of use frame + + This frame contains a brief description of the terms of use and + ownership of the file. More detailed information concerning the legal + terms might be available through the "WCOP" frame. Newlines are + allowed in the text. There may be more than one 'Terms of use' frame + in a tag, but only one with the same 'Language'. + +
+ Text encoding $xx + Language $xx xx xx + The actual text + + +4.23. Ownership frame + + The ownership frame might be used as a reminder of a made transaction + or, if signed, as proof. Note that the "USER" and "TOWN" frames are + good to use in conjunction with this one. The frame begins, after the + frame ID, size and encoding fields, with a 'price paid' field. The + first three characters of this field contains the currency used for + the transaction, encoded according to ISO 4217 [ISO-4217] alphabetic + currency code. Concatenated to this is the actual price paid, as a + numerical string using "." as the decimal separator. Next is an 8 + character date string (YYYYMMDD) followed by a string with the name + of the seller as the last field in the frame. There may only be one + "OWNE" frame in a tag. + +
+ Text encoding $xx + Price paid $00 + Date of purch. + Seller + + +4.24. Commercial frame + + This frame enables several competing offers in the same tag by + bundling all needed information. That makes this frame rather complex + but it's an easier solution than if one tries to achieve the same + result with several frames. The frame begins, after the frame ID, + size and encoding fields, with a price string field. A price is + constructed by one three character currency code, encoded according + to ISO 4217 [ISO-4217] alphabetic currency code, followed by a + numerical value where "." is used as decimal separator. In the price + string several prices may be concatenated, separated by a "/" + character, but there may only be one currency of each type. + + The price string is followed by an 8 character date string in the + format YYYYMMDD, describing for how long the price is valid. After + that is a contact URL, with which the user can contact the seller, + followed by a one byte 'received as' field. It describes how the + audio is delivered when bought according to the following list: + + $00 Other + $01 Standard CD album with other songs + $02 Compressed audio on CD + $03 File over the Internet + $04 Stream over the Internet + $05 As note sheets + $06 As note sheets in a book with other sheets + $07 Music on other media + $08 Non-musical merchandise + + Next follows a terminated string with the name of the seller followed + by a terminated string with a short description of the product. The + last thing is the ability to include a company logotype. The first of + them is the 'Picture MIME type' field containing information about + which picture format is used. In the event that the MIME media type + name is omitted, "image/" will be implied. Currently only "image/png" + and "image/jpeg" are allowed. This format string is followed by the + binary picture data. This two last fields may be omitted if no + picture is attached. There may be more than one 'commercial frame' in + a tag, but no two may be identical. + +
+ Text encoding $xx + Price string $00 + Valid until + Contact URL $00 + Received as $xx + Name of seller $00 (00) + Description $00 (00) + Picture MIME type $00 + Seller logo + + +4.25. Encryption method registration + + To identify with which method a frame has been encrypted the + encryption method must be registered in the tag with this frame. The + 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for this specific encryption method. Questions regarding the + encryption method should be sent to the indicated email address. The + 'Method symbol' contains a value that is associated with this method + throughout the whole tag, in the range $80-F0. All other values are + reserved. The 'Method symbol' may optionally be followed by + encryption specific data. There may be several "ENCR" frames in a tag + but only one containing the same symbol and only one containing the + same owner identifier. The method must be used somewhere in the tag. + See the description of the frame encryption flag in the ID3v2 + structure document [ID3v2-strct] for more information. + +
+ Owner identifier $00 + Method symbol $xx + Encryption data + + +4.26. Group identification registration + + This frame enables grouping of otherwise unrelated frames. This can + be used when some frames are to be signed. To identify which frames + belongs to a set of frames a group identifier must be registered in + the tag with this frame. The 'Owner identifier' is a null-terminated + string with a URL [URL] containing an email address, or a link to a + location where an email address can be found, that belongs to the + organisation responsible for this grouping. Questions regarding the + grouping should be sent to the indicated email address. The 'Group + symbol' contains a value that associates the frame with this group + throughout the whole tag, in the range $80-F0. All other values are + reserved. The 'Group symbol' may optionally be followed by some group + specific data, e.g. a digital signature. There may be several "GRID" + frames in a tag but only one containing the same symbol and only one + containing the same owner identifier. The group symbol must be used + somewhere in the tag. See the description of the frame grouping flag + in the ID3v2 structure document [ID3v2-strct] for more information. + +
+ Owner identifier $00 + Group symbol $xx + Group dependent data + + +4.27. Private frame + + This frame is used to contain information from a software producer + that its program uses and does not fit into the other frames. The + frame consists of an 'Owner identifier' string and the binary data. + The 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for the frame. Questions regarding the frame should be sent to the + indicated email address. The tag may contain more than one "PRIV" + frame but only with different contents. + +
+ Owner identifier $00 + The private data + + +4.28. Signature frame + + This frame enables a group of frames, grouped with the 'Group + identification registration', to be signed. Although signatures can + reside inside the registration frame, it might be desired to store + the signature elsewhere, e.g. in watermarks. There may be more than + one 'signature frame' in a tag, but no two may be identical. + +
+ Group symbol $xx + Signature + + +4.29. Seek frame + + This frame indicates where other tags in a file/stream can be found. + The 'minimum offset to next tag' is calculated from the end of this + tag to the beginning of the next. There may only be one 'seek frame' + in a tag. + +
+ Minimum offset to next tag $xx xx xx xx + + +4.30. Audio seek point index + + Audio files with variable bit rates are intrinsically difficult to + deal with in the case of seeking within the file. The ASPI frame + makes seeking easier by providing a list a seek points within the + audio file. The seek points are a fractional offset within the audio + data, providing a starting point from which to find an appropriate + point to start decoding. The presence of an ASPI frame requires the + existence of a TLEN frame, indicating the duration of the file in + milliseconds. There may only be one 'audio seek point index' frame in + a tag. + +
+ Indexed data start (S) $xx xx xx xx + Indexed data length (L) $xx xx xx xx + Number of index points (N) $xx xx + Bits per index point (b) $xx + + Then for every index point the following data is included; + + Fraction at index (Fi) $xx (xx) + + 'Indexed data start' is a byte offset from the beginning of the file. + 'Indexed data length' is the byte length of the audio data being + indexed. 'Number of index points' is the number of index points, as + the name implies. The recommended number is 100. 'Bits per index + point' is 8 or 16, depending on the chosen precision. 8 bits works + well for short files (less than 5 minutes of audio), while 16 bits is + advantageous for long files. 'Fraction at index' is the numerator of + the fraction representing a relative position in the data. The + denominator is 2 to the power of b. + + Here are the algorithms to be used in the calculation. The known data + must be the offset of the start of the indexed data (S), the offset + of the end of the indexed data (E), the number of index points (N), + the offset at index i (Oi). We calculate the fraction at index i + (Fi). + + Oi is the offset of the frame whose start is soonest after the point + for which the time offset is (i/N * duration). + + The frame data should be calculated as follows: + + Fi = Oi/L * 2^b (rounded down to the nearest integer) + + Offset calculation should be calculated as follows from data in the + frame: + + Oi = (Fi/2^b)*L (rounded up to the nearest integer) + + +5. Copyright + + Copyright (C) Martin Nilsson 2000. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + "AS IS" basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +6. References + + [CDDB] Compact Disc Data Base + + + + [ID3v2.3.0] Martin Nilsson, "ID3v2 informal standard". + + + + [ID3v2-strct] Martin Nilsson, + "ID3 tag version 2.4.0 - Main Structure" + + + + [ISO-639-2] ISO/FDIS 639-2. + Codes for the representation of names of languages, Part 2: Alpha-3 + code. Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-4217] ISO 4217:1995. + Codes for the representation of currencies and funds. + Technical committee / subcommittee: TC 68 + + [ISO-8859-1] ISO/IEC DIS 8859-1. + 8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1. Technical committee / subcommittee: JTC 1 / SC 2 + + [ISRC] ISO 3901:1986 + International Standard Recording Code (ISRC). + Technical committee / subcommittee: TC 46 / SC 9 + + [JFIF] JPEG File Interchange Format, version 1.02 + + + + [KEYWORDS] S. Bradner, 'Key words for use in RFCs to Indicate + Requirement Levels', RFC 2119, March 1997. + + + + [MIME] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message Bodies", + RFC 2045, November 1996. + + + + [MPEG] ISO/IEC 11172-3:1993. + Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + Generic coding of moving pictures and associated audio information, + Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995) + + + [PNG] Portable Network Graphics, version 1.0 + + + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, "Uniform Resource + Locators (URL).", RFC 1738, December 1994. + + + + [ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, "ZLIB + Compressed + Data Format Specification version 3.3", RFC 1950, May 1996. + + + + +7. Appendix + + +A. Appendix A - Genre List from ID3v1 + + The following genres is defined in ID3v1 + + 0.Blues + 1.Classic Rock + 2.Country + 3.Dance + 4.Disco + 5.Funk + 6.Grunge + 7.Hip-Hop + 8.Jazz + 9.Metal + 10.New Age + 11.Oldies + 12.Other + 13.Pop + 14.R&B + 15.Rap + 16.Reggae + 17.Rock + 18.Techno + 19.Industrial + 20.Alternative + 21.Ska + 22.Death Metal + 23.Pranks + 24.Soundtrack + 25.Euro-Techno + 26.Ambient + 27.Trip-Hop + 28.Vocal + 29.Jazz+Funk + 30.Fusion + 31.Trance + 32.Classical + 33.Instrumental + 34.Acid + 35.House + 36.Game + 37.Sound Clip + 38.Gospel + 39.Noise + 40.AlternRock + 41.Bass + 42.Soul + 43.Punk + 44.Space + 45.Meditative + 46.Instrumental Pop + 47.Instrumental Rock + 48.Ethnic + 49.Gothic + 50.Darkwave + 51.Techno-Industrial + 52.Electronic + 53.Pop-Folk + 54.Eurodance + 55.Dream + 56.Southern Rock + 57.Comedy + 58.Cult + 59.Gangsta + 60.Top 40 + 61.Christian Rap + 62.Pop/Funk + 63.Jungle + 64.Native American + 65.Cabaret + 66.New Wave + 67.Psychadelic + 68.Rave + 69.Showtunes + 70.Trailer + 71.Lo-Fi + 72.Tribal + 73.Acid Punk + 74.Acid Jazz + 75.Polka + 76.Retro + 77.Musical + 78.Rock & Roll + 79.Hard Rock + + +8. Author's Address + + Written by + + Martin Nilsson + Rydsvägen 246 C. 30 + SE-584 34 Linköping + Sweden + + Email: nilsson@id3.org diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-structure.txt b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-structure.txt new file mode 100644 index 00000000..5fa156a0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2.4.0-structure.txt @@ -0,0 +1,733 @@ + +Informal standard M. Nilsson +Document: id3v2.4.0-structure.txt 16 September 2001 + + + ID3 tag version 2.4.0 - Main Structure + +Status of this document + + This document is an informal standard and replaces the ID3v2.3.0 + standard [ID3v2]. A formal standard will use another revision number + even if the content is identical to document. The contents in this + document may change for clarifications but never for added or altered + functionallity. + + Distribution of this document is unlimited. + + +Abstract + + This document describes the main structure of ID3v2.4.0, which is a + revised version of the ID3v2 informal standard [ID3v2] version + 2.3.0. The ID3v2 offers a flexible way of storing audio meta + information within the audio file itself. The information may be + technical information, such as equalisation curves, as well as + title, performer, copyright etc. + + ID3v2.4.0 is meant to be as close as possible to ID3v2.3.0 in order + to allow for implementations to be revised as easily as possible. + + +1. Table of contents + + Status of this document + Abstract + 1. Table of contents + 2. Conventions in this document + 2. Standard overview + 3. ID3v2 overview + 3.1. ID3v2 header + 3.2. ID3v2 extended header + 3.3. Padding + 3.4. ID3v2 footer + 4. ID3v2 frames overview + 4.1. Frame header flags + 4.1.1. Frame status flags + 4.1.2. Frame format flags + 5. Tag location + 6. Unsynchronisation + 6.1. The unsynchronisation scheme + 6.2. Synchsafe integers + 7. Copyright + 8. References + 9. Author's Address + + +2. Conventions in this document + + Text within "" is a text string exactly as it appears in a tag. + Numbers preceded with $ are hexadecimal and numbers preceded with % + are binary. $xx is used to indicate a byte with unknown content. %x + is used to indicate a bit with unknown content. The most significant + bit (MSB) of a byte is called 'bit 7' and the least significant bit + (LSB) is called 'bit 0'. + + A tag is the whole tag described in this document. A frame is a block + of information in the tag. The tag consists of a header, frames and + optional padding. A field is a piece of information; one value, a + string etc. A numeric string is a string that consists of the + characters "0123456789" only. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119 [KEYWORDS]. + + +3. ID3v2 overview + + ID3v2 is a general tagging format for audio, which makes it possible + to store meta data about the audio inside the audio file itself. The + ID3 tag described in this document is mainly targeted at files + encoded with MPEG-1/2 layer I, MPEG-1/2 layer II, MPEG-1/2 layer III + and MPEG-2.5, but may work with other types of encoded audio or as a + stand alone format for audio meta data. + + ID3v2 is designed to be as flexible and expandable as possible to + meet new meta information needs that might arise. To achieve that + ID3v2 is constructed as a container for several information blocks, + called frames, whose format need not be known to the software that + encounters them. At the start of every frame is an unique and + predefined identifier, a size descriptor that allows software to skip + unknown frames and a flags field. The flags describes encoding + details and if the frame should remain in the tag, should it be + unknown to the software, if the file is altered. + + The bitorder in ID3v2 is most significant bit first (MSB). The + byteorder in multibyte numbers is most significant byte first (e.g. + $12345678 would be encoded $12 34 56 78), also known as big endian + and network byte order. + + Overall tag structure: + + +-----------------------------+ + | Header (10 bytes) | + +-----------------------------+ + | Extended Header | + | (variable length, OPTIONAL) | + +-----------------------------+ + | Frames (variable length) | + +-----------------------------+ + | Padding | + | (variable length, OPTIONAL) | + +-----------------------------+ + | Footer (10 bytes, OPTIONAL) | + +-----------------------------+ + + In general, padding and footer are mutually exclusive. See details in + sections 3.3, 3.4 and 5. + + +3.1. ID3v2 header + + The first part of the ID3v2 tag is the 10 byte tag header, laid out + as follows: + + ID3v2/file identifier "ID3" + ID3v2 version $04 00 + ID3v2 flags %abcd0000 + ID3v2 size 4 * %0xxxxxxx + + The first three bytes of the tag are always "ID3", to indicate that + this is an ID3v2 tag, directly followed by the two version bytes. The + first byte of ID3v2 version is its major version, while the second + byte is its revision number. In this case this is ID3v2.4.0. All + revisions are backwards compatible while major versions are not. If + software with ID3v2.4.0 and below support should encounter version + five or higher it should simply ignore the whole tag. Version or + revision will never be $FF. + + The version is followed by the ID3v2 flags field, of which currently + four flags are used. + + + a - Unsynchronisation + + Bit 7 in the 'ID3v2 flags' indicates whether or not + unsynchronisation is applied on all frames (see section 6.1 for + details); a set bit indicates usage. + + + b - Extended header + + The second bit (bit 6) indicates whether or not the header is + followed by an extended header. The extended header is described in + section 3.2. A set bit indicates the presence of an extended + header. + + + c - Experimental indicator + + The third bit (bit 5) is used as an 'experimental indicator'. This + flag SHALL always be set when the tag is in an experimental stage. + + + d - Footer present + + Bit 4 indicates that a footer (section 3.4) is present at the very + end of the tag. A set bit indicates the presence of a footer. + + + All the other flags MUST be cleared. If one of these undefined flags + are set, the tag might not be readable for a parser that does not + know the flags function. + + The ID3v2 tag size is stored as a 32 bit synchsafe integer (section + 6.2), making a total of 28 effective bits (representing up to 256MB). + + The ID3v2 tag size is the sum of the byte length of the extended + header, the padding and the frames after unsynchronisation. If a + footer is present this equals to ('total size' - 20) bytes, otherwise + ('total size' - 10) bytes. + + An ID3v2 tag can be detected with the following pattern: + $49 44 33 yy yy xx zz zz zz zz + Where yy is less than $FF, xx is the 'flags' byte and zz is less than + $80. + + +3.2. Extended header + + The extended header contains information that can provide further + insight in the structure of the tag, but is not vital to the correct + parsing of the tag information; hence the extended header is + optional. + + Extended header size 4 * %0xxxxxxx + Number of flag bytes $01 + Extended Flags $xx + + Where the 'Extended header size' is the size of the whole extended + header, stored as a 32 bit synchsafe integer. An extended header can + thus never have a size of fewer than six bytes. + + The extended flags field, with its size described by 'number of flag + bytes', is defined as: + + %0bcd0000 + + Each flag that is set in the extended header has data attached, which + comes in the order in which the flags are encountered (i.e. the data + for flag 'b' comes before the data for flag 'c'). Unset flags cannot + have any attached data. All unknown flags MUST be unset and their + corresponding data removed when a tag is modified. + + Every set flag's data starts with a length byte, which contains a + value between 0 and 127 ($00 - $7f), followed by data that has the + field length indicated by the length byte. If a flag has no attached + data, the value $00 is used as length byte. + + + b - Tag is an update + + If this flag is set, the present tag is an update of a tag found + earlier in the present file or stream. If frames defined as unique + are found in the present tag, they are to override any + corresponding ones found in the earlier tag. This flag has no + corresponding data. + + Flag data length $00 + + c - CRC data present + + If this flag is set, a CRC-32 [ISO-3309] data is included in the + extended header. The CRC is calculated on all the data between the + header and footer as indicated by the header's tag length field, + minus the extended header. Note that this includes the padding (if + there is any), but excludes the footer. The CRC-32 is stored as an + 35 bit synchsafe integer, leaving the upper four bits always + zeroed. + + Flag data length $05 + Total frame CRC 5 * %0xxxxxxx + + d - Tag restrictions + + For some applications it might be desired to restrict a tag in more + ways than imposed by the ID3v2 specification. Note that the + presence of these restrictions does not affect how the tag is + decoded, merely how it was restricted before encoding. If this flag + is set the tag is restricted as follows: + + Flag data length $01 + Restrictions %ppqrrstt + + p - Tag size restrictions + + 00 No more than 128 frames and 1 MB total tag size. + 01 No more than 64 frames and 128 KB total tag size. + 10 No more than 32 frames and 40 KB total tag size. + 11 No more than 32 frames and 4 KB total tag size. + + q - Text encoding restrictions + + 0 No restrictions + 1 Strings are only encoded with ISO-8859-1 [ISO-8859-1] or + UTF-8 [UTF-8]. + + r - Text fields size restrictions + + 00 No restrictions + 01 No string is longer than 1024 characters. + 10 No string is longer than 128 characters. + 11 No string is longer than 30 characters. + + Note that nothing is said about how many bytes is used to + represent those characters, since it is encoding dependent. If a + text frame consists of more than one string, the sum of the + strungs is restricted as stated. + + s - Image encoding restrictions + + 0 No restrictions + 1 Images are encoded only with PNG [PNG] or JPEG [JFIF]. + + t - Image size restrictions + + 00 No restrictions + 01 All images are 256x256 pixels or smaller. + 10 All images are 64x64 pixels or smaller. + 11 All images are exactly 64x64 pixels, unless required + otherwise. + + +3.3. Padding + + It is OPTIONAL to include padding after the final frame (at the end + of the ID3 tag), making the size of all the frames together smaller + than the size given in the tag header. A possible purpose of this + padding is to allow for adding a few additional frames or enlarge + existing frames within the tag without having to rewrite the entire + file. The value of the padding bytes must be $00. A tag MUST NOT have + any padding between the frames or between the tag header and the + frames. Furthermore it MUST NOT have any padding when a tag footer is + added to the tag. + + +3.4. ID3v2 footer + + To speed up the process of locating an ID3v2 tag when searching from + the end of a file, a footer can be added to the tag. It is REQUIRED + to add a footer to an appended tag, i.e. a tag located after all + audio data. The footer is a copy of the header, but with a different + identifier. + + ID3v2 identifier "3DI" + ID3v2 version $04 00 + ID3v2 flags %abcd0000 + ID3v2 size 4 * %0xxxxxxx + + +4. ID3v2 frame overview + + All ID3v2 frames consists of one frame header followed by one or more + fields containing the actual information. The header is always 10 + bytes and laid out as follows: + + Frame ID $xx xx xx xx (four characters) + Size 4 * %0xxxxxxx + Flags $xx xx + + The frame ID is made out of the characters capital A-Z and 0-9. + Identifiers beginning with "X", "Y" and "Z" are for experimental + frames and free for everyone to use, without the need to set the + experimental bit in the tag header. Bear in mind that someone else + might have used the same identifier as you. All other identifiers are + either used or reserved for future use. + + The frame ID is followed by a size descriptor containing the size of + the data in the final frame, after encryption, compression and + unsynchronisation. The size is excluding the frame header ('total + frame size' - 10 bytes) and stored as a 32 bit synchsafe integer. + + In the frame header the size descriptor is followed by two flag + bytes. These flags are described in section 4.1. + + There is no fixed order of the frames' appearance in the tag, + although it is desired that the frames are arranged in order of + significance concerning the recognition of the file. An example of + such order: UFID, TIT2, MCDI, TRCK ... + + A tag MUST contain at least one frame. A frame must be at least 1 + byte big, excluding the header. + + If nothing else is said, strings, including numeric strings and URLs + [URL], are represented as ISO-8859-1 [ISO-8859-1] characters in the + range $20 - $FF. Such strings are represented in frame descriptions + as , or if newlines are allowed. If + nothing else is said newline character is forbidden. In ISO-8859-1 a + newline is represented, when allowed, with $0A only. + + Frames that allow different types of text encoding contains a text + encoding description byte. Possible encodings: + + $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00. + $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All + strings in the same frame SHALL have the same byteorder. + Terminated with $00 00. + $02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM. + Terminated with $00 00. + $03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00. + + Strings dependent on encoding are represented in frame descriptions + as , or if newlines are allowed. Any empty strings of + type $01 which are NULL-terminated may have the Unicode BOM followed + by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00). + + The timestamp fields are based on a subset of ISO 8601. When being as + precise as possible the format of a time string is + yyyy-MM-ddTHH:mm:ss (year, "-", month, "-", day, "T", hour (out of + 24), ":", minutes, ":", seconds), but the precision may be reduced by + removing as many time indicators as wanted. Hence valid timestamps + are + yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm and + yyyy-MM-ddTHH:mm:ss. All time stamps are UTC. For durations, use + the slash character as described in 8601, and for multiple non- + contiguous dates, use multiple strings, if allowed by the frame + definition. + + The three byte language field, present in several frames, is used to + describe the language of the frame's content, according to ISO-639-2 + [ISO-639-2]. The language should be represented in lower case. If the + language is not known the string "XXX" should be used. + + All URLs [URL] MAY be relative, e.g. "picture.png", "../doc.txt". + + If a frame is longer than it should be, e.g. having more fields than + specified in this document, that indicates that additions to the + frame have been made in a later version of the ID3v2 standard. This + is reflected by the revision number in the header of the tag. + + +4.1. Frame header flags + + In the frame header the size descriptor is followed by two flag + bytes. All unused flags MUST be cleared. The first byte is for + 'status messages' and the second byte is a format description. If an + unknown flag is set in the first byte the frame MUST NOT be changed + without that bit cleared. If an unknown flag is set in the second + byte the frame is likely to not be readable. Some flags in the second + byte indicates that extra information is added to the header. These + fields of extra information is ordered as the flags that indicates + them. The flags field is defined as follows (l and o left out because + ther resemblence to one and zero): + + %0abc0000 %0h00kmnp + + Some frame format flags indicate that additional information fields + are added to the frame. This information is added after the frame + header and before the frame data in the same order as the flags that + indicates them. I.e. the four bytes of decompressed size will precede + the encryption method byte. These additions affects the 'frame size' + field, but are not subject to encryption or compression. + + The default status flags setting for a frame is, unless stated + otherwise, 'preserved if tag is altered' and 'preserved if file is + altered', i.e. %00000000. + + +4.1.1. Frame status flags + + a - Tag alter preservation + + This flag tells the tag parser what to do with this frame if it is + unknown and the tag is altered in any way. This applies to all + kinds of alterations, including adding more padding and reordering + the frames. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + b - File alter preservation + + This flag tells the tag parser what to do with this frame if it is + unknown and the file, excluding the tag, is altered. This does not + apply when the audio is completely replaced with other audio data. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + c - Read only + + This flag, if set, tells the software that the contents of this + frame are intended to be read only. Changing the contents might + break something, e.g. a signature. If the contents are changed, + without knowledge of why the frame was flagged read only and + without taking the proper means to compensate, e.g. recalculating + the signature, the bit MUST be cleared. + + +4.1.2. Frame format flags + + h - Grouping identity + + This flag indicates whether or not this frame belongs in a group + with other frames. If set, a group identifier byte is added to the + frame. Every frame with the same group identifier belongs to the + same group. + + 0 Frame does not contain group information + 1 Frame contains group information + + + k - Compression + + This flag indicates whether or not the frame is compressed. + A 'Data Length Indicator' byte MUST be included in the frame. + + 0 Frame is not compressed. + 1 Frame is compressed using zlib [zlib] deflate method. + If set, this requires the 'Data Length Indicator' bit + to be set as well. + + + m - Encryption + + This flag indicates whether or not the frame is encrypted. If set, + one byte indicating with which method it was encrypted will be + added to the frame. See description of the ENCR frame for more + information about encryption method registration. Encryption + should be done after compression. Whether or not setting this flag + requires the presence of a 'Data Length Indicator' depends on the + specific algorithm used. + + 0 Frame is not encrypted. + 1 Frame is encrypted. + + n - Unsynchronisation + + This flag indicates whether or not unsynchronisation was applied + to this frame. See section 6 for details on unsynchronisation. + If this flag is set all data from the end of this header to the + end of this frame has been unsynchronised. Although desirable, the + presence of a 'Data Length Indicator' is not made mandatory by + unsynchronisation. + + 0 Frame has not been unsynchronised. + 1 Frame has been unsyrchronised. + + p - Data length indicator + + This flag indicates that a data length indicator has been added to + the frame. The data length indicator is the value one would write + as the 'Frame length' if all of the frame format flags were + zeroed, represented as a 32 bit synchsafe integer. + + 0 There is no Data Length Indicator. + 1 A data length Indicator has been added to the frame. + + +5. Tag location + + The default location of an ID3v2 tag is prepended to the audio so + that players can benefit from the information when the data is + streamed. It is however possible to append the tag, or make a + prepend/append combination. When deciding upon where an unembedded + tag should be located, the following order of preference SHOULD be + considered. + + 1. Prepend the tag. + + 2. Prepend a tag with all vital information and add a second tag at + the end of the file, before tags from other tagging systems. The + first tag is required to have a SEEK frame. + + 3. Add a tag at the end of the file, before tags from other tagging + systems. + + In case 2 and 3 the tag can simply be appended if no other known tags + are present. The suggested method to find ID3v2 tags are: + + 1. Look for a prepended tag using the pattern found in section 3.1. + + 2. If a SEEK frame was found, use its values to guide further + searching. + + 3. Look for a tag footer, scanning from the back of the file. + + For every new tag that is found, the old tag should be discarded + unless the update flag in the extended header (section 3.2) is set. + + +6. Unsynchronisation + + The only purpose of unsynchronisation is to make the ID3v2 tag as + compatible as possible with existing software and hardware. There is + no use in 'unsynchronising' tags if the file is only to be processed + only by ID3v2 aware software and hardware. Unsynchronisation is only + useful with tags in MPEG 1/2 layer I, II and III, MPEG 2.5 and AAC + files. + + +6.1. The unsynchronisation scheme + + Whenever a false synchronisation is found within the tag, one zeroed + byte is inserted after the first false synchronisation byte. The + format of synchronisations that should be altered by ID3 encoders is + as follows: + + %11111111 111xxxxx + + and should be replaced with: + + %11111111 00000000 111xxxxx + + This has the side effect that all $FF 00 combinations have to be + altered, so they will not be affected by the decoding process. + Therefore all the $FF 00 combinations have to be replaced with the + $FF 00 00 combination during the unsynchronisation. + + To indicate usage of the unsynchronisation, the unsynchronisation + flag in the frame header should be set. This bit MUST be set if the + frame was altered by the unsynchronisation and SHOULD NOT be set if + unaltered. If all frames in the tag are unsynchronised the + unsynchronisation flag in the tag header SHOULD be set. It MUST NOT + be set if the tag has a frame which is not unsynchronised. + + Assume the first byte of the audio to be $FF. The special case when + the last byte of the last frame is $FF and no padding nor footer is + used will then introduce a false synchronisation. This can be solved + by adding a footer, adding padding or unsynchronising the frame and + add $00 to the end of the frame data, thus adding more byte to the + frame size than a normal unsynchronisation would. Although not + preferred, it is allowed to apply the last method on all frames + ending with $FF. + + It is preferred that the tag is either completely unsynchronised or + not unsynchronised at all. A completely unsynchronised tag has no + false synchonisations in it, as defined above, and does not end with + $FF. A completely non-unsynchronised tag contains no unsynchronised + frames, and thus the unsynchronisation flag in the header is cleared. + + Do bear in mind, that if compression or encryption is used, the + unsynchronisation scheme MUST be applied afterwards. When decoding an + unsynchronised frame, the unsynchronisation scheme MUST be reversed + first, encryption and decompression afterwards. + + +6.2. Synchsafe integers + + In some parts of the tag it is inconvenient to use the + unsychronisation scheme because the size of unsynchronised data is + not known in advance, which is particularly problematic with size + descriptors. The solution in ID3v2 is to use synchsafe integers, in + which there can never be any false synchs. Synchsafe integers are + integers that keep its highest bit (bit 7) zeroed, making seven bits + out of eight available. Thus a 32 bit synchsafe integer can store 28 + bits of information. + + Example: + + 255 (%11111111) encoded as a 16 bit synchsafe integer is 383 + (%00000001 01111111). + + +7. Copyright + + Copyright (C) Martin Nilsson 2000. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + 'AS IS' basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +8. References + + [ID3v2] Martin Nilsson, 'ID3v2 informal standard'. + + + + [ISO-639-2] ISO/FDIS 639-2. + 'Codes for the representation of names of languages, Part 2: Alpha-3 + code.' Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-3309] ISO 3309 + 'Information Processing Systems--Data Communication High-Level Data + Link Control Procedure--Frame Structure', IS 3309, October 1984, 3rd + Edition. + + [ISO-8859-1] ISO/IEC DIS 8859-1. + '8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1.' Technical committee / subcommittee: JTC 1 / SC 2 + + [JFIF] 'JPEG File Interchange Format, version 1.02' + + + + [KEYWORDS] S. Bradner, 'Key words for use in RFCs to Indicate + Requirement Levels', RFC 2119, March 1997. + + + + [MPEG] ISO/IEC 11172-3:1993. + 'Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio.' + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + 'Generic coding of moving pictures and associated audio information, + Part 3: Audio.' + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + 'Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995)' + + [PNG] 'Portable Network Graphics, version 1.0' + + + + [UNICODE] The Unicode Consortium, + 'The Unicode Standard Version 3.0', ISBN 0-201-61633-5. + + + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, 'Uniform Resource + Locators (URL)', RFC 1738, December 1994. + + + + [UTF-8] F. Yergeau, 'UTF-8, a transformation format of ISO 10646', + RFC 2279, January 1998. + + + + [UTF-16] F. Yergeau, 'UTF-16, an encoding of ISO 10646', RFC 2781, + February 2000. + + + + [ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, 'ZLIB + Compressed Data Format Specification version 3.3', RFC 1950, + May 1996. + + + + +9. Author's Address + + Written by + + Martin Nilsson + Rydsvägen 246 C. 30 + SE-584 34 Linköping + Sweden + + Email: nilsson@id3.org + diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.cpp new file mode 100644 index 00000000..ddcfd452 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.cpp @@ -0,0 +1,71 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "id3v2extendedheader.h" +#include "id3v2synchdata.h" + +using namespace TagLib; +using namespace ID3v2; + +class ExtendedHeader::ExtendedHeaderPrivate +{ +public: + ExtendedHeaderPrivate() : size(0) {} + + uint size; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +ExtendedHeader::ExtendedHeader() +{ + d = new ExtendedHeaderPrivate(); +} + +ExtendedHeader::~ExtendedHeader() +{ + delete d; +} + +TagLib::uint ExtendedHeader::size() const +{ + return d->size; +} + +void ExtendedHeader::setData(const ByteVector &data) +{ + parse(data); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void ExtendedHeader::parse(const ByteVector &data) +{ + d->size = SynchData::toUInt(data.mid(0, 4)); // (structure 3.2 "Extended header size") +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.h new file mode 100644 index 00000000..d7227e9d --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2extendedheader.h @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2EXTENDEDHEADER_H +#define TAGLIB_ID3V2EXTENDEDHEADER_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "taglib.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 extended header implementation + + /*! + * This class implements ID3v2 extended headers. It attempts to follow, + * both semantically and programatically, the structure specified in + * the ID3v2 standard. The API is based on the properties of ID3v2 extended + * headers specified there. If any of the terms used in this documentation + * are unclear please check the specification in the linked section. + * (Structure, 3.2) + */ + + class TAGLIB_EXPORT ExtendedHeader + { + public: + /*! + * Constructs an empty ID3v2 extended header. + */ + ExtendedHeader(); + + /*! + * Destroys the extended header. + */ + virtual ~ExtendedHeader(); + + /*! + * Returns the size of the extended header. This is variable for the + * extended header. + */ + uint size() const; + + /*! + * Sets the data that will be used as the extended header. Since the + * length is not known before the extended header has been parsed, this + * should just be a pointer to the first byte of the extended header. It + * will determine the length internally and make that available through + * size(). + */ + void setData(const ByteVector &data); + + protected: + /*! + * Called by setData() to parse the extended header data. It makes this + * information available through the public API. + */ + void parse(const ByteVector &data); + + private: + ExtendedHeader(const ExtendedHeader &); + ExtendedHeader &operator=(const ExtendedHeader &); + + class ExtendedHeaderPrivate; + ExtendedHeaderPrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.cpp new file mode 100644 index 00000000..defbb17e --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.cpp @@ -0,0 +1,60 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "id3v2footer.h" +#include "id3v2header.h" + +using namespace TagLib; +using namespace ID3v2; + +class Footer::FooterPrivate +{ +public: + static const uint size = 10; +}; + +Footer::Footer() +{ + +} + +Footer::~Footer() +{ + +} + +TagLib::uint Footer::size() +{ + return FooterPrivate::size; +} + +ByteVector Footer::render(const Header *header) const +{ + ByteVector headerData = header->render(); + headerData[0] = '3'; + headerData[1] = 'D'; + headerData[2] = 'I'; + return headerData; +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.h new file mode 100644 index 00000000..1374a149 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2footer.h @@ -0,0 +1,82 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FOOTER_H +#define TAGLIB_ID3V2FOOTER_H + +#include "taglib_export.h" +#include "tbytevector.h" + +namespace TagLib { + + namespace ID3v2 { + + class Header; + + //! ID3v2 footer implementation + + /*! + * Per the ID3v2 specification, the tag's footer is just a copy of the + * information in the header. As such there is no API for reading the + * data from the header, it can just as easily be done from the header. + * + * In fact, at this point, TagLib does not even parse the footer since + * it is not useful internally. However, if the flag to include a footer + * has been set in the ID3v2::Tag, TagLib will render a footer. + */ + + class TAGLIB_EXPORT Footer + { + public: + /*! + * Constructs an empty ID3v2 footer. + */ + Footer(); + /*! + * Destroys the footer. + */ + virtual ~Footer(); + + /*! + * Returns the size of the footer. Presently this is always 10 bytes. + */ + static uint size(); + + /*! + * Renders the footer based on the data in \a header. + */ + ByteVector render(const Header *header) const; + + private: + Footer(const Footer &); + Footer &operator=(const Footer &); + + class FooterPrivate; + FooterPrivate *d; + }; + + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.cpp new file mode 100644 index 00000000..786336b9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.cpp @@ -0,0 +1,549 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef HAVE_ZLIB +#include +#endif + +#if HAVE_ZLIB +#include +#endif + +#include + +#include +#include + +#include "id3v2frame.h" +#include "id3v2synchdata.h" + +using namespace TagLib; +using namespace ID3v2; + +class Frame::FramePrivate +{ +public: + FramePrivate() : + header(0) + {} + + ~FramePrivate() + { + delete header; + } + + Frame::Header *header; +}; + +namespace +{ + bool isValidFrameID(const ByteVector &frameID) + { + if(frameID.size() != 4) + return false; + + for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) { + if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) { + return false; + } + } + return true; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// static methods +//////////////////////////////////////////////////////////////////////////////// + +TagLib::uint Frame::headerSize() +{ + return Header::size(); +} + +TagLib::uint Frame::headerSize(uint version) +{ + return Header::size(version); +} + +ByteVector Frame::textDelimiter(String::Type t) +{ + ByteVector d = char(0); + if(t == String::UTF16 || t == String::UTF16BE || t == String::UTF16LE) + d.append(char(0)); + return d; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Frame::~Frame() +{ + delete d; +} + +ByteVector Frame::frameID() const +{ + if(d->header) + return d->header->frameID(); + else + return ByteVector::null; +} + +TagLib::uint Frame::size() const +{ + if(d->header) + return d->header->frameSize(); + else + return 0; +} + +void Frame::setData(const ByteVector &data) +{ + parse(data); +} + +void Frame::setText(const String &) +{ + +} + +ByteVector Frame::render() const +{ + ByteVector fieldData = renderFields(); + d->header->setFrameSize(fieldData.size()); + ByteVector headerData = d->header->render(); + + return headerData + fieldData; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +Frame::Frame(const ByteVector &data) +{ + d = new FramePrivate; + d->header = new Header(data); +} + +Frame::Frame(Header *h) +{ + d = new FramePrivate; + d->header = h; +} + +Frame::Header *Frame::header() const +{ + return d->header; +} + +void Frame::setHeader(Header *h, bool deleteCurrent) +{ + if(deleteCurrent) + delete d->header; + + d->header = h; +} + +void Frame::parse(const ByteVector &data) +{ + if(d->header) + d->header->setData(data); + else + d->header = new Header(data); + + parseFields(fieldData(data)); +} + +ByteVector Frame::fieldData(const ByteVector &frameData) const +{ + uint headerSize = Header::size(d->header->version()); + + uint frameDataOffset = headerSize; + uint frameDataLength = size(); + + if(d->header->compression() || d->header->dataLengthIndicator()) { + frameDataLength = SynchData::toUInt(frameData.mid(headerSize, 4)); + frameDataOffset += 4; + } + +#if HAVE_ZLIB + if(d->header->compression() && + !d->header->encryption()) + { + ByteVector data(frameDataLength); + uLongf uLongTmp = frameDataLength; + ::uncompress((Bytef *) data.data(), + (uLongf *) &uLongTmp, + (Bytef *) frameData.data() + frameDataOffset, + size()); + return data; + } + else +#endif + return frameData.mid(frameDataOffset, frameDataLength); +} + +String Frame::readStringField(const ByteVector &data, String::Type encoding, int *position) +{ + int start = 0; + + if(!position) + position = &start; + + ByteVector delimiter = textDelimiter(encoding); + + int end = data.find(delimiter, *position, delimiter.size()); + + if(end < *position) + return String::null; + + String str = String(data.mid(*position, end - *position), encoding); + + *position = end + delimiter.size(); + + return str; +} + +String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding) // static +{ + if(encoding != String::Latin1) + return encoding; + + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { + if(!(*it).isLatin1()) { + debug("Frame::checkEncoding() -- Rendering using UTF8."); + return String::UTF8; + } + } + + return String::Latin1; +} + +//////////////////////////////////////////////////////////////////////////////// +// Frame::Header class +//////////////////////////////////////////////////////////////////////////////// + +class Frame::Header::HeaderPrivate +{ +public: + HeaderPrivate() : + frameSize(0), + version(4), + tagAlterPreservation(false), + fileAlterPreservation(false), + readOnly(false), + groupingIdentity(false), + compression(false), + encryption(false), + unsynchronisation(false), + dataLengthIndicator(false) + {} + + ByteVector frameID; + uint frameSize; + uint version; + + // flags + + bool tagAlterPreservation; + bool fileAlterPreservation; + bool readOnly; + bool groupingIdentity; + bool compression; + bool encryption; + bool unsynchronisation; + bool dataLengthIndicator; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members (Frame::Header) +//////////////////////////////////////////////////////////////////////////////// + +TagLib::uint Frame::Header::size() +{ + return size(4); +} + +TagLib::uint Frame::Header::size(uint version) +{ + switch(version) { + case 0: + case 1: + case 2: + return 6; + case 3: + case 4: + default: + return 10; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// public members (Frame::Header) +//////////////////////////////////////////////////////////////////////////////// + +Frame::Header::Header(const ByteVector &data, bool synchSafeInts) +{ + d = new HeaderPrivate; + setData(data, synchSafeInts); +} + +Frame::Header::Header(const ByteVector &data, uint version) +{ + d = new HeaderPrivate; + setData(data, version); +} + +Frame::Header::~Header() +{ + delete d; +} + +void Frame::Header::setData(const ByteVector &data, bool synchSafeInts) +{ + setData(data, uint(synchSafeInts ? 4 : 3)); +} + +void Frame::Header::setData(const ByteVector &data, uint version) +{ + d->version = version; + + switch(version) { + case 0: + case 1: + case 2: + { + // ID3v2.2 + + if(data.size() < 3) { + debug("You must at least specify a frame ID."); + return; + } + + // Set the frame ID -- the first three bytes + + d->frameID = data.mid(0, 3); + + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 6) { + d->frameSize = 0; + return; + } + + d->frameSize = data.mid(3, 3).toUInt(); + + break; + } + case 3: + { + // ID3v2.3 + + if(data.size() < 4) { + debug("You must at least specify a frame ID."); + return; + } + + // Set the frame ID -- the first four bytes + + d->frameID = data.mid(0, 4); + + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 10) { + d->frameSize = 0; + return; + } + + // Set the size -- the frame size is the four bytes starting at byte four in + // the frame header (structure 4) + + d->frameSize = data.mid(4, 4).toUInt(); + + { // read the first byte of flags + std::bitset<8> flags(data[8]); + d->tagAlterPreservation = flags[7]; // (structure 3.3.1.a) + d->fileAlterPreservation = flags[6]; // (structure 3.3.1.b) + d->readOnly = flags[5]; // (structure 3.3.1.c) + } + + { // read the second byte of flags + std::bitset<8> flags(data[9]); + d->compression = flags[7]; // (structure 3.3.1.i) + d->encryption = flags[6]; // (structure 3.3.1.j) + d->groupingIdentity = flags[5]; // (structure 3.3.1.k) + } + break; + } + case 4: + default: + { + // ID3v2.4 + + if(data.size() < 4) { + debug("You must at least specify a frame ID."); + return; + } + + // Set the frame ID -- the first four bytes + + d->frameID = data.mid(0, 4); + + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 10) { + d->frameSize = 0; + return; + } + + // Set the size -- the frame size is the four bytes starting at byte four in + // the frame header (structure 4) + + d->frameSize = SynchData::toUInt(data.mid(4, 4)); +#ifndef NO_ITUNES_HACKS + // iTunes writes v2.4 tags with v2.3-like frame sizes + if(d->frameSize > 127) { + if(!isValidFrameID(data.mid(d->frameSize + 10, 4))) { + unsigned int uintSize = data.mid(4, 4).toUInt(); + if(isValidFrameID(data.mid(uintSize + 10, 4))) { + d->frameSize = uintSize; + } + } + } +#endif + + { // read the first byte of flags + std::bitset<8> flags(data[8]); + d->tagAlterPreservation = flags[6]; // (structure 4.1.1.a) + d->fileAlterPreservation = flags[5]; // (structure 4.1.1.b) + d->readOnly = flags[4]; // (structure 4.1.1.c) + } + + { // read the second byte of flags + std::bitset<8> flags(data[9]); + d->groupingIdentity = flags[6]; // (structure 4.1.2.h) + d->compression = flags[3]; // (structure 4.1.2.k) + d->encryption = flags[2]; // (structure 4.1.2.m) + d->unsynchronisation = flags[1]; // (structure 4.1.2.n) + d->dataLengthIndicator = flags[0]; // (structure 4.1.2.p) + } + break; + } + } +} + +ByteVector Frame::Header::frameID() const +{ + return d->frameID; +} + +void Frame::Header::setFrameID(const ByteVector &id) +{ + d->frameID = id.mid(0, 4); +} + +TagLib::uint Frame::Header::frameSize() const +{ + return d->frameSize; +} + +void Frame::Header::setFrameSize(uint size) +{ + d->frameSize = size; +} + +TagLib::uint Frame::Header::version() const +{ + return d->version; +} + +bool Frame::Header::tagAlterPreservation() const +{ + return d->tagAlterPreservation; +} + +void Frame::Header::setTagAlterPreservation(bool preserve) +{ + d->tagAlterPreservation = preserve; +} + +bool Frame::Header::fileAlterPreservation() const +{ + return d->fileAlterPreservation; +} + +bool Frame::Header::readOnly() const +{ + return d->readOnly; +} + +bool Frame::Header::groupingIdentity() const +{ + return d->groupingIdentity; +} + +bool Frame::Header::compression() const +{ + return d->compression; +} + +bool Frame::Header::encryption() const +{ + return d->encryption; +} + +bool Frame::Header::unsycronisation() const +{ + return unsynchronisation(); +} + +bool Frame::Header::unsynchronisation() const +{ + return d->unsynchronisation; +} + +bool Frame::Header::dataLengthIndicator() const +{ + return d->dataLengthIndicator; +} + +ByteVector Frame::Header::render() const +{ + ByteVector flags(2, char(0)); // just blank for the moment + + ByteVector v = d->frameID + SynchData::fromUInt(d->frameSize) + flags; + + return v; +} + +bool Frame::Header::frameAlterPreservation() const +{ + return fileAlterPreservation(); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.h new file mode 100644 index 00000000..661be3d2 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2frame.h @@ -0,0 +1,414 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FRAME_H +#define TAGLIB_ID3V2FRAME_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class StringList; + + namespace ID3v2 { + + class Tag; + class FrameFactory; + + //! ID3v2 frame implementation + + /*! + * This class is the main ID3v2 frame implementation. In ID3v2, a tag is + * split between a collection of frames (which are in turn split into fields + * (Structure, 4) + * (Frames). This class provides an API for + * gathering information about and modifying ID3v2 frames. Funtionallity + * specific to a given frame type is handed in one of the many subclasses. + */ + + class TAGLIB_EXPORT Frame + { + friend class Tag; + friend class FrameFactory; + + public: + /*! + * Destroys this Frame instance. + */ + virtual ~Frame(); + + /*! + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ + ByteVector frameID() const; + + /*! + * Returns the size of the frame. + */ + uint size() const; + + /*! + * Returns the size of the frame header + * + * \deprecated This is only accurate for ID3v2.3 or ID3v2.4. Please use + * the call below which accepts an ID3v2 version number. In the next + * non-binary compatible release this will be made into a non-static + * member that checks the internal ID3v2 version. + */ + static uint headerSize(); // BIC: remove and make non-static + + /*! + * Returns the size of the frame header for the given ID3v2 version. + * + * \deprecated Please see the explanation above. + */ + static uint headerSize(uint version); // BIC: remove and make non-static + + /*! + * Sets the data that will be used as the frame. Since the length is not + * known before the frame has been parsed, this should just be a pointer to + * the first byte of the frame. It will determine the length internally + * and make that available through size(). + */ + void setData(const ByteVector &data); + + /*! + * Set the text of frame in the sanest way possible. This should only be + * reimplemented in frames where there is some logical mapping to text. + * + * \note If the frame type supports multiple text encodings, this will not + * change the text encoding of the frame; the string will be converted to + * that frame's encoding. Please use the specific APIs of the frame types + * to set the encoding if that is desired. + */ + virtual void setText(const String &text); + + /*! + * This returns the textual representation of the data in the frame. + * Subclasses must reimplement this method to provide a string + * representation of the frame's data. + */ + virtual String toString() const = 0; + + /*! + * Render the frame back to its binary format in a ByteVector. + */ + ByteVector render() const; + + /*! + * Returns the text delimiter that is used between fields for the string + * type \a t. + */ + static ByteVector textDelimiter(String::Type t); + + protected: + class Header; + + /*! + * Constructs an ID3v2 frame using \a data to read the header information. + * All other processing of \a data should be handled in a subclass. + * + * \note This need not contain anything more than a frame ID, but + * \e must constain at least that. + */ + explicit Frame(const ByteVector &data); + + /*! + * This creates an Frame using the header \a h. + * + * The ownership of this header will be assigned to the frame and the + * header will be deleted when the frame is destroyed. + */ + Frame(Header *h); + + /*! + * Returns a pointer to the frame header. + */ + Header *header() const; + + /*! + * Sets the header to \a h. If \a deleteCurrent is true, this will free + * the memory of the current header. + * + * The ownership of this header will be assigned to the frame and the + * header will be deleted when the frame is destroyed. + */ + void setHeader(Header *h, bool deleteCurrent = true); + + /*! + * Called by setData() to parse the frame data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + /*! + * Called by parse() to parse the field data. It makes this information + * available through the public API. This must be overridden by the + * subclasses. + */ + virtual void parseFields(const ByteVector &data) = 0; + + /*! + * Render the field data back to a binary format in a ByteVector. This + * must be overridden by subclasses. + */ + virtual ByteVector renderFields() const = 0; + + /*! + * Returns a ByteVector containing the field data given the frame data. + * This correctly adjusts for the header size plus any additional frame + * data that's specified in the frame header flags. + */ + ByteVector fieldData(const ByteVector &frameData) const; + + /*! + * Reads a String of type \a encodiong from the ByteVector \a data. If \a + * position is passed in it is used both as the starting point and is + * updated to replect the position just after the string that has been read. + * This is useful for reading strings sequentially. + */ + String readStringField(const ByteVector &data, String::Type encoding, + int *positon = 0); + + /*! + * Checks a the list of string values to see if they can be used with the + * specified encoding and returns the recommended encoding. + */ + static String::Type checkEncoding(const StringList &fields, + String::Type encoding); + + private: + Frame(const Frame &); + Frame &operator=(const Frame &); + + class FramePrivate; + friend class FramePrivate; + FramePrivate *d; + }; + + //! ID3v2 frame header implementation + + /*! + * The ID3v2 Frame Header (Structure, 4) + * + * Every ID3v2::Frame has an associated header that gives some general + * properties of the frame and also makes it possible to identify the frame + * type. + * + * As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the + * frame headers and then creates the appropriate Frame subclass based on + * the type and attaches the header. + */ + + class TAGLIB_EXPORT Frame::Header + { + public: + /*! + * Construct a Frame Header based on \a data. \a data must at least + * contain a 4 byte frame ID, and optionally can contain flag data and the + * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \deprecated Please use the constructor below that accepts a version + * number. + */ + Header(const ByteVector &data, bool synchSafeInts); + + /*! + * Construct a Frame Header based on \a data. \a data must at least + * contain a 4 byte frame ID, and optionally can contain flag data and the + * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \a version should be the ID3v2 version of the tag. + */ + explicit Header(const ByteVector &data, uint version = 4); + + /*! + * Destroys this Header instance. + */ + virtual ~Header(); + + /*! + * Sets the data for the Header. + * + * \deprecated Please use the version below that accepts an ID3v2 version + * number. + */ + void setData(const ByteVector &data, bool synchSafeInts); + + /*! + * Sets the data for the Header. \a version should indicate the ID3v2 + * version number of the tag that this frame is contained in. + */ + void setData(const ByteVector &data, uint version = 4); + + /*! + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ + ByteVector frameID() const; + + /*! + * Sets the frame's ID to \a id. Only the first four bytes of \a id will + * be used. + * + * \warning This method should in general be avoided. It exists simply to + * provide a mechanism for transforming frames from a deprecated frame type + * to a newer one -- i.e. TYER to TDRC from ID3v2.3 to ID3v2.4. + */ + void setFrameID(const ByteVector &id); + + /*! + * Returns the size of the frame data portion, as set when setData() was + * called or set explicitly via setFrameSize(). + */ + uint frameSize() const; + + /*! + * Sets the size of the frame data portion. + */ + void setFrameSize(uint size); + + /*! + * Returns the ID3v2 version of the header (as passed in from the + * construction of the header). + */ + uint version() const; + + /*! + * Returns the size of the frame header in bytes. + * + * \deprecated Please use the version of this method that accepts a + * version. This is only accurate for ID3v2.3 and ID3v2.4. This will be + * removed in the next binary incompatible release (2.0) and will be + * replaced with a non-static method that checks the frame version. + */ + static uint size(); + + /*! + * Returns the size of the frame header in bytes for the ID3v2 version + * that's given. + * + * \deprecated Please see the explanation in the version above. + */ + static uint size(uint version); + + /*! + * Returns true if the flag for tag alter preservation is set. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see setTagAlterPreservation() + */ + bool tagAlterPreservation() const; + + /*! + * Sets the flag for preservation of this frame if the tag is set. If + * this is set to true the frame will not be written when the tag is + * saved. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see tagAlterPreservation() + */ + void setTagAlterPreservation(bool discard); + + /*! + * Returns true if the flag for file alter preservation is set. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool fileAlterPreservation() const; + + /*! + * Returns true if the frame is meant to be read only. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool readOnly() const; + + /*! + * Returns true if the flag for the grouping identifity is set. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool groupingIdentity() const; + + /*! + * Returns true if compression is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool compression() const; + + /*! + * Returns true if encryption is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool encryption() const; + +#ifndef DO_NOT_DOCUMENT + bool unsycronisation() const; +#endif + + /*! + * Returns true if unsynchronisation is enabled for this frame. + */ + bool unsynchronisation() const; + + /*! + * Returns true if the flag for a data length indicator is set. + */ + bool dataLengthIndicator() const; + + /*! + * Render the Header back to binary format in a ByteVector. + */ + ByteVector render() const; + + /*! + * \deprecated + */ + bool frameAlterPreservation() const; + + private: + Header(const Header &); + Header &operator=(const Header &); + + class HeaderPrivate; + HeaderPrivate *d; + }; + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.cpp new file mode 100644 index 00000000..356d60d4 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -0,0 +1,433 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef HAVE_ZLIB +#include +#endif + +#include + +#include "id3v2framefactory.h" +#include "id3v2synchdata.h" +#include "id3v1genres.h" + +#include "frames/attachedpictureframe.h" +#include "frames/commentsframe.h" +#include "frames/relativevolumeframe.h" +#include "frames/textidentificationframe.h" +#include "frames/uniquefileidentifierframe.h" +#include "frames/unknownframe.h" +#include "frames/generalencapsulatedobjectframe.h" +#include "frames/urllinkframe.h" +#include "frames/unsynchronizedlyricsframe.h" +#include "frames/popularimeterframe.h" +#include "frames/privateframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class FrameFactory::FrameFactoryPrivate +{ +public: + FrameFactoryPrivate() : + defaultEncoding(String::Latin1), + useDefaultEncoding(false) {} + + String::Type defaultEncoding; + bool useDefaultEncoding; + + template void setTextEncoding(T *frame) + { + if(useDefaultEncoding) + frame->setTextEncoding(defaultEncoding); + } +}; + +FrameFactory *FrameFactory::factory = 0; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FrameFactory *FrameFactory::instance() +{ + if(!factory) + factory = new FrameFactory; + return factory; +} + +Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const +{ + return createFrame(data, uint(synchSafeInts ? 4 : 3)); +} + +Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const +{ + Header tagHeader; + tagHeader.setMajorVersion(version); + return createFrame(data, &tagHeader); +} + +Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) const +{ + ByteVector data = origData; + uint version = tagHeader->majorVersion(); + Frame::Header *header = new Frame::Header(data, version); + ByteVector frameID = header->frameID(); + + // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1 + // characters. Also make sure that there is data in the frame. + + if(!frameID.size() == (version < 3 ? 3 : 4) || + header->frameSize() <= uint(header->dataLengthIndicator() ? 4 : 0) || + header->frameSize() > data.size()) + { + delete header; + return 0; + } + + for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) { + if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) { + delete header; + return 0; + } + } + + if(version > 3 && (tagHeader->unsynchronisation() || header->unsynchronisation())) { + // Data lengths are not part of the encoded data, but since they are synch-safe + // integers they will be never actually encoded. + ByteVector frameData = data.mid(Frame::Header::size(version), header->frameSize()); + frameData = SynchData::decode(frameData); + data = data.mid(0, Frame::Header::size(version)) + frameData; + } + + // TagLib doesn't mess with encrypted frames, so just treat them + // as unknown frames. + +#if HAVE_ZLIB == 0 + if(header->compression()) { + debug("Compressed frames are currently not supported."); + return new UnknownFrame(data, header); + } +#endif + if(header->encryption()) { + debug("Encrypted frames are currently not supported."); + return new UnknownFrame(data, header); + } + + if(!updateFrame(header)) { + header->setTagAlterPreservation(true); + return new UnknownFrame(data, header); + } + + // updateFrame() might have updated the frame ID. + + frameID = header->frameID(); + + // This is where things get necissarily nasty. Here we determine which + // Frame subclass (or if none is found simply an Frame) based + // on the frame ID. Since there are a lot of possibilities, that means + // a lot of if blocks. + + // Text Identification (frames 4.2) + + if(frameID.startsWith("T")) { + + TextIdentificationFrame *f = frameID != "TXXX" + ? new TextIdentificationFrame(data, header) + : new UserTextIdentificationFrame(data, header); + + d->setTextEncoding(f); + + if(frameID == "TCON") + updateGenre(f); + + return f; + } + + // Comments (frames 4.10) + + if(frameID == "COMM") { + CommentsFrame *f = new CommentsFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // Attached Picture (frames 4.14) + + if(frameID == "APIC") { + AttachedPictureFrame *f = new AttachedPictureFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // ID3v2.2 Attached Picture + + if(frameID == "PIC") { + AttachedPictureFrame *f = new AttachedPictureFrameV22(data, header); + d->setTextEncoding(f); + return f; + } + + // Relative Volume Adjustment (frames 4.11) + + if(frameID == "RVA2") + return new RelativeVolumeFrame(data, header); + + // Unique File Identifier (frames 4.1) + + if(frameID == "UFID") + return new UniqueFileIdentifierFrame(data, header); + + // General Encapsulated Object (frames 4.15) + + if(frameID == "GEOB") { + GeneralEncapsulatedObjectFrame *f = new GeneralEncapsulatedObjectFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // URL link (frames 4.3) + + if(frameID.startsWith("W")) { + if(frameID != "WXXX") { + return new UrlLinkFrame(data, header); + } + else { + UserUrlLinkFrame *f = new UserUrlLinkFrame(data, header); + d->setTextEncoding(f); + return f; + } + } + + // Unsynchronized lyric/text transcription (frames 4.8) + + if(frameID == "USLT") { + UnsynchronizedLyricsFrame *f = new UnsynchronizedLyricsFrame(data, header); + if(d->useDefaultEncoding) + f->setTextEncoding(d->defaultEncoding); + return f; + } + + // Popularimeter (frames 4.17) + + if(frameID == "POPM") + return new PopularimeterFrame(data, header); + + // Private (frames 4.27) + + if(frameID == "PRIV") + return new PrivateFrame(data, header); + + return new UnknownFrame(data, header); +} + +String::Type FrameFactory::defaultTextEncoding() const +{ + return d->defaultEncoding; +} + +void FrameFactory::setDefaultTextEncoding(String::Type encoding) +{ + d->useDefaultEncoding = true; + d->defaultEncoding = encoding; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +FrameFactory::FrameFactory() +{ + d = new FrameFactoryPrivate; +} + +FrameFactory::~FrameFactory() +{ + delete d; +} + +bool FrameFactory::updateFrame(Frame::Header *header) const +{ + TagLib::ByteVector frameID = header->frameID(); + + switch(header->version()) { + + case 2: // ID3v2.2 + { + if(frameID == "CRM" || + frameID == "EQU" || + frameID == "LNK" || + frameID == "RVA" || + frameID == "TIM" || + frameID == "TSI" || + frameID == "TDA") + { + debug("ID3v2.4 no longer supports the frame type " + String(frameID) + + ". It will be discarded from the tag."); + return false; + } + + // ID3v2.2 only used 3 bytes for the frame ID, so we need to convert all of + // the frames to their 4 byte ID3v2.4 equivalent. + + convertFrame("BUF", "RBUF", header); + convertFrame("CNT", "PCNT", header); + convertFrame("COM", "COMM", header); + convertFrame("CRA", "AENC", header); + convertFrame("ETC", "ETCO", header); + convertFrame("GEO", "GEOB", header); + convertFrame("IPL", "TIPL", header); + convertFrame("MCI", "MCDI", header); + convertFrame("MLL", "MLLT", header); + convertFrame("POP", "POPM", header); + convertFrame("REV", "RVRB", header); + convertFrame("SLT", "SYLT", header); + convertFrame("STC", "SYTC", header); + convertFrame("TAL", "TALB", header); + convertFrame("TBP", "TBPM", header); + convertFrame("TCM", "TCOM", header); + convertFrame("TCO", "TCON", header); + convertFrame("TCR", "TCOP", header); + convertFrame("TDY", "TDLY", header); + convertFrame("TEN", "TENC", header); + convertFrame("TFT", "TFLT", header); + convertFrame("TKE", "TKEY", header); + convertFrame("TLA", "TLAN", header); + convertFrame("TLE", "TLEN", header); + convertFrame("TMT", "TMED", header); + convertFrame("TOA", "TOAL", header); + convertFrame("TOF", "TOFN", header); + convertFrame("TOL", "TOLY", header); + convertFrame("TOR", "TDOR", header); + convertFrame("TOT", "TOAL", header); + convertFrame("TP1", "TPE1", header); + convertFrame("TP2", "TPE2", header); + convertFrame("TP3", "TPE3", header); + convertFrame("TP4", "TPE4", header); + convertFrame("TPA", "TPOS", header); + convertFrame("TPB", "TPUB", header); + convertFrame("TRC", "TSRC", header); + convertFrame("TRD", "TDRC", header); + convertFrame("TRK", "TRCK", header); + convertFrame("TSS", "TSSE", header); + convertFrame("TT1", "TIT1", header); + convertFrame("TT2", "TIT2", header); + convertFrame("TT3", "TIT3", header); + convertFrame("TXT", "TOLY", header); + convertFrame("TXX", "TXXX", header); + convertFrame("TYE", "TDRC", header); + convertFrame("UFI", "UFID", header); + convertFrame("ULT", "USLT", header); + convertFrame("WAF", "WOAF", header); + convertFrame("WAR", "WOAR", header); + convertFrame("WAS", "WOAS", header); + convertFrame("WCM", "WCOM", header); + convertFrame("WCP", "WCOP", header); + convertFrame("WPB", "WPUB", header); + convertFrame("WXX", "WXXX", header); + + break; + } + + case 3: // ID3v2.3 + { + if(frameID == "EQUA" || + frameID == "RVAD" || + frameID == "TIME" || + frameID == "TRDA" || + frameID == "TSIZ" || + frameID == "TDAT") + { + debug("ID3v2.4 no longer supports the frame type " + String(frameID) + + ". It will be discarded from the tag."); + return false; + } + + convertFrame("TORY", "TDOR", header); + convertFrame("TYER", "TDRC", header); + + break; + } + + default: + + // This should catch a typo that existed in TagLib up to and including + // version 1.1 where TRDC was used for the year rather than TDRC. + + convertFrame("TRDC", "TDRC", header); + break; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void FrameFactory::convertFrame(const char *from, const char *to, + Frame::Header *header) const +{ + if(header->frameID() != from) + return; + + // debug("ID3v2.4 no longer supports the frame type " + String(from) + " It has" + + // "been converted to the type " + String(to) + "."); + + header->setFrameID(to); +} + +void FrameFactory::updateGenre(TextIdentificationFrame *frame) const +{ + StringList fields = frame->fieldList(); + StringList newfields; + + for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) { + String s = *it; + int end = s.find(")"); + + if(s.startsWith("(") && end > 0) { + // "(12)Genre" + String text = s.substr(end + 1); + bool ok; + int number = s.substr(1, end - 1).toInt(&ok); + if(ok && number >= 0 && number <= 255 && !(ID3v1::genre(number) == text)) + newfields.append(s.substr(1, end - 1)); + if(!text.isEmpty()) + newfields.append(text); + } + else { + // "Genre" or "12" + newfields.append(s); + } + } + + if(newfields.isEmpty()) + fields.append(String::null); + + frame->setText(newfields); + +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.h new file mode 100644 index 00000000..34b704bf --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2framefactory.h @@ -0,0 +1,167 @@ + /*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FRAMEFACTORY_H +#define TAGLIB_ID3V2FRAMEFACTORY_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "id3v2frame.h" +#include "id3v2header.h" + +namespace TagLib { + + namespace ID3v2 { + + class TextIdentificationFrame; + + //! A factory for creating ID3v2 frames during parsing + + /*! + * This factory abstracts away the frame creation process and instantiates + * the appropriate ID3v2::Frame subclasses based on the contents of the + * data. + * + * Reimplementing this factory is the key to adding support for frame types + * not directly supported by TagLib to your application. To do so you would + * subclass this factory reimplement createFrame(). Then by setting your + * factory to be the default factory in ID3v2::Tag constructor or with + * MPEG::File::setID3v2FrameFactory() you can implement behavior that will + * allow for new ID3v2::Frame subclasses (also provided by you) to be used. + * + * This implements both abstract factory and singleton patterns + * of which more information is available on the web and in software design + * textbooks (Notably Design Patters). + * + * \note You do not need to use this factory to create new frames to add to + * an ID3v2::Tag. You can instantiate frame subclasses directly (with new) + * and add them to a tag using ID3v2::Tag::addFrame() + * + * \see ID3v2::Tag::addFrame() + */ + + class TAGLIB_EXPORT FrameFactory + { + public: + static FrameFactory *instance(); + /*! + * Create a frame based on \a data. \a synchSafeInts should only be set + * false if we are parsing an old tag (v2.3 or older) that does not support + * synchsafe ints. + * + * \deprecated Please use the method below that accepts a ID3v2::Header + * instance in new code. + */ + Frame *createFrame(const ByteVector &data, bool synchSafeInts) const; + + /*! + * Create a frame based on \a data. \a version should indicate the ID3v2 + * version of the tag. As ID3v2.4 is the most current version of the + * standard 4 is the default. + * + * \deprecated Please use the method below that accepts a ID3v2::Header + * instance in new code. + */ + Frame *createFrame(const ByteVector &data, uint version = 4) const; + + /*! + * Create a frame based on \a data. \a tagHeader should be a valid + * ID3v2::Header instance. + */ + // BIC: make virtual + Frame *createFrame(const ByteVector &data, Header *tagHeader) const; + + /*! + * Returns the default text encoding for text frames. If setTextEncoding() + * has not been explicitly called this will only be used for new text + * frames. However, if this value has been set explicitly all frames will be + * converted to this type (unless it's explitly set differently for the + * individual frame) when being rendered. + * + * \see setDefaultTextEncoding() + */ + String::Type defaultTextEncoding() const; + + /*! + * Set the default text encoding for all text frames that are created to + * \a encoding. If no value is set the frames with either default to the + * encoding type that was parsed and new frames default to Latin1. + * + * Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE. + * + * \see defaultTextEncoding() + */ + void setDefaultTextEncoding(String::Type encoding); + + protected: + /*! + * Constructs a frame factory. Because this is a singleton this method is + * protected, but may be used for subclasses. + */ + FrameFactory(); + + /*! + * Destroys the frame factory. In most cases this will never be called (as + * is typical of singletons). + */ + virtual ~FrameFactory(); + + /*! + * This method checks for compliance to the current ID3v2 standard (2.4) + * and does nothing in the common case. However if a frame is found that + * is not compatible with the current standard, this method either updates + * the frame or indicates that it should be discarded. + * + * This method with return true (with or without changes to the frame) if + * this frame should be kept or false if it should be discarded. + * + * See the id3v2.4.0-changes.txt document for further information. + */ + virtual bool updateFrame(Frame::Header *header) const; + + private: + FrameFactory(const FrameFactory &); + FrameFactory &operator=(const FrameFactory &); + + /*! + * This method is used internally to convert a frame from ID \a from to ID + * \a to. If the frame matches the \a from pattern and converts the frame + * ID in the \a header or simply does nothing if the frame ID does not match. + */ + void convertFrame(const char *from, const char *to, + Frame::Header *header) const; + + void updateGenre(TextIdentificationFrame *frame) const; + + static FrameFactory *factory; + + class FrameFactoryPrivate; + FrameFactoryPrivate *d; + }; + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.cpp new file mode 100644 index 00000000..31a5a1ec --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.cpp @@ -0,0 +1,243 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include +#include + +#include "id3v2header.h" +#include "id3v2footer.h" +#include "id3v2synchdata.h" + +using namespace TagLib; +using namespace ID3v2; + +class Header::HeaderPrivate +{ +public: + HeaderPrivate() : majorVersion(4), + revisionNumber(0), + unsynchronisation(false), + extendedHeader(false), + experimentalIndicator(false), + footerPresent(false), + tagSize(0) {} + + ~HeaderPrivate() {} + + uint majorVersion; + uint revisionNumber; + + bool unsynchronisation; + bool extendedHeader; + bool experimentalIndicator; + bool footerPresent; + + uint tagSize; + + static const uint size = 10; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +TagLib::uint Header::size() +{ + return HeaderPrivate::size; +} + +ByteVector Header::fileIdentifier() +{ + return ByteVector::fromCString("ID3"); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Header::Header() +{ + d = new HeaderPrivate; +} + +Header::Header(const ByteVector &data) +{ + d = new HeaderPrivate; + parse(data); +} + +Header::~Header() +{ + delete d; +} + +TagLib::uint Header::majorVersion() const +{ + return d->majorVersion; +} + +void Header::setMajorVersion(TagLib::uint version) +{ + d->majorVersion = version; +} + +TagLib::uint Header::revisionNumber() const +{ + return d->revisionNumber; +} + +bool Header::unsynchronisation() const +{ + return d->unsynchronisation; +} + +bool Header::extendedHeader() const +{ + return d->extendedHeader; +} + +bool Header::experimentalIndicator() const +{ + return d->experimentalIndicator; +} + +bool Header::footerPresent() const +{ + return d->footerPresent; +} + +TagLib::uint Header::tagSize() const +{ + return d->tagSize; +} + +TagLib::uint Header::completeTagSize() const +{ + if(d->footerPresent) + return d->tagSize + d->size + Footer::size(); + else + return d->tagSize + d->size; +} + +void Header::setTagSize(uint s) +{ + d->tagSize = s; +} + +void Header::setData(const ByteVector &data) +{ + parse(data); +} + +ByteVector Header::render() const +{ + ByteVector v; + + // add the file identifier -- "ID3" + v.append(fileIdentifier()); + + // add the version number -- we always render a 2.4.0 tag regardless of what + // the tag originally was. + + v.append(char(4)); + v.append(char(0)); + + // Currently we don't actually support writing extended headers, footers or + // unsynchronized tags, make sure that the flags are set accordingly. + + d->extendedHeader = false; + d->footerPresent = false; + d->unsynchronisation = false; + + // render and add the flags + std::bitset<8> flags; + + flags[7] = d->unsynchronisation; + flags[6] = d->extendedHeader; + flags[5] = d->experimentalIndicator; + flags[4] = d->footerPresent; + + v.append(char(flags.to_ulong())); + + // add the size + v.append(SynchData::fromUInt(d->tagSize)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void Header::parse(const ByteVector &data) +{ + if(data.size() < size()) + return; + + + // do some sanity checking -- even in ID3v2.3.0 and less the tag size is a + // synch-safe integer, so all bytes must be less than 128. If this is not + // true then this is an invalid tag. + + // note that we're doing things a little out of order here -- the size is + // later in the bytestream than the version + + ByteVector sizeData = data.mid(6, 4); + + if(sizeData.size() != 4) { + d->tagSize = 0; + debug("TagLib::ID3v2::Header::parse() - The tag size as read was 0 bytes!"); + return; + } + + for(ByteVector::Iterator it = sizeData.begin(); it != sizeData.end(); it++) { + if(uchar(*it) >= 128) { + d->tagSize = 0; + debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128."); + return; + } + } + + // The first three bytes, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier") + + // Read the version number from the fourth and fifth bytes. + d->majorVersion = data[3]; // (structure 3.1 "major version") + d->revisionNumber = data[4]; // (structure 3.1 "revision number") + + // Read the flags, the first four bits of the sixth byte. + std::bitset<8> flags(data[5]); + + d->unsynchronisation = flags[7]; // (structure 3.1.a) + d->extendedHeader = flags[6]; // (structure 3.1.b) + d->experimentalIndicator = flags[5]; // (structure 3.1.c) + d->footerPresent = flags[4]; // (structure 3.1.d) + + // Get the size from the remaining four bytes (read above) + + d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size") +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.h new file mode 100644 index 00000000..307ba96c --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2header.h @@ -0,0 +1,175 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2HEADER_H +#define TAGLIB_ID3V2HEADER_H + +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 headers + + /*! + * This class implements ID3v2 headers. It attempts to follow, both + * semantically and programatically, the structure specified in + * the ID3v2 standard. The API is based on the properties of ID3v2 headers + * specified there. If any of the terms used in this documentation are + * unclear please check the specification in the linked section. + * (Structure, 3.1) + */ + + class TAGLIB_EXPORT Header + { + public: + /*! + * Constructs an empty ID3v2 header. + */ + Header(); + + /*! + * Constructs an ID3v2 header based on \a data. parse() is called + * immediately. + */ + Header(const ByteVector &data); + + /*! + * Destroys the header. + */ + virtual ~Header(); + + /*! + * Returns the major version number. (Note: This is the 4, not the 2 in + * ID3v2.4.0. The 2 is implied.) + */ + uint majorVersion() const; + + /*! + * Set the the major version number to \a version. (Note: This is + * the 4, not the 2 in ID3v2.4.0. The 2 is implied.) + * \see majorVersion() + * + * \note This is used by the internal parser; this will not change the + * version which is written and in general should not be called by API + * users. + */ + void setMajorVersion(uint version); + + /*! + * Returns the revision number. (Note: This is the 0, not the 4 in + * ID3v2.4.0. The 2 is implied.) + */ + uint revisionNumber() const; + + /*! + * Returns true if unsynchronisation has been applied to all frames. + */ + bool unsynchronisation() const; + + /*! + * Returns true if an extended header is present in the tag. + */ + bool extendedHeader() const; + + /*! + * Returns true if the experimental indicator flag is set. + */ + bool experimentalIndicator() const; + + /*! + * Returns true if a footer is present in the tag. + */ + bool footerPresent() const; + /*! + * Returns the tag size in bytes. This is the size of the frame content. + * The size of the \e entire tag will be this plus the header size (10 + * bytes) and, if present, the footer size (potentially another 10 bytes). + * + * \note This is the value as read from the header to which TagLib attempts + * to provide an API to; it was not a design decision on the part of TagLib + * to not include the mentioned portions of the tag in the \e size. + * + * \see completeTagSize() + */ + uint tagSize() const; + + /*! + * Returns the tag size, including the header and, if present, the footer + * size. + * + * \see tagSize() + */ + uint completeTagSize() const; + + /*! + * Set the tag size to \a s. + * \see tagSize() + */ + void setTagSize(uint s); + + /*! + * Returns the size of the header. Presently this is always 10 bytes. + */ + static uint size(); + + /*! + * Returns the string used to identify and ID3v2 tag inside of a file. + * Presently this is always "ID3". + */ + static ByteVector fileIdentifier(); + + /*! + * Sets the data that will be used as the header. 10 bytes, starting from + * the beginning of \a data are used. + */ + void setData(const ByteVector &data); + + /*! + * Renders the Header back to binary format. + */ + ByteVector render() const; + + protected: + /*! + * Called by setData() to parse the header data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + private: + Header(const Header &); + Header &operator=(const Header &); + + class HeaderPrivate; + HeaderPrivate *d; + }; + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.cpp new file mode 100644 index 00000000..12e1f5b2 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include "id3v2synchdata.h" + +using namespace TagLib; +using namespace ID3v2; + +TagLib::uint SynchData::toUInt(const ByteVector &data) +{ + uint sum = 0; + bool notSynchSafe = false; + int last = data.size() > 4 ? 3 : data.size() - 1; + + for(int i = 0; i <= last; i++) { + if(data[i] & 0x80) { + notSynchSafe = true; + break; + } + + sum |= (data[i] & 0x7f) << ((last - i) * 7); + } + + if(notSynchSafe) { + // Invalid data; assume this was created by some buggy software that just + // put normal integers here rather than syncsafe ones, and try it that + // way. + sum = (data.size() > 4) ? data.mid(0, 4).toUInt() : data.toUInt(); + } + + return sum; +} + +ByteVector SynchData::fromUInt(uint value) +{ + ByteVector v(4, 0); + + for(int i = 0; i < 4; i++) + v[i] = uchar(value >> ((3 - i) * 7) & 0x7f); + + return v; +} + +ByteVector SynchData::decode(const ByteVector &data) +{ + ByteVector result = data; + + ByteVector pattern(2, char(0)); + pattern[0] = '\xFF'; + pattern[1] = '\x00'; + + return result.replace(pattern, '\xFF'); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.h new file mode 100644 index 00000000..4a1f596a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2synchdata.h @@ -0,0 +1,70 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2SYNCHDATA_H +#define TAGLIB_ID3V2SYNCHDATA_H + +#include "tbytevector.h" +#include "taglib.h" + +namespace TagLib { + + namespace ID3v2 { + + //! A few functions for ID3v2 synch safe integer conversion + + /*! + * In the ID3v2.4 standard most integer values are encoded as "synch safe" + * integers which are encoded in such a way that they will not give false + * MPEG syncs and confuse MPEG decoders. This namespace provides some + * methods for converting to and from these values to ByteVectors for + * things rendering and parsing ID3v2 data. + */ + + namespace SynchData + { + /*! + * This returns the unsigned integer value of \a data where \a data is a + * ByteVector that contains a \e synchsafe integer (Structure, + * 6.2). The default \a length of + * 4 is used if another value is not specified. + */ + TAGLIB_EXPORT uint toUInt(const ByteVector &data); + + /*! + * Returns a 4 byte (32 bit) synchsafe integer based on \a value. + */ + TAGLIB_EXPORT ByteVector fromUInt(uint value); + + /*! + * Convert the data from unsynchronized data to its original format. + */ + TAGLIB_EXPORT ByteVector decode(const ByteVector &input); + } + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.cpp new file mode 100644 index 00000000..7e8012b2 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.cpp @@ -0,0 +1,475 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "id3v2tag.h" +#include "id3v2header.h" +#include "id3v2extendedheader.h" +#include "id3v2footer.h" +#include "id3v2synchdata.h" + +#include "id3v1genres.h" + +#include "frames/textidentificationframe.h" +#include "frames/commentsframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class ID3v2::Tag::TagPrivate +{ +public: + TagPrivate() : file(0), tagOffset(-1), extendedHeader(0), footer(0), paddingSize(0) + { + frameList.setAutoDelete(true); + } + ~TagPrivate() + { + delete extendedHeader; + delete footer; + } + + File *file; + long tagOffset; + const FrameFactory *factory; + + Header header; + ExtendedHeader *extendedHeader; + Footer *footer; + + int paddingSize; + + FrameListMap frameListMap; + FrameList frameList; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ID3v2::Tag::Tag() : TagLib::Tag() +{ + d = new TagPrivate; + d->factory = FrameFactory::instance(); +} + +ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) : + TagLib::Tag() +{ + d = new TagPrivate; + + d->file = file; + d->tagOffset = tagOffset; + d->factory = factory; + + read(); +} + +ID3v2::Tag::~Tag() +{ + delete d; +} + + +String ID3v2::Tag::title() const +{ + if(!d->frameListMap["TIT2"].isEmpty()) + return d->frameListMap["TIT2"].front()->toString(); + return String::null; +} + +String ID3v2::Tag::artist() const +{ + if(!d->frameListMap["TPE1"].isEmpty()) + return d->frameListMap["TPE1"].front()->toString(); + return String::null; +} + +String ID3v2::Tag::album() const +{ + if(!d->frameListMap["TALB"].isEmpty()) + return d->frameListMap["TALB"].front()->toString(); + return String::null; +} + +String ID3v2::Tag::comment() const +{ + const FrameList &comments = d->frameListMap["COMM"]; + + if(comments.isEmpty()) + return String::null; + + for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it) + { + CommentsFrame *frame = dynamic_cast(*it); + + if(frame && frame->description().isEmpty()) + return (*it)->toString(); + } + + return comments.front()->toString(); +} + +String ID3v2::Tag::genre() const +{ + // TODO: In the next major version (TagLib 2.0) a list of multiple genres + // should be separated by " / " instead of " ". For the moment to keep + // the behavior the same as released versions it is being left with " ". + + if(d->frameListMap["TCON"].isEmpty() || + !dynamic_cast(d->frameListMap["TCON"].front())) + { + return String::null; + } + + // ID3v2.4 lists genres as the fields in its frames field list. If the field + // is simply a number it can be assumed that it is an ID3v1 genre number. + // Here was assume that if an ID3v1 string is present that it should be + // appended to the genre string. Multiple fields will be appended as the + // string is built. + + TextIdentificationFrame *f = static_cast( + d->frameListMap["TCON"].front()); + + StringList fields = f->fieldList(); + + StringList genres; + + for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) { + + if((*it).isEmpty()) + continue; + + bool ok; + int number = (*it).toInt(&ok); + if(ok && number >= 0 && number <= 255) { + *it = ID3v1::genre(number); + } + + if(std::find(genres.begin(), genres.end(), *it) == genres.end()) + genres.append(*it); + } + + return genres.toString(); +} + +TagLib::uint ID3v2::Tag::year() const +{ + if(!d->frameListMap["TDRC"].isEmpty()) + return d->frameListMap["TDRC"].front()->toString().substr(0, 4).toInt(); + return 0; +} + +TagLib::uint ID3v2::Tag::track() const +{ + if(!d->frameListMap["TRCK"].isEmpty()) + return d->frameListMap["TRCK"].front()->toString().toInt(); + return 0; +} + +void ID3v2::Tag::setTitle(const String &s) +{ + setTextFrame("TIT2", s); +} + +void ID3v2::Tag::setArtist(const String &s) +{ + setTextFrame("TPE1", s); +} + +void ID3v2::Tag::setAlbum(const String &s) +{ + setTextFrame("TALB", s); +} + +void ID3v2::Tag::setComment(const String &s) +{ + if(s.isEmpty()) { + removeFrames("COMM"); + return; + } + + if(!d->frameListMap["COMM"].isEmpty()) + d->frameListMap["COMM"].front()->setText(s); + else { + CommentsFrame *f = new CommentsFrame(d->factory->defaultTextEncoding()); + addFrame(f); + f->setText(s); + } +} + +void ID3v2::Tag::setGenre(const String &s) +{ + if(s.isEmpty()) { + removeFrames("TCON"); + return; + } + + // iTunes can't handle correctly encoded ID3v2.4 numerical genres. Just use + // strings until iTunes sucks less. + +#ifdef NO_ITUNES_HACKS + + int index = ID3v1::genreIndex(s); + + if(index != 255) + setTextFrame("TCON", String::number(index)); + else + setTextFrame("TCON", s); + +#else + + setTextFrame("TCON", s); + +#endif +} + +void ID3v2::Tag::setYear(uint i) +{ + if(i <= 0) { + removeFrames("TDRC"); + return; + } + setTextFrame("TDRC", String::number(i)); +} + +void ID3v2::Tag::setTrack(uint i) +{ + if(i <= 0) { + removeFrames("TRCK"); + return; + } + setTextFrame("TRCK", String::number(i)); +} + +bool ID3v2::Tag::isEmpty() const +{ + return d->frameList.isEmpty(); +} + +Header *ID3v2::Tag::header() const +{ + return &(d->header); +} + +ExtendedHeader *ID3v2::Tag::extendedHeader() const +{ + return d->extendedHeader; +} + +Footer *ID3v2::Tag::footer() const +{ + return d->footer; +} + +const FrameListMap &ID3v2::Tag::frameListMap() const +{ + return d->frameListMap; +} + +const FrameList &ID3v2::Tag::frameList() const +{ + return d->frameList; +} + +const FrameList &ID3v2::Tag::frameList(const ByteVector &frameID) const +{ + return d->frameListMap[frameID]; +} + +void ID3v2::Tag::addFrame(Frame *frame) +{ + d->frameList.append(frame); + d->frameListMap[frame->frameID()].append(frame); +} + +void ID3v2::Tag::removeFrame(Frame *frame, bool del) +{ + // remove the frame from the frame list + FrameList::Iterator it = d->frameList.find(frame); + d->frameList.erase(it); + + // ...and from the frame list map + it = d->frameListMap[frame->frameID()].find(frame); + d->frameListMap[frame->frameID()].erase(it); + + // ...and delete as desired + if(del) + delete frame; +} + +void ID3v2::Tag::removeFrames(const ByteVector &id) +{ + FrameList l = d->frameListMap[id]; + for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + removeFrame(*it, true); +} + +ByteVector ID3v2::Tag::render() const +{ + // We need to render the "tag data" first so that we have to correct size to + // render in the tag's header. The "tag data" -- everything that is included + // in ID3v2::Header::tagSize() -- includes the extended header, frames and + // padding, but does not include the tag's header or footer. + + ByteVector tagData; + + // TODO: Render the extended header. + + // Loop through the frames rendering them and adding them to the tagData. + + for(FrameList::Iterator it = d->frameList.begin(); it != d->frameList.end(); it++) { + if((*it)->header()->frameID().size() != 4) { + debug("A frame of unsupported or unknown type \'" + + String((*it)->header()->frameID()) + "\' has been discarded"); + continue; + } + if(!(*it)->header()->tagAlterPreservation()) + tagData.append((*it)->render()); + } + + // Compute the amount of padding, and append that to tagData. + + uint paddingSize = 0; + uint originalSize = d->header.tagSize(); + + if(tagData.size() < originalSize) + paddingSize = originalSize - tagData.size(); + else + paddingSize = 1024; + + tagData.append(ByteVector(paddingSize, char(0))); + + // Set the tag size. + d->header.setTagSize(tagData.size()); + + // TODO: This should eventually include d->footer->render(). + return d->header.render() + tagData; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void ID3v2::Tag::read() +{ + if(d->file && d->file->isOpen()) { + + d->file->seek(d->tagOffset); + d->header.setData(d->file->readBlock(Header::size())); + + // if the tag size is 0, then this is an invalid tag (tags must contain at + // least one frame) + + if(d->header.tagSize() == 0) + return; + + parse(d->file->readBlock(d->header.tagSize())); + } +} + +void ID3v2::Tag::parse(const ByteVector &origData) +{ + ByteVector data = origData; + + if(d->header.unsynchronisation() && d->header.majorVersion() <= 3) + data = SynchData::decode(data); + + uint frameDataPosition = 0; + uint frameDataLength = data.size(); + + // check for extended header + + if(d->header.extendedHeader()) { + if(!d->extendedHeader) + d->extendedHeader = new ExtendedHeader; + d->extendedHeader->setData(data); + if(d->extendedHeader->size() <= data.size()) { + frameDataPosition += d->extendedHeader->size(); + frameDataLength -= d->extendedHeader->size(); + } + } + + // check for footer -- we don't actually need to parse it, as it *must* + // contain the same data as the header, but we do need to account for its + // size. + + if(d->header.footerPresent() && Footer::size() <= frameDataLength) + frameDataLength -= Footer::size(); + + // parse frames + + // Make sure that there is at least enough room in the remaining frame data for + // a frame header. + + while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) { + + // If the next data is position is 0, assume that we've hit the padding + // portion of the frame data. + + if(data.at(frameDataPosition) == 0) { + if(d->header.footerPresent()) + debug("Padding *and* a footer found. This is not allowed by the spec."); + + d->paddingSize = frameDataLength - frameDataPosition; + return; + } + + Frame *frame = d->factory->createFrame(data.mid(frameDataPosition), + &d->header); + + if(!frame) + return; + + // Checks to make sure that frame parsed correctly. + + if(frame->size() <= 0) { + delete frame; + return; + } + + frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion()); + addFrame(frame); + } +} + +void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) +{ + if(value.isEmpty()) { + removeFrames(id); + return; + } + + if(!d->frameListMap[id].isEmpty()) + d->frameListMap[id].front()->setText(value); + else { + const String::Type encoding = d->factory->defaultTextEncoding(); + TextIdentificationFrame *f = new TextIdentificationFrame(id, encoding); + addFrame(f); + f->setText(value); + } +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.h b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.h new file mode 100644 index 00000000..a139d455 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/id3v2/id3v2tag.h @@ -0,0 +1,300 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2TAG_H +#define TAGLIB_ID3V2TAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "tstring.h" +#include "tlist.h" +#include "tmap.h" +#include "taglib_export.h" + +#include "id3v2framefactory.h" + +namespace TagLib { + + class File; + + //! An ID3v2 implementation + + /*! + * This is a relatively complete and flexible framework for working with ID3v2 + * tags. + * + * \see ID3v2::Tag + */ + + namespace ID3v2 { + + class Header; + class ExtendedHeader; + class Footer; + + typedef List FrameList; + typedef Map FrameListMap; + + //! The main class in the ID3v2 implementation + + /*! + * This is the main class in the ID3v2 implementation. It serves two + * functions. This first, as is obvious from the public API, is to provide a + * container for the other ID3v2 related classes. In addition, through the + * read() and parse() protected methods, it provides the most basic level of + * parsing. In these methods the ID3v2 tag is extracted from the file and + * split into data components. + * + * ID3v2 tags have several parts, TagLib attempts to provide an interface + * for them all. header(), footer() and extendedHeader() corespond to those + * data structures in the ID3v2 standard and the APIs for the classes that + * they return attempt to reflect this. + * + * Also ID3v2 tags are built up from a list of frames, which are in turn + * have a header and a list of fields. TagLib provides two ways of accessing + * the list of frames that are in a given ID3v2 tag. The first is simply + * via the frameList() method. This is just a list of pointers to the frames. + * The second is a map from the frame type -- i.e. "COMM" for comments -- and + * a list of frames of that type. (In some cases ID3v2 allows for multiple + * frames of the same type, hence this being a map to a list rather than just + * a map to an individual frame.) + * + * More information on the structure of frames can be found in the ID3v2::Frame + * class. + * + * read() and parse() pass binary data to the other ID3v2 class structures, + * they do not handle parsing of flags or fields, for instace. Those are + * handled by similar functions within those classes. + * + * \note All pointers to data structures within the tag will become invalid + * when the tag is destroyed. + * + * \warning Dealing with the nasty details of ID3v2 is not for the faint of + * heart and should not be done without much meditation on the spec. It's + * rather long, but if you're planning on messing with this class and others + * that deal with the details of ID3v2 (rather than the nice, safe, abstract + * TagLib::Tag and friends), it's worth your time to familiarize yourself + * with said spec (which is distrubuted with the TagLib sources). TagLib + * tries to do most of the work, but with a little luck, you can still + * convince it to generate invalid ID3v2 tags. The APIs for ID3v2 assume a + * working knowledge of ID3v2 structure. You're been warned. + */ + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Constructs an empty ID3v2 tag. + * + * \note You must create at least one frame for this tag to be valid. + */ + Tag(); + + /*! + * Constructs an ID3v2 tag read from \a file starting at \a tagOffset. + * \a factory specifies which FrameFactory will be used for the + * construction of new frames. + * + * \note You should be able to ignore the \a factory parameter in almost + * all situations. You would want to specify your own FrameFactory + * subclass in the case that you are extending TagLib to support additional + * frame types, which would be incorperated into your factory. + * + * \see FrameFactory + */ + Tag(File *file, long tagOffset, + const FrameFactory *factory = FrameFactory::instance()); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual uint year() const; + virtual uint track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(uint i); + virtual void setTrack(uint i); + + virtual bool isEmpty() const; + + /*! + * Returns a pointer to the tag's header. + */ + Header *header() const; + + /*! + * Returns a pointer to the tag's extended header or null if there is no + * extended header. + */ + ExtendedHeader *extendedHeader() const; + + /*! + * Returns a pointer to the tag's footer or null if there is no footer. + * + * \deprecated I don't see any reason to keep this around since there's + * nothing useful to be retrieved from the footer, but well, again, I'm + * prone to change my mind, so this gets to stay around until near a + * release. + */ + Footer *footer() const; + + /*! + * Returns a reference to the frame list map. This is an FrameListMap of + * all of the frames in the tag. + * + * This is the most convenient structure for accessing the tag's frames. + * Many frame types allow multiple instances of the same frame type so this + * is a map of lists. In most cases however there will only be a single + * frame of a certain type. + * + * Let's say for instance that you wanted to access the frame for total + * beats per minute -- the TBPM frame. + * + * \code + * TagLib::MPEG::File f("foo.mp3"); + * + * // Check to make sure that it has an ID3v2 tag + * + * if(f.ID3v2Tag()) { + * + * // Get the list of frames for a specific frame type + * + * TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"]; + * + * if(!l.isEmpty()) + * std::cout << l.front()->toString() << std::endl; + * } + * + * \endcode + * + * \warning You should not modify this data structure directly, instead + * use addFrame() and removeFrame(). + * + * \see frameList() + */ + const FrameListMap &frameListMap() const; + + /*! + * Returns a reference to the frame list. This is an FrameList of all of + * the frames in the tag in the order that they were parsed. + * + * This can be useful if for example you want iterate over the tag's frames + * in the order that they occur in the tag. + * + * \warning You should not modify this data structure directly, instead + * use addFrame() and removeFrame(). + */ + const FrameList &frameList() const; + + /*! + * Returns the frame list for frames with the id \a frameID or an empty + * list if there are no frames of that type. This is just a convenience + * and is equivalent to: + * + * \code + * frameListMap()[frameID]; + * \endcode + * + * \see frameListMap() + */ + const FrameList &frameList(const ByteVector &frameID) const; + + /*! + * Add a frame to the tag. At this point the tag takes ownership of + * the frame and will handle freeing its memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void addFrame(Frame *frame); + + /*! + * Remove a frame from the tag. If \a del is true the frame's memory + * will be freed; if it is false, it must be deleted by the user. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void removeFrame(Frame *frame, bool del = true); + + /*! + * Remove all frames of type \a id from the tag and free their memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void removeFrames(const ByteVector &id); + + /*! + * Render the tag back to binary data, suitable to be written to disk. + */ + ByteVector render() const; + + protected: + /*! + * Reads data from the file specified in the constructor. It does basic + * parsing of the data in the largest chunks. It partitions the tag into + * the Header, the body of the tag (which contains the ExtendedHeader and + * frames) and Footer. + */ + void read(); + + /*! + * This is called by read to parse the body of the tag. It determines if an + * extended header exists and adds frames to the FrameListMap. + */ + void parse(const ByteVector &data); + + /*! + * Sets the value of the text frame with the Frame ID \a id to \a value. + * If the frame does not exist, it is created. + */ + void setTextFrame(const ByteVector &id, const String &value); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.cpp new file mode 100644 index 00000000..2fc1b380 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.cpp @@ -0,0 +1,593 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mpegfile.h" +#include "mpegheader.h" + +using namespace TagLib; + +namespace +{ + enum { ID3v2Index = 0, APEIndex = 1, ID3v1Index = 2 }; +} + +class MPEG::File::FilePrivate +{ +public: + FilePrivate(ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : + ID3v2FrameFactory(frameFactory), + ID3v2Location(-1), + ID3v2OriginalSize(0), + APELocation(-1), + APEFooterLocation(-1), + APEOriginalSize(0), + ID3v1Location(-1), + hasID3v2(false), + hasID3v1(false), + hasAPE(false), + properties(0) + { + + } + + ~FilePrivate() + { + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + + long ID3v2Location; + uint ID3v2OriginalSize; + + long APELocation; + long APEFooterLocation; + uint APEOriginalSize; + + long ID3v1Location; + + TagUnion tag; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasID3v2; + bool hasID3v1; + bool hasAPE; + + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPEG::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + + if(isOpen()) + read(readProperties, propertiesStyle); +} + +MPEG::File::File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate(frameFactory); + + if(isOpen()) + read(readProperties, propertiesStyle); +} + +MPEG::File::~File() +{ + delete d; +} + +TagLib::Tag *MPEG::File::tag() const +{ + return &d->tag; +} + +MPEG::Properties *MPEG::File::audioProperties() const +{ + return d->properties; +} + +bool MPEG::File::save() +{ + return save(AllTags); +} + +bool MPEG::File::save(int tags) +{ + return save(tags, true); +} + +bool MPEG::File::save(int tags, bool stripOthers) +{ + if(tags == NoTags && stripOthers) + return strip(AllTags); + + if(!ID3v2Tag() && !ID3v1Tag() && !APETag()) { + + if((d->hasID3v1 || d->hasID3v2 || d->hasAPE) && stripOthers) + return strip(AllTags); + + return true; + } + + if(readOnly()) { + debug("MPEG::File::save() -- File is read only."); + return false; + } + + // Create the tags if we've been asked to. Copy the values from the tag that + // does exist into the new tag. + + if((tags & ID3v2) && ID3v1Tag()) + Tag::duplicate(ID3v1Tag(), ID3v2Tag(true), false); + + if((tags & ID3v1) && d->tag[ID3v2Index]) + Tag::duplicate(ID3v2Tag(), ID3v1Tag(true), false); + + bool success = true; + + if(ID3v2 & tags) { + + if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) { + + if(!d->hasID3v2) + d->ID3v2Location = 0; + + insert(ID3v2Tag()->render(), d->ID3v2Location, d->ID3v2OriginalSize); + + d->hasID3v2 = true; + + // v1 tag location has changed, update if it exists + + if(ID3v1Tag()) + d->ID3v1Location = findID3v1(); + + // APE tag location has changed, update if it exists + + if(APETag()) + findAPE(); + } + else if(stripOthers) + success = strip(ID3v2, false) && success; + } + else if(d->hasID3v2 && stripOthers) + success = strip(ID3v2) && success; + + if(ID3v1 & tags) { + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + int offset = d->hasID3v1 ? -128 : 0; + seek(offset, End); + writeBlock(ID3v1Tag()->render()); + d->hasID3v1 = true; + d->ID3v1Location = findID3v1(); + } + else if(stripOthers) + success = strip(ID3v1) && success; + } + else if(d->hasID3v1 && stripOthers) + success = strip(ID3v1, false) && success; + + // Dont save an APE-tag unless one has been created + + if((APE & tags) && APETag()) { + if(d->hasAPE) + insert(APETag()->render(), d->APELocation, d->APEOriginalSize); + else { + if(d->hasID3v1) { + insert(APETag()->render(), d->ID3v1Location, 0); + d->APEOriginalSize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + d->APELocation = d->ID3v1Location; + d->ID3v1Location += d->APEOriginalSize; + } + else { + seek(0, End); + d->APELocation = tell(); + d->APEFooterLocation = d->APELocation + + d->tag.access(APEIndex, false)->footer()->completeTagSize() + - APE::Footer::size(); + writeBlock(APETag()->render()); + d->APEOriginalSize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + } + } + } + else if(d->hasAPE && stripOthers) + success = strip(APE, false) && success; + + return success; +} + +ID3v2::Tag *MPEG::File::ID3v2Tag(bool create) +{ + return d->tag.access(ID3v2Index, create); +} + +ID3v1::Tag *MPEG::File::ID3v1Tag(bool create) +{ + return d->tag.access(ID3v1Index, create); +} + +APE::Tag *MPEG::File::APETag(bool create) +{ + return d->tag.access(APEIndex, create); +} + +bool MPEG::File::strip(int tags) +{ + return strip(tags, true); +} + +bool MPEG::File::strip(int tags, bool freeMemory) +{ + if(readOnly()) { + debug("MPEG::File::strip() - Cannot strip tags from a read only file."); + return false; + } + + if((tags & ID3v2) && d->hasID3v2) { + removeBlock(d->ID3v2Location, d->ID3v2OriginalSize); + d->ID3v2Location = -1; + d->ID3v2OriginalSize = 0; + d->hasID3v2 = false; + + if(freeMemory) + d->tag.set(ID3v2Index, 0); + + // v1 tag location has changed, update if it exists + + if(ID3v1Tag()) + d->ID3v1Location = findID3v1(); + + // APE tag location has changed, update if it exists + + if(APETag()) + findAPE(); + } + + if((tags & ID3v1) && d->hasID3v1) { + truncate(d->ID3v1Location); + d->ID3v1Location = -1; + d->hasID3v1 = false; + + if(freeMemory) + d->tag.set(ID3v1Index, 0); + } + + if((tags & APE) && d->hasAPE) { + removeBlock(d->APELocation, d->APEOriginalSize); + d->APELocation = -1; + d->APEFooterLocation = -1; + d->hasAPE = false; + if(d->hasID3v1) { + if(d->ID3v1Location > d->APELocation) + d->ID3v1Location -= d->APEOriginalSize; + } + + if(freeMemory) + d->tag.set(APEIndex, 0); + } + + return true; +} + +void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + +long MPEG::File::nextFrameOffset(long position) +{ + bool foundLastSyncPattern = false; + + ByteVector buffer; + + while(true) { + seek(position); + buffer = readBlock(bufferSize()); + + if(buffer.size() <= 0) + return -1; + + if(foundLastSyncPattern && secondSynchByte(buffer[0])) + return position - 1; + + for(uint i = 0; i < buffer.size() - 1; i++) { + if(uchar(buffer[i]) == 0xff && secondSynchByte(buffer[i + 1])) + return position + i; + } + + foundLastSyncPattern = uchar(buffer[buffer.size() - 1]) == 0xff; + position += buffer.size(); + } +} + +long MPEG::File::previousFrameOffset(long position) +{ + bool foundFirstSyncPattern = false; + ByteVector buffer; + + while (position > 0) { + long size = ulong(position) < bufferSize() ? position : bufferSize(); + position -= size; + + seek(position); + buffer = readBlock(size); + + if(buffer.size() <= 0) + break; + + if(foundFirstSyncPattern && uchar(buffer[buffer.size() - 1]) == 0xff) + return position + buffer.size() - 1; + + for(int i = buffer.size() - 2; i >= 0; i--) { + if(uchar(buffer[i]) == 0xff && secondSynchByte(buffer[i + 1])) + return position + i; + } + + foundFirstSyncPattern = secondSynchByte(buffer[0]); + } + return -1; +} + +long MPEG::File::firstFrameOffset() +{ + long position = 0; + + if(ID3v2Tag()) + position = d->ID3v2Location + ID3v2Tag()->header()->completeTagSize(); + + return nextFrameOffset(position); +} + +long MPEG::File::lastFrameOffset() +{ + return previousFrameOffset(ID3v1Tag() ? d->ID3v1Location - 1 : length()); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + + d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory)); + + d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize(); + + if(ID3v2Tag()->header()->tagSize() <= 0) + d->tag.set(ID3v2Index, 0); + else + d->hasID3v2 = true; + } + + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + d->hasID3v1 = true; + } + + // Look for an APE tag + + findAPE(); + + if(d->APELocation >= 0) { + + d->tag.set(APEIndex, new APE::Tag(this, d->APEFooterLocation)); + d->APEOriginalSize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + } + + if(readProperties) + d->properties = new Properties(this, propertiesStyle); + + // Make sure that we have our default tag types available. + + ID3v2Tag(true); + ID3v1Tag(true); +} + +long MPEG::File::findID3v2() +{ + // This method is based on the contents of TagLib::File::find(), but because + // of some subtlteies -- specifically the need to look for the bit pattern of + // an MPEG sync, it has been modified for use here. + + if(isValid() && ID3v2::Header::fileIdentifier().size() <= bufferSize()) { + + // The position in the file that the current buffer starts at. + + long bufferOffset = 0; + ByteVector buffer; + + // These variables are used to keep track of a partial match that happens at + // the end of a buffer. + + int previousPartialMatch = -1; + bool previousPartialSynchMatch = false; + + // Save the location of the current read pointer. We will restore the + // position using seek() before all returns. + + long originalPosition = tell(); + + // Start the search at the beginning of the file. + + seek(0); + + // This loop is the crux of the find method. There are three cases that we + // want to account for: + // (1) The previously searched buffer contained a partial match of the search + // pattern and we want to see if the next one starts with the remainder of + // that pattern. + // + // (2) The search pattern is wholly contained within the current buffer. + // + // (3) The current buffer ends with a partial match of the pattern. We will + // note this for use in the next itteration, where we will check for the rest + // of the pattern. + + for(buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) { + + // (1) previous partial match + + if(previousPartialSynchMatch && secondSynchByte(buffer[0])) + return -1; + + if(previousPartialMatch >= 0 && int(bufferSize()) > previousPartialMatch) { + const int patternOffset = (bufferSize() - previousPartialMatch); + if(buffer.containsAt(ID3v2::Header::fileIdentifier(), 0, patternOffset)) { + seek(originalPosition); + return bufferOffset - bufferSize() + previousPartialMatch; + } + } + + // (2) pattern contained in current buffer + + long location = buffer.find(ID3v2::Header::fileIdentifier()); + if(location >= 0) { + seek(originalPosition); + return bufferOffset + location; + } + + int firstSynchByte = buffer.find(char(uchar(255))); + + // Here we have to loop because there could be several of the first + // (11111111) byte, and we want to check all such instances until we find + // a full match (11111111 111) or hit the end of the buffer. + + while(firstSynchByte >= 0) { + + // if this *is not* at the end of the buffer + + if(firstSynchByte < int(buffer.size()) - 1) { + if(secondSynchByte(buffer[firstSynchByte + 1])) { + // We've found the frame synch pattern. + seek(originalPosition); + return -1; + } + else { + + // We found 11111111 at the end of the current buffer indicating a + // partial match of the synch pattern. The find() below should + // return -1 and break out of the loop. + + previousPartialSynchMatch = true; + } + } + + // Check in the rest of the buffer. + + firstSynchByte = buffer.find(char(uchar(255)), firstSynchByte + 1); + } + + // (3) partial match + + previousPartialMatch = buffer.endsWithPartialMatch(ID3v2::Header::fileIdentifier()); + + bufferOffset += bufferSize(); + } + + // Since we hit the end of the file, reset the status before continuing. + + clear(); + + seek(originalPosition); + } + + return -1; +} + +long MPEG::File::findID3v1() +{ + if(isValid()) { + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + } + return -1; +} + +void MPEG::File::findAPE() +{ + if(isValid()) { + seek(d->hasID3v1 ? -160 : -32, End); + + long p = tell(); + + if(readBlock(8) == APE::Tag::fileIdentifier()) { + d->APEFooterLocation = p; + seek(d->APEFooterLocation); + APE::Footer footer(readBlock(APE::Footer::size())); + d->APELocation = d->APEFooterLocation - footer.completeTagSize() + + APE::Footer::size(); + return; + } + } + + d->APELocation = -1; + d->APEFooterLocation = -1; +} + +bool MPEG::File::secondSynchByte(char byte) +{ + if(uchar(byte) == 0xff) + return false; + + std::bitset<8> b(byte); + + // check to see if the byte matches 111xxxxx + return b.test(7) && b.test(6) && b.test(5); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.h b/Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.h new file mode 100644 index 00000000..282af775 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/mpegfile.h @@ -0,0 +1,277 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGFILE_H +#define TAGLIB_MPEGFILE_H + +#include "taglib_export.h" +#include "tfile.h" + +#include "mpegproperties.h" + +namespace TagLib { + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of TagLib::File with MPEG (MP3) specific methods + + namespace MPEG { + + //! An MPEG file class with some useful methods specific to MPEG + + /*! + * This implements the generic TagLib::File API and additionally provides + * access to properties that are distinct to MPEG files, notably access + * to the different ID3 tags. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches APE tags. + APE = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * 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. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * 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. + */ + // BIC: merge with the above constructor + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to a tag that is the union of the ID3v2 and ID3v1 + * tags. The ID3v2 tag is given priority in reading the information -- if + * requested information exists in both the ID3v2 tag and the ID3v1 tag, + * the information from the ID3v2 tag will be returned. + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use the tag-type specific calls. + * + * \note As this tag is not implemented as an ID3v2 tag or an ID3v1 tag, + * but a union of the two this pointer may not be cast to the specific + * tag types. + * + * \see ID3v1Tag() + * \see ID3v2Tag() + * \see APETag() + */ + virtual Tag *tag() const; + + /*! + * Returns the MPEG::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. If at least one tag -- ID3v1 or ID3v2 -- exists this + * will duplicate its content into the other tag. This returns true + * if saving was successful. + * + * If neither exists or if both tags are empty, this will strip the tags + * from the file. + * + * This is the same as calling save(AllTags); + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use paramaterized save call below. + * + * \see save(int tags) + */ + virtual bool save(); + + /*! + * Save the file. This will attempt to save all of the tag types that are + * specified by OR-ing together TagTypes values. The save() method above + * uses AllTags. This returns true if saving was successful. + * + * This strips all tags not included in the mask, but does not modify them + * in memory, so later calls to save() which make use of these tags will + * remain valid. This also strips empty tags. + */ + bool save(int tags); + + /*! + * Save the file. This will attempt to save all of the tag types that are + * specified by OR-ing together TagTypes values. The save() method above + * uses AllTags. This returns true if saving was successful. + * + * If \a stripOthers is true this strips all tags not included in the mask, + * but does not modify them in memory, so later calls to save() which make + * use of these tags will remain valid. This also strips empty tags. + */ + // BIC: combine with the above method + bool save(int tags, bool stripOthers); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * This is equivalent to strip(tags, true) + * + * \note This will also invalidate pointers to the ID3 and APE tags + * as their memory will be freed. + */ + bool strip(int tags = AllTags); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * If \a freeMemory is true the ID3 and APE tags will be deleted and + * pointers to them will be invalidated. + */ + // BIC: merge with the method above + bool strip(int tags, bool freeMemory); + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + */ + void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Returns the position in the file of the first MPEG frame. + */ + long firstFrameOffset(); + + /*! + * Returns the position in the file of the next MPEG frame, + * using the current position as start + */ + long nextFrameOffset(long position); + + /*! + * Returns the position in the file of the previous MPEG frame, + * using the current position as start + */ + long previousFrameOffset(long position); + + /*! + * Returns the position in the file of the last MPEG frame. + */ + long lastFrameOffset(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + long findID3v2(); + long findID3v1(); + void findAPE(); + + /*! + * MPEG frames can be recognized by the bit pattern 11111111 111, so the + * first byte is easy to check for, however checking to see if the second byte + * starts with \e 111 is a bit more tricky, hence this member function. + */ + static bool secondSynchByte(char byte); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.cpp new file mode 100644 index 00000000..c715dbc1 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.cpp @@ -0,0 +1,276 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include +#include + +#include "mpegheader.h" + +using namespace TagLib; + +class MPEG::Header::HeaderPrivate : public RefCounter +{ +public: + HeaderPrivate() : + isValid(false), + version(Version1), + layer(0), + protectionEnabled(false), + sampleRate(0), + isPadded(false), + channelMode(Stereo), + isCopyrighted(false), + isOriginal(false), + frameLength(0), + samplesPerFrame(0) {} + + bool isValid; + Version version; + int layer; + bool protectionEnabled; + int bitrate; + int sampleRate; + bool isPadded; + ChannelMode channelMode; + bool isCopyrighted; + bool isOriginal; + int frameLength; + int samplesPerFrame; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPEG::Header::Header(const ByteVector &data) +{ + d = new HeaderPrivate; + parse(data); +} + +MPEG::Header::Header(const Header &h) : d(h.d) +{ + d->ref(); +} + +MPEG::Header::~Header() +{ + if (d->deref()) + delete d; +} + +bool MPEG::Header::isValid() const +{ + return d->isValid; +} + +MPEG::Header::Version MPEG::Header::version() const +{ + return d->version; +} + +int MPEG::Header::layer() const +{ + return d->layer; +} + +bool MPEG::Header::protectionEnabled() const +{ + return d->protectionEnabled; +} + +int MPEG::Header::bitrate() const +{ + return d->bitrate; +} + +int MPEG::Header::sampleRate() const +{ + return d->sampleRate; +} + +bool MPEG::Header::isPadded() const +{ + return d->isPadded; +} + +MPEG::Header::ChannelMode MPEG::Header::channelMode() const +{ + return d->channelMode; +} + +bool MPEG::Header::isCopyrighted() const +{ + return d->isCopyrighted; +} + +bool MPEG::Header::isOriginal() const +{ + return d->isOriginal; +} + +int MPEG::Header::frameLength() const +{ + return d->frameLength; +} + +int MPEG::Header::samplesPerFrame() const +{ + return d->samplesPerFrame; +} + +MPEG::Header &MPEG::Header::operator=(const Header &h) +{ + if(&h == this) + return *this; + + if(d->deref()) + delete d; + + d = h.d; + d->ref(); + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPEG::Header::parse(const ByteVector &data) +{ + if(data.size() < 4 || uchar(data[0]) != 0xff) { + debug("MPEG::Header::parse() -- First byte did not match MPEG synch."); + return; + } + + std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt())); + + // Check for the second byte's part of the MPEG synch + + if(!flags[23] || !flags[22] || !flags[21]) { + debug("MPEG::Header::parse() -- Second byte did not match MPEG synch."); + return; + } + + // Set the MPEG version + + if(!flags[20] && !flags[19]) + d->version = Version2_5; + else if(flags[20] && !flags[19]) + d->version = Version2; + else if(flags[20] && flags[19]) + d->version = Version1; + + // Set the MPEG layer + + if(!flags[18] && flags[17]) + d->layer = 3; + else if(flags[18] && !flags[17]) + d->layer = 2; + else if(flags[18] && flags[17]) + d->layer = 1; + + d->protectionEnabled = !flags[16]; + + // Set the bitrate + + static const int bitrates[2][3][16] = { + { // Version 1 + { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // layer 1 + { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }, // layer 2 + { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 } // layer 3 + }, + { // Version 2 or 2.5 + { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, // layer 1 + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, // layer 2 + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 } // layer 3 + } + }; + + const int versionIndex = d->version == Version1 ? 0 : 1; + const int layerIndex = d->layer > 0 ? d->layer - 1 : 0; + + // The bitrate index is encoded as the first 4 bits of the 3rd byte, + // i.e. 1111xxxx + + int i = uchar(data[2]) >> 4; + + d->bitrate = bitrates[versionIndex][layerIndex][i]; + + // Set the sample rate + + static const int sampleRates[3][4] = { + { 44100, 48000, 32000, 0 }, // Version 1 + { 22050, 24000, 16000, 0 }, // Version 2 + { 11025, 12000, 8000, 0 } // Version 2.5 + }; + + // The sample rate index is encoded as two bits in the 3nd byte, i.e. xxxx11xx + + i = uchar(data[2]) >> 2 & 0x03; + + d->sampleRate = sampleRates[d->version][i]; + + if(d->sampleRate == 0) { + debug("MPEG::Header::parse() -- Invalid sample rate."); + return; + } + + // The channel mode is encoded as a 2 bit value at the end of the 3nd byte, + // i.e. xxxxxx11 + + d->channelMode = ChannelMode((uchar(data[3]) & 0xC0) >> 6); + + // TODO: Add mode extension for completeness + + d->isOriginal = flags[2]; + d->isCopyrighted = flags[3]; + d->isPadded = flags[9]; + + // Calculate the frame length + + if(d->layer == 1) + d->frameLength = 24000 * 2 * d->bitrate / d->sampleRate + int(d->isPadded); + else + d->frameLength = 72000 * d->bitrate / d->sampleRate + int(d->isPadded); + + // Samples per frame + + static const int samplesPerFrame[3][2] = { + // MPEG1, 2/2.5 + { 384, 384 }, // Layer I + { 1152, 1152 }, // Layer II + { 1152, 576 } // Layer III + }; + + d->samplesPerFrame = samplesPerFrame[layerIndex][versionIndex]; + + // Now that we're done parsing, set this to be a valid frame. + + d->isValid = true; +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.h b/Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.h new file mode 100644 index 00000000..020ebd06 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/mpegheader.h @@ -0,0 +1,166 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGHEADER_H +#define TAGLIB_MPEGHEADER_H + +#include "taglib_export.h" + +namespace TagLib { + + class ByteVector; + + namespace MPEG { + + //! An implementation of MP3 frame headers + + /*! + * This is an implementation of MPEG Layer III headers. The API follows more + * or less the binary format of these headers. I've used + * this + * document as a reference. + */ + + class TAGLIB_EXPORT Header + { + public: + /*! + * Parses an MPEG header based on \a data. + */ + Header(const ByteVector &data); + + /*! + * Does a shallow copy of \a h. + */ + Header(const Header &h); + + /*! + * Destroys this Header instance. + */ + virtual ~Header(); + + /*! + * Returns true if the frame is at least an appropriate size and has + * legal values. + */ + bool isValid() const; + + /*! + * The MPEG Version. + */ + enum Version { + //! MPEG Version 1 + Version1 = 0, + //! MPEG Version 2 + Version2 = 1, + //! MPEG Version 2.5 + Version2_5 = 2 + }; + + /*! + * Returns the MPEG Version of the header. + */ + Version version() const; + + /*! + * Returns the layer version. This will be between the values 1-3. + */ + int layer() const; + + /*! + * Returns true if the MPEG protection bit is enabled. + */ + bool protectionEnabled() const; + + /*! + * Returns the bitrate encoded in the header. + */ + int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + int sampleRate() const; + + /*! + * Returns true if the frame is padded. + */ + bool isPadded() const; + + /*! + * There are a few combinations or one or two channel audio that are + * possible: + */ + enum ChannelMode { + //! Stereo + Stereo = 0, + //! Stereo + JointStereo = 1, + //! Dual Mono + DualChannel = 2, + //! Mono + SingleChannel = 3 + }; + + /*! + * Returns the channel mode for this frame. + */ + ChannelMode channelMode() const; + + /*! + * Returns true if the copyrighted bit is set. + */ + bool isCopyrighted() const; + + /*! + * Returns true if the "original" bit is set. + */ + bool isOriginal() const; + + /*! + * Returns the frame length. + */ + int frameLength() const; + + /*! + * Returns the number of frames per sample. + */ + int samplesPerFrame() const; + + /*! + * Makes a shallow copy of the header. + */ + Header &operator=(const Header &h); + + private: + void parse(const ByteVector &data); + + class HeaderPrivate; + HeaderPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.cpp new file mode 100644 index 00000000..028ee061 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.cpp @@ -0,0 +1,254 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "mpegproperties.h" +#include "mpegfile.h" +#include "xingheader.h" + +using namespace TagLib; + +class MPEG::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(File *f, ReadStyle s) : + file(f), + xingHeader(0), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + layer(0), + version(Header::Version1), + channelMode(Header::Stereo), + protectionEnabled(false), + isCopyrighted(false), + isOriginal(false) {} + + ~PropertiesPrivate() + { + delete xingHeader; + } + + File *file; + XingHeader *xingHeader; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int layer; + Header::Version version; + Header::ChannelMode channelMode; + bool protectionEnabled; + bool isCopyrighted; + bool isOriginal; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPEG::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file, style); + + if(file && file->isOpen()) + read(); +} + +MPEG::Properties::~Properties() +{ + delete d; +} + +int MPEG::Properties::length() const +{ + return d->length; +} + +int MPEG::Properties::bitrate() const +{ + return d->bitrate; +} + +int MPEG::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int MPEG::Properties::channels() const +{ + return d->channels; +} + +const MPEG::XingHeader *MPEG::Properties::xingHeader() const +{ + return d->xingHeader; +} + +MPEG::Header::Version MPEG::Properties::version() const +{ + return d->version; +} + +int MPEG::Properties::layer() const +{ + return d->layer; +} + +bool MPEG::Properties::protectionEnabled() const +{ + return d->protectionEnabled; +} + +MPEG::Header::ChannelMode MPEG::Properties::channelMode() const +{ + return d->channelMode; +} + +bool MPEG::Properties::isCopyrighted() const +{ + return d->isCopyrighted; +} + +bool MPEG::Properties::isOriginal() const +{ + return d->isOriginal; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPEG::Properties::read() +{ + // Since we've likely just looked for the ID3v1 tag, start at the end of the + // file where we're least likely to have to have to move the disk head. + + long last = d->file->lastFrameOffset(); + + if(last < 0) { + debug("MPEG::Properties::read() -- Could not find a valid last MPEG frame in the stream."); + return; + } + + d->file->seek(last); + Header lastHeader(d->file->readBlock(4)); + + long first = d->file->firstFrameOffset(); + + if(first < 0) { + debug("MPEG::Properties::read() -- Could not find a valid first MPEG frame in the stream."); + return; + } + + if(!lastHeader.isValid()) { + + long pos = last; + + while(pos > first) { + + pos = d->file->previousFrameOffset(pos); + + if(pos < 0) + break; + + d->file->seek(pos); + Header header(d->file->readBlock(4)); + + if(header.isValid()) { + lastHeader = header; + last = pos; + break; + } + } + } + + // Now jump back to the front of the file and read what we need from there. + + d->file->seek(first); + Header firstHeader(d->file->readBlock(4)); + + if(!firstHeader.isValid() || !lastHeader.isValid()) { + debug("MPEG::Properties::read() -- Page headers were invalid."); + return; + } + + // Check for a Xing header that will help us in gathering information about a + // VBR stream. + + int xingHeaderOffset = MPEG::XingHeader::xingHeaderOffset(firstHeader.version(), + firstHeader.channelMode()); + + d->file->seek(first + xingHeaderOffset); + d->xingHeader = new XingHeader(d->file->readBlock(16)); + + // Read the length and the bitrate from the Xing header. + + if(d->xingHeader->isValid() && + firstHeader.sampleRate() > 0 && + d->xingHeader->totalFrames() > 0) + { + double timePerFrame = + double(firstHeader.samplesPerFrame()) / firstHeader.sampleRate(); + + double length = timePerFrame * d->xingHeader->totalFrames(); + + d->length = int(length); + d->bitrate = d->length > 0 ? d->xingHeader->totalSize() * 8 / length / 1000 : 0; + } + else { + // Since there was no valid Xing header found, we hope that we're in a constant + // bitrate file. + + delete d->xingHeader; + d->xingHeader = 0; + + // TODO: Make this more robust with audio property detection for VBR without a + // Xing header. + + if(firstHeader.frameLength() > 0 && firstHeader.bitrate() > 0) { + int frames = (last - first) / firstHeader.frameLength() + 1; + + d->length = int(float(firstHeader.frameLength() * frames) / + float(firstHeader.bitrate() * 125) + 0.5); + d->bitrate = firstHeader.bitrate(); + } + } + + + d->sampleRate = firstHeader.sampleRate(); + d->channels = firstHeader.channelMode() == Header::SingleChannel ? 1 : 2; + d->version = firstHeader.version(); + d->layer = firstHeader.layer(); + d->protectionEnabled = firstHeader.protectionEnabled(); + d->channelMode = firstHeader.channelMode(); + d->isCopyrighted = firstHeader.isCopyrighted(); + d->isOriginal = firstHeader.isOriginal(); +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.h b/Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.h new file mode 100644 index 00000000..72e594ff --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/mpegproperties.h @@ -0,0 +1,118 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGPROPERTIES_H +#define TAGLIB_MPEGPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +#include "mpegheader.h" + +namespace TagLib { + + namespace MPEG { + + class File; + class XingHeader; + + //! An implementation of audio property reading for MP3 + + /*! + * This reads the data from an MPEG Layer III stream found in the + * AudioProperties API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of MPEG::Properties with the data read from the + * MPEG::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this MPEG Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns a pointer to the XingHeader if one exists or null if no + * XingHeader was found. + */ + + const XingHeader *xingHeader() const; + + /*! + * Returns the MPEG Version of the file. + */ + Header::Version version() const; + + /*! + * Returns the layer version. This will be between the values 1-3. + */ + int layer() const; + + /*! + * Returns true if the MPEG protection bit is enabled. + */ + bool protectionEnabled() const; + + /*! + * Returns the channel mode for this frame. + */ + Header::ChannelMode channelMode() const; + + /*! + * Returns true if the copyrighted bit is set. + */ + bool isCopyrighted() const; + + /*! + * Returns true if the "original" bit is set. + */ + bool isOriginal() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/xingheader.cpp b/Plugins/PluginNowPlaying/taglib/mpeg/xingheader.cpp new file mode 100644 index 00000000..1ba932de --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/xingheader.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + copyright : (C) 2003 by Ismael Orenstein + email : orenstein@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "xingheader.h" + +using namespace TagLib; + +class MPEG::XingHeader::XingHeaderPrivate +{ +public: + XingHeaderPrivate() : + frames(0), + size(0), + valid(false) + {} + + uint frames; + uint size; + bool valid; +}; + +MPEG::XingHeader::XingHeader(const ByteVector &data) +{ + d = new XingHeaderPrivate; + parse(data); +} + +MPEG::XingHeader::~XingHeader() +{ + delete d; +} + +bool MPEG::XingHeader::isValid() const +{ + return d->valid; +} + +TagLib::uint MPEG::XingHeader::totalFrames() const +{ + return d->frames; +} + +TagLib::uint MPEG::XingHeader::totalSize() const +{ + return d->size; +} + +int MPEG::XingHeader::xingHeaderOffset(TagLib::MPEG::Header::Version v, + TagLib::MPEG::Header::ChannelMode c) +{ + if(v == MPEG::Header::Version1) { + if(c == MPEG::Header::SingleChannel) + return 0x15; + else + return 0x24; + } + else { + if(c == MPEG::Header::SingleChannel) + return 0x0D; + else + return 0x15; + } +} + +void MPEG::XingHeader::parse(const ByteVector &data) +{ + // Check to see if a valid Xing header is available. + + if(!data.startsWith("Xing") && !data.startsWith("Info")) + return; + + // If the XingHeader doesn't contain the number of frames and the total stream + // info it's invalid. + + if(!(data[7] & 0x01)) { + debug("MPEG::XingHeader::parse() -- Xing header doesn't contain the total number of frames."); + return; + } + + if(!(data[7] & 0x02)) { + debug("MPEG::XingHeader::parse() -- Xing header doesn't contain the total stream size."); + return; + } + + d->frames = data.mid(8, 4).toUInt(); + d->size = data.mid(12, 4).toUInt(); + + d->valid = true; +} diff --git a/Plugins/PluginNowPlaying/taglib/mpeg/xingheader.h b/Plugins/PluginNowPlaying/taglib/mpeg/xingheader.h new file mode 100644 index 00000000..ffe7494d --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/mpeg/xingheader.h @@ -0,0 +1,100 @@ +/*************************************************************************** + copyright : (C) 2003 by Ismael Orenstein + email : orenstein@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_XINGHEADER_H +#define TAGLIB_XINGHEADER_H + +#include "mpegheader.h" +#include "taglib_export.h" + +namespace TagLib { + + class ByteVector; + + namespace MPEG { + + //! An implementation of the Xing VBR headers + + /*! + * This is a minimalistic implementation of the Xing VBR headers. Xing + * headers are often added to VBR (variable bit rate) MP3 streams to make it + * easy to compute the length and quality of a VBR stream. Our implementation + * is only concerned with the total size of the stream (so that we can + * calculate the total playing time and the average bitrate). It uses + * this text + * and the XMMS sources as references. + */ + + class TAGLIB_EXPORT XingHeader + { + public: + /*! + * Parses a Xing header based on \a data. The data must be at least 16 + * bytes long (anything longer than this is discarded). + */ + XingHeader(const ByteVector &data); + + /*! + * Destroy this XingHeader instance. + */ + virtual ~XingHeader(); + + /*! + * Returns true if the data was parsed properly and if there is a valid + * Xing header present. + */ + bool isValid() const; + + /*! + * Returns the total number of frames. + */ + uint totalFrames() const; + + /*! + * Returns the total size of stream in bytes. + */ + uint totalSize() const; + + /*! + * Returns the offset for the start of this Xing header, given the + * version and channels of the frame + */ + // BIC: rename to offset() + static int xingHeaderOffset(TagLib::MPEG::Header::Version v, + TagLib::MPEG::Header::ChannelMode c); + + private: + XingHeader(const XingHeader &); + XingHeader &operator=(const XingHeader &); + + void parse(const ByteVector &data); + + class XingHeaderPrivate; + XingHeaderPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.cpp b/Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.cpp new file mode 100644 index 00000000..22d7b81f --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.cpp @@ -0,0 +1,269 @@ +/*************************************************************************** + copyright : (C) 2004-2005 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include +#include "oggflacfile.h" + +using namespace TagLib; +using TagLib::FLAC::Properties; + +class Ogg::FLAC::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0), + streamStart(0), + streamLength(0), + scanned(false), + hasXiphComment(false), + commentPacket(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + + Properties *properties; + ByteVector streamInfoData; + ByteVector xiphCommentData; + long streamStart; + long streamLength; + bool scanned; + + bool hasXiphComment; + int commentPacket; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::FLAC::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +Ogg::FLAC::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Ogg::FLAC::File::tag() const +{ + return d->comment; +} + +Properties *Ogg::FLAC::File::audioProperties() const +{ + return d->properties; +} + + +bool Ogg::FLAC::File::save() +{ + d->xiphCommentData = d->comment->render(false); + + // Create FLAC metadata-block: + + // Put the size in the first 32 bit (I assume no more than 24 bit are used) + + ByteVector v = ByteVector::fromUInt(d->xiphCommentData.size()); + + // Set the type of the metadata-block to be a Xiph / Vorbis comment + + v[0] = 4; + + // Append the comment-data after the 32 bit header + + v.append(d->xiphCommentData); + + // Save the packet at the old spot + // FIXME: Use padding if size is increasing + + setPacket(d->commentPacket, v); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + // Sanity: Check if we really have an Ogg/FLAC file + +/* + ByteVector oggHeader = packet(0); + + if (oggHeader.mid(28,4) != "fLaC") { + debug("Ogg::FLAC::File::read() -- Not an Ogg/FLAC file"); + setValid(false); + return; + }*/ + + // Look for FLAC metadata, including vorbis comments + + scan(); + + if (!d->scanned) { + setValid(false); + return; + } + + + if(d->hasXiphComment) + d->comment = new Ogg::XiphComment(xiphCommentData()); + else + d->comment = new Ogg::XiphComment; + + + if(readProperties) + d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle); +} + +ByteVector Ogg::FLAC::File::streamInfoData() +{ + scan(); + return d->streamInfoData; +} + +ByteVector Ogg::FLAC::File::xiphCommentData() +{ + scan(); + return d->xiphCommentData; +} + +long Ogg::FLAC::File::streamLength() +{ + scan(); + return d->streamLength; +} + +void Ogg::FLAC::File::scan() +{ + // Scan the metadata pages + + if(d->scanned) + return; + + if(!isValid()) + return; + + int ipacket = 0; + long overhead = 0; + + ByteVector metadataHeader = packet(ipacket); + if(metadataHeader.isNull()) + return; + + ByteVector header; + + if (!metadataHeader.startsWith("fLaC")) { + // FLAC 1.1.2+ + if (metadataHeader.mid(1,4) != "FLAC") return; + + if (metadataHeader[5] != 1) return; // not version 1 + + metadataHeader = metadataHeader.mid(13); + } + else { + // FLAC 1.1.0 & 1.1.1 + metadataHeader = packet(++ipacket); + + if(metadataHeader.isNull()) + return; + + } + + header = metadataHeader.mid(0,4); + // Header format (from spec): + // <1> Last-metadata-block flag + // <7> BLOCK_TYPE + // 0 : STREAMINFO + // 1 : PADDING + // .. + // 4 : VORBIS_COMMENT + // .. + // <24> Length of metadata to follow + + char blockType = header[0] & 0x7f; + bool lastBlock = (header[0] & 0x80) != 0; + uint length = header.mid(1, 3).toUInt(); + overhead += length; + + // Sanity: First block should be the stream_info metadata + + if(blockType != 0) { + debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC stream"); + return; + } + + d->streamInfoData = metadataHeader.mid(4,length); + + // Search through the remaining metadata + + while(!lastBlock) { + metadataHeader = packet(++ipacket); + + if(metadataHeader.isNull()) + return; + + header = metadataHeader.mid(0, 4); + blockType = header[0] & 0x7f; + lastBlock = (header[0] & 0x80) != 0; + length = header.mid(1, 3).toUInt(); + overhead += length; + + if(blockType == 1) { + // debug("Ogg::FLAC::File::scan() -- Padding found"); + } + else if(blockType == 4) { + // debug("Ogg::FLAC::File::scan() -- Vorbis-comments found"); + d->xiphCommentData = metadataHeader.mid(4, length); + d->hasXiphComment = true; + d->commentPacket = ipacket; + } + else if(blockType > 5) + debug("Ogg::FLAC::File::scan() -- Unknown metadata block"); + + } + + // End of metadata, now comes the datastream + d->streamStart = overhead; + d->streamLength = File::length() - d->streamStart; + + d->scanned = true; +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.h b/Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.h new file mode 100644 index 00000000..5882a696 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/flac/oggflacfile.h @@ -0,0 +1,118 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGFLACFILE_H +#define TAGLIB_OGGFLACFILE_H + +#include "taglib_export.h" +#include "oggfile.h" +#include "xiphcomment.h" + +#include "flacproperties.h" + +namespace TagLib { + + class Tag; + + namespace Ogg { + + //! An implementation of Ogg FLAC metadata + + /*! + * This is implementation of FLAC metadata for Ogg FLAC files. For "pure" + * FLAC files look under the FLAC hiearchy. + * + * Unlike "pure" FLAC-files, Ogg FLAC only supports Xiph-comments, + * while the audio-properties are the same. + */ + namespace FLAC { + + using TagLib::FLAC::Properties; + + //! An implementation of TagLib::File with Ogg/FLAC specific methods + + /*! + * This implements and provides an interface for Ogg/FLAC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to Ogg FLAC files. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * 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(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will always be a XiphComment. + */ + virtual XiphComment *tag() const; + + /*! + * Returns the FLAC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. This will primarily save and update the XiphComment. + * Returns true if the save is successful. + */ + virtual bool save(); + + /*! + * Returns the length of the audio-stream, used by FLAC::Properties for + * calculating the bitrate. + */ + long streamLength(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + ByteVector streamInfoData(); + ByteVector xiphCommentData(); + + class FilePrivate; + FilePrivate *d; + }; + } // namespace FLAC + } // namespace Ogg +} // namespace TagLib + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/oggfile.cpp b/Plugins/PluginNowPlaying/taglib/ogg/oggfile.cpp new file mode 100644 index 00000000..f29ba14a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/oggfile.cpp @@ -0,0 +1,427 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "oggfile.h" +#include "oggpage.h" +#include "oggpageheader.h" + +using namespace TagLib; + +class Ogg::File::FilePrivate +{ +public: + FilePrivate() : + streamSerialNumber(0), + firstPageHeader(0), + lastPageHeader(0), + currentPage(0), + currentPacketPage(0) + { + pages.setAutoDelete(true); + } + + ~FilePrivate() + { + delete firstPageHeader; + delete lastPageHeader; + } + + uint streamSerialNumber; + List pages; + PageHeader *firstPageHeader; + PageHeader *lastPageHeader; + std::vector< List > packetToPageMap; + Map dirtyPackets; + List dirtyPages; + + //! The current page for the reader -- used by nextPage() + Page *currentPage; + //! The current page for the packet parser -- used by packet() + Page *currentPacketPage; + //! The packets for the currentPacketPage -- used by packet() + ByteVectorList currentPackets; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::File::~File() +{ + delete d; +} + +ByteVector Ogg::File::packet(uint i) +{ + // Check to see if we're called setPacket() for this packet since the last + // save: + + if(d->dirtyPackets.contains(i)) + return d->dirtyPackets[i]; + + // If we haven't indexed the page where the packet we're interested in starts, + // begin reading pages until we have. + + while(d->packetToPageMap.size() <= i) { + if(!nextPage()) { + debug("Ogg::File::packet() -- Could not find the requested packet."); + return ByteVector::null; + } + } + + // Start reading at the first page that contains part (or all) of this packet. + // If the last read stopped at the packet that we're interested in, don't + // reread its packet list. (This should make sequential packet reads fast.) + + uint pageIndex = d->packetToPageMap[i].front(); + if(d->currentPacketPage != d->pages[pageIndex]) { + d->currentPacketPage = d->pages[pageIndex]; + d->currentPackets = d->currentPacketPage->packets(); + } + + // If the packet is completely contained in the first page that it's in, then + // just return it now. + + if(d->currentPacketPage->containsPacket(i) & Page::CompletePacket) + return d->currentPackets[i - d->currentPacketPage->firstPacketIndex()]; + + // If the packet is *not* completely contained in the first page that it's a + // part of then that packet trails off the end of the page. Continue appending + // the pages' packet data until we hit a page that either does not end with the + // packet that we're fetching or where the last packet is complete. + + ByteVector packet = d->currentPackets.back(); + while(d->currentPacketPage->containsPacket(i) & Page::EndsWithPacket && + !d->currentPacketPage->header()->lastPacketCompleted()) + { + pageIndex++; + if(pageIndex == d->pages.size()) { + if(!nextPage()) { + debug("Ogg::File::packet() -- Could not find the requested packet."); + return ByteVector::null; + } + } + d->currentPacketPage = d->pages[pageIndex]; + d->currentPackets = d->currentPacketPage->packets(); + packet.append(d->currentPackets.front()); + } + + return packet; +} + +void Ogg::File::setPacket(uint i, const ByteVector &p) +{ + while(d->packetToPageMap.size() <= i) { + if(!nextPage()) { + debug("Ogg::File::setPacket() -- Could not set the requested packet."); + return; + } + } + + List::ConstIterator it = d->packetToPageMap[i].begin(); + for(; it != d->packetToPageMap[i].end(); ++it) + d->dirtyPages.sortedInsert(*it, true); + + d->dirtyPackets.insert(i, p); +} + +const Ogg::PageHeader *Ogg::File::firstPageHeader() +{ + if(d->firstPageHeader) + return d->firstPageHeader->isValid() ? d->firstPageHeader : 0; + + long firstPageHeaderOffset = find("OggS"); + + if(firstPageHeaderOffset < 0) + return 0; + + d->firstPageHeader = new PageHeader(this, firstPageHeaderOffset); + return d->firstPageHeader->isValid() ? d->firstPageHeader : 0; +} + +const Ogg::PageHeader *Ogg::File::lastPageHeader() +{ + if(d->lastPageHeader) + return d->lastPageHeader->isValid() ? d->lastPageHeader : 0; + + long lastPageHeaderOffset = rfind("OggS"); + + if(lastPageHeaderOffset < 0) + return 0; + + d->lastPageHeader = new PageHeader(this, lastPageHeaderOffset); + return d->lastPageHeader->isValid() ? d->lastPageHeader : 0; +} + +bool Ogg::File::save() +{ + if(readOnly()) { + debug("Ogg::File::save() - Cannot save to a read only file."); + return false; + } + + List pageGroup; + + for(List::ConstIterator it = d->dirtyPages.begin(); it != d->dirtyPages.end(); ++it) { + if(!pageGroup.isEmpty() && pageGroup.back() + 1 != *it) { + writePageGroup(pageGroup); + pageGroup.clear(); + } + else + pageGroup.append(*it); + } + writePageGroup(pageGroup); + d->dirtyPages.clear(); + d->dirtyPackets.clear(); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::File::File(FileName file) : TagLib::File(file) +{ + d = new FilePrivate; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +bool Ogg::File::nextPage() +{ + long nextPageOffset; + int currentPacket; + + if(d->pages.isEmpty()) { + currentPacket = 0; + nextPageOffset = find("OggS"); + if(nextPageOffset < 0) + return false; + } + else { + if(d->currentPage->header()->lastPageOfStream()) + return false; + + if(d->currentPage->header()->lastPacketCompleted()) + currentPacket = d->currentPage->firstPacketIndex() + d->currentPage->packetCount(); + else + currentPacket = d->currentPage->firstPacketIndex() + d->currentPage->packetCount() - 1; + + nextPageOffset = d->currentPage->fileOffset() + d->currentPage->size(); + } + + // Read the next page and add it to the page list. + + d->currentPage = new Page(this, nextPageOffset); + + if(!d->currentPage->header()->isValid()) { + delete d->currentPage; + d->currentPage = 0; + return false; + } + + d->currentPage->setFirstPacketIndex(currentPacket); + + if(d->pages.isEmpty()) + d->streamSerialNumber = d->currentPage->header()->streamSerialNumber(); + + d->pages.append(d->currentPage); + + // Loop through the packets in the page that we just read appending the + // current page number to the packet to page map for each packet. + + for(uint i = 0; i < d->currentPage->packetCount(); i++) { + uint currentPacket = d->currentPage->firstPacketIndex() + i; + if(d->packetToPageMap.size() <= currentPacket) + d->packetToPageMap.push_back(List()); + d->packetToPageMap[currentPacket].append(d->pages.size() - 1); + } + + return true; +} + +void Ogg::File::writePageGroup(const List &thePageGroup) +{ + if(thePageGroup.isEmpty()) + return; + + + // pages in the pageGroup and packets must be equivalent + // (originalSize and size of packets would not work together), + // therefore we sometimes have to add pages to the group + List pageGroup(thePageGroup); + while (!d->pages[pageGroup.back()]->header()->lastPacketCompleted()) { + if (d->currentPage->header()->pageSequenceNumber() == pageGroup.back()) { + if (nextPage() == false) { + debug("broken ogg file"); + return; + } + pageGroup.append(d->currentPage->header()->pageSequenceNumber()); + } else { + pageGroup.append(pageGroup.back() + 1); + } + } + + ByteVectorList packets; + + // If the first page of the group isn't dirty, append its partial content here. + + if(!d->dirtyPages.contains(d->pages[pageGroup.front()]->firstPacketIndex())) + packets.append(d->pages[pageGroup.front()]->packets().front()); + + int previousPacket = -1; + int originalSize = 0; + + for(List::ConstIterator it = pageGroup.begin(); it != pageGroup.end(); ++it) { + uint firstPacket = d->pages[*it]->firstPacketIndex(); + uint lastPacket = firstPacket + d->pages[*it]->packetCount() - 1; + + List::ConstIterator last = --pageGroup.end(); + + for(uint i = firstPacket; i <= lastPacket; i++) { + + if(it == last && i == lastPacket && !d->dirtyPages.contains(i)) + packets.append(d->pages[*it]->packets().back()); + else if(int(i) != previousPacket) { + previousPacket = i; + packets.append(packet(i)); + } + } + originalSize += d->pages[*it]->size(); + } + + const bool continued = d->pages[pageGroup.front()]->header()->firstPacketContinued(); + const bool completed = d->pages[pageGroup.back()]->header()->lastPacketCompleted(); + + // TODO: This pagination method isn't accurate for what's being done here. + // This should account for real possibilities like non-aligned packets and such. + + List pages = Page::paginate(packets, Page::SinglePagePerGroup, + d->streamSerialNumber, pageGroup.front(), + continued, completed); + + List renumberedPages; + + // Correct the page numbering of following pages + + if (pages.back()->header()->pageSequenceNumber() != pageGroup.back()) { + + // TODO: change the internal data structure so that we don't need to hold the + // complete file in memory (is unavoidable at the moment) + + // read the complete stream + while(!d->currentPage->header()->lastPageOfStream()) { + if(nextPage() == false) { + debug("broken ogg file"); + break; + } + } + + // create a gap for the new pages + int numberOfNewPages = pages.back()->header()->pageSequenceNumber() - pageGroup.back(); + List::Iterator pageIter = d->pages.begin(); + for(int i = 0; i < pageGroup.back(); i++) { + if(pageIter != d->pages.end()) { + ++pageIter; + } + else { + debug("Ogg::File::writePageGroup() -- Page sequence is broken in original file."); + break; + } + } + + ++pageIter; + for(; pageIter != d->pages.end(); ++pageIter) { + Ogg::Page *newPage = + (*pageIter)->getCopyWithNewPageSequenceNumber( + (*pageIter)->header()->pageSequenceNumber() + numberOfNewPages); + + ByteVector data; + data.append(newPage->render()); + insert(data, newPage->fileOffset(), data.size()); + + renumberedPages.append(newPage); + } + } + + // insert the new data + + ByteVector data; + for(List::ConstIterator it = pages.begin(); it != pages.end(); ++it) + data.append((*it)->render()); + + // The insertion algorithms could also be improve to queue and prioritize data + // on the way out. Currently it requires rewriting the file for every page + // group rather than just once; however, for tagging applications there will + // generally only be one page group, so it's not worth the time for the + // optimization at the moment. + + insert(data, d->pages[pageGroup.front()]->fileOffset(), originalSize); + + // Update the page index to include the pages we just created and to delete the + // old pages. + + // First step: Pages that contain the comment data + + for(List::ConstIterator it = pages.begin(); it != pages.end(); ++it) { + const unsigned int index = (*it)->header()->pageSequenceNumber(); + if(index < d->pages.size()) { + delete d->pages[index]; + d->pages[index] = *it; + } + else if(index == d->pages.size()) { + d->pages.append(*it); + } + else { + // oops - there's a hole in the sequence + debug("Ogg::File::writePageGroup() -- Page sequence is broken."); + } + } + + // Second step: the renumbered pages + + for(List::ConstIterator it = renumberedPages.begin(); it != renumberedPages.end(); ++it) { + const unsigned int index = (*it)->header()->pageSequenceNumber(); + if(index < d->pages.size()) { + delete d->pages[index]; + d->pages[index] = *it; + } + else if(index == d->pages.size()) { + d->pages.append(*it); + } + else { + // oops - there's a hole in the sequence + debug("Ogg::File::writePageGroup() -- Page sequence is broken."); + } + } +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/oggfile.h b/Plugins/PluginNowPlaying/taglib/ogg/oggfile.h new file mode 100644 index 00000000..da1fcb69 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/oggfile.h @@ -0,0 +1,112 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "taglib_export.h" +#include "tfile.h" +#include "tbytevectorlist.h" + +#ifndef TAGLIB_OGGFILE_H +#define TAGLIB_OGGFILE_H + +namespace TagLib { + + //! A namespace for the classes used by Ogg-based metadata files + + namespace Ogg { + + class PageHeader; + + //! An implementation of TagLib::File with some helpers for Ogg based formats + + /*! + * This is an implementation of Ogg file page and packet rendering and is of + * use to Ogg based formats. While the API is small this handles the + * non-trivial details of breaking up an Ogg stream into packets and makes + * these available (via subclassing) to the codec meta data implementations. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + virtual ~File(); + + /*! + * Returns the packet contents for the i-th packet (starting from zero) + * in the Ogg bitstream. + * + * \warning The requires reading at least the packet header for every page + * up to the requested page. + */ + ByteVector packet(uint i); + + /*! + * Sets the packet with index \a i to the value \a p. + */ + void setPacket(uint i, const ByteVector &p); + + /*! + * Returns a pointer to the PageHeader for the first page in the stream or + * null if the page could not be found. + */ + const PageHeader *firstPageHeader(); + + /*! + * Returns a pointer to the PageHeader for the last page in the stream or + * null if the page could not be found. + */ + const PageHeader *lastPageHeader(); + + virtual bool save(); + + protected: + /*! + * 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(FileName file); + + private: + File(const File &); + File &operator=(const File &); + + /*! + * Reads the next page and updates the internal "current page" pointer. + */ + bool nextPage(); + void writePageGroup(const List &group); + + class FilePrivate; + FilePrivate *d; + }; + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/oggpage.cpp b/Plugins/PluginNowPlaying/taglib/ogg/oggpage.cpp new file mode 100644 index 00000000..732f01dd --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/oggpage.cpp @@ -0,0 +1,340 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "oggpage.h" +#include "oggpageheader.h" +#include "oggfile.h" + +using namespace TagLib; + +class Ogg::Page::PagePrivate +{ +public: + PagePrivate(File *f = 0, long pageOffset = -1) : + file(f), + fileOffset(pageOffset), + packetOffset(0), + header(f, pageOffset), + firstPacketIndex(-1) + { + if(file) { + packetOffset = fileOffset + header.size(); + packetSizes = header.packetSizes(); + dataSize = header.dataSize(); + } + } + + File *file; + long fileOffset; + long packetOffset; + int dataSize; + List packetSizes; + PageHeader header; + int firstPacketIndex; + ByteVectorList packets; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::Page::Page(Ogg::File *file, long pageOffset) +{ + d = new PagePrivate(file, pageOffset); +} + +Ogg::Page::~Page() +{ + delete d; +} + +long Ogg::Page::fileOffset() const +{ + return d->fileOffset; +} + +const Ogg::PageHeader *Ogg::Page::header() const +{ + return &d->header; +} + +int Ogg::Page::firstPacketIndex() const +{ + return d->firstPacketIndex; +} + +void Ogg::Page::setFirstPacketIndex(int index) +{ + d->firstPacketIndex = index; +} + +Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const +{ + int lastPacketIndex = d->firstPacketIndex + packetCount() - 1; + if(index < d->firstPacketIndex || index > lastPacketIndex) + return DoesNotContainPacket; + + ContainsPacketFlags flags = DoesNotContainPacket; + + if(index == d->firstPacketIndex) + flags = ContainsPacketFlags(flags | BeginsWithPacket); + + if(index == lastPacketIndex) + flags = ContainsPacketFlags(flags | EndsWithPacket); + + // If there's only one page and it's complete: + + if(packetCount() == 1 && + !d->header.firstPacketContinued() && + d->header.lastPacketCompleted()) + { + flags = ContainsPacketFlags(flags | CompletePacket); + } + + // Or if there is more than one page and the page is + // (a) the first page and it's complete or + // (b) the last page and it's complete or + // (c) a page in the middle. + else if(packetCount() > 1 && + ((flags & BeginsWithPacket && !d->header.firstPacketContinued()) || + (flags & EndsWithPacket && d->header.lastPacketCompleted()) || + (!(flags & BeginsWithPacket) && !(flags & EndsWithPacket)))) + { + flags = ContainsPacketFlags(flags | CompletePacket); + } + + return flags; +} + +TagLib::uint Ogg::Page::packetCount() const +{ + return d->header.packetSizes().size(); +} + +ByteVectorList Ogg::Page::packets() const +{ + if(!d->packets.isEmpty()) + return d->packets; + + ByteVectorList l; + + if(d->file && d->header.isValid()) { + + d->file->seek(d->packetOffset); + + List packetSizes = d->header.packetSizes(); + + List::ConstIterator it = packetSizes.begin(); + for(; it != packetSizes.end(); ++it) + l.append(d->file->readBlock(*it)); + } + else + debug("Ogg::Page::packets() -- attempting to read packets from an invalid page."); + + return l; +} + +int Ogg::Page::size() const +{ + return d->header.size() + d->header.dataSize(); +} + +ByteVector Ogg::Page::render() const +{ + ByteVector data; + + data.append(d->header.render()); + + if(d->packets.isEmpty()) { + if(d->file) { + d->file->seek(d->packetOffset); + data.append(d->file->readBlock(d->dataSize)); + } + else + debug("Ogg::Page::render() -- this page is empty!"); + } + else { + ByteVectorList::ConstIterator it = d->packets.begin(); + for(; it != d->packets.end(); ++it) + data.append(*it); + } + + // Compute and set the checksum for the Ogg page. The checksum is taken over + // the entire page with the 4 bytes reserved for the checksum zeroed and then + // inserted in bytes 22-25 of the page header. + + ByteVector checksum = ByteVector::fromUInt(data.checksum(), false); + for(int i = 0; i < 4; i++) + data[i + 22] = checksum[i]; + + return data; +} + +List Ogg::Page::paginate(const ByteVectorList &packets, + PaginationStrategy strategy, + uint streamSerialNumber, + int firstPage, + bool firstPacketContinued, + bool lastPacketCompleted, + bool containsLastPacket) +{ + List l; + + int totalSize = 0; + + for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) + totalSize += (*it).size(); + + // Handle creation of multiple pages with appropriate pagination. + if(strategy == Repaginate || totalSize + packets.size() > 255 * 255) { + + // SPLITSIZE must be a multiple of 255 in order to get the lacing values right + // create pages of about 8KB each +#define SPLITSIZE (32*255) + + int pageIndex = 0; + + for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) { + bool continued = false; + + // mark very first packet? + if(firstPacketContinued && it==packets.begin()) { + continued = true; + } + + // append to buf + ByteVector packetBuf; + packetBuf.append(*it); + + while(packetBuf.size() > SPLITSIZE) { + // output a Page + ByteVector packetForOnePage; + packetForOnePage.resize(SPLITSIZE); + std::copy(packetBuf.begin(), packetBuf.begin() + SPLITSIZE, packetForOnePage.begin()); + + ByteVectorList packetList; + packetList.append(packetForOnePage); + Page *p = new Page(packetList, streamSerialNumber, firstPage+pageIndex, continued, false, false); + l.append(p); + + pageIndex++; + continued = true; + packetBuf = packetBuf.mid(SPLITSIZE); + } + + ByteVectorList::ConstIterator jt = it; + ++jt; + bool lastPacketInList = (jt == packets.end()); + + // output a page for the rest (we output one packet per page, so this one should be completed) + ByteVectorList packetList; + packetList.append(packetBuf); + + bool isVeryLastPacket = false; + if(containsLastPacket) { + // mark the very last output page as last of stream + ByteVectorList::ConstIterator jt = it; + ++jt; + if(jt == packets.end()) { + isVeryLastPacket = true; + } + } + + Page *p = new Page(packetList, streamSerialNumber, firstPage+pageIndex, continued, + lastPacketInList ? lastPacketCompleted : true, + isVeryLastPacket); + pageIndex++; + + l.append(p); + } + } + else { + Page *p = new Page(packets, streamSerialNumber, firstPage, firstPacketContinued, + lastPacketCompleted, containsLastPacket); + l.append(p); + } + + return l; +} + +Ogg::Page* Ogg::Page::getCopyWithNewPageSequenceNumber(int sequenceNumber) +{ + Page *pResultPage = NULL; + + // TODO: a copy constructor would be helpful + + if(d->file == 0) { + pResultPage = new Page( + d->packets, + d->header.streamSerialNumber(), + sequenceNumber, + d->header.firstPacketContinued(), + d->header.lastPacketCompleted(), + d->header.lastPageOfStream()); + } + else + { + pResultPage = new Page(d->file, d->fileOffset); + pResultPage->d->header.setPageSequenceNumber(sequenceNumber); + } + return pResultPage; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::Page::Page(const ByteVectorList &packets, + uint streamSerialNumber, + int pageNumber, + bool firstPacketContinued, + bool lastPacketCompleted, + bool containsLastPacket) +{ + d = new PagePrivate; + + ByteVector data; + List packetSizes; + + d->header.setFirstPageOfStream(pageNumber == 0 && !firstPacketContinued); + d->header.setLastPageOfStream(containsLastPacket); + d->header.setFirstPacketContinued(firstPacketContinued); + d->header.setLastPacketCompleted(lastPacketCompleted); + d->header.setStreamSerialNumber(streamSerialNumber); + d->header.setPageSequenceNumber(pageNumber); + + // Build a page from the list of packets. + + for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) { + packetSizes.append((*it).size()); + data.append(*it); + } + d->packets = packets; + d->header.setPacketSizes(packetSizes); +} + diff --git a/Plugins/PluginNowPlaying/taglib/ogg/oggpage.h b/Plugins/PluginNowPlaying/taglib/ogg/oggpage.h new file mode 100644 index 00000000..a8d5c1a3 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/oggpage.h @@ -0,0 +1,211 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGPAGE_H +#define TAGLIB_OGGPAGE_H + +#include "taglib_export.h" +#include "tbytevectorlist.h" + +namespace TagLib { + + namespace Ogg { + + class File; + class PageHeader; + + //! An implementation of Ogg pages + + /*! + * This is an implementation of the pages that make up an Ogg stream. + * This handles parsing pages and breaking them down into packets and handles + * the details of packets spanning multiple pages and pages that contiain + * multiple packets. + * + * In most Xiph.org formats the comments are found in the first few packets, + * this however is a reasonably complete implementation of Ogg pages that + * could potentially be useful for non-meta data purposes. + */ + + class TAGLIB_EXPORT Page + { + public: + /*! + * Read an Ogg page from the \a file at the position \a pageOffset. + */ + Page(File *file, long pageOffset); + + virtual ~Page(); + + /*! + * Returns the page's position within the file (in bytes). + */ + long fileOffset() const; + + /*! + * Returns a pointer to the header for this page. This pointer will become + * invalid when the page is deleted. + */ + const PageHeader *header() const; + + /*! + * Returns a copy of the page with \a sequenceNumber set as sequence number. + * + * \see header() + * \see PageHeader::setPageSequenceNumber() + */ + Page* getCopyWithNewPageSequenceNumber(int sequenceNumber); + + /*! + * Returns the index of the first packet wholly or partially contained in + * this page. + * + * \see setFirstPacketIndex() + */ + int firstPacketIndex() const; + + /*! + * Sets the index of the first packet in the page. + * + * \see firstPacketIndex() + */ + void setFirstPacketIndex(int index); + + /*! + * When checking to see if a page contains a given packet this set of flags + * represents the possible values for that packets status in the page. + * + * \see containsPacket() + */ + enum ContainsPacketFlags { + //! No part of the packet is contained in the page + DoesNotContainPacket = 0x0000, + //! The packet is wholly contained in the page + CompletePacket = 0x0001, + //! The page starts with the given packet + BeginsWithPacket = 0x0002, + //! The page ends with the given packet + EndsWithPacket = 0x0004 + }; + + /*! + * Checks to see if the specified \a packet is contained in the current + * page. + * + * \see ContainsPacketFlags + */ + ContainsPacketFlags containsPacket(int index) const; + + /*! + * Returns the number of packets (whole or partial) in this page. + */ + uint packetCount() const; + + /*! + * Returns a list of the packets in this page. + * + * \note Either or both the first and last packets may be only partial. + * \see PageHeader::firstPacketContinued() + */ + ByteVectorList packets() const; + + /*! + * Returns the size of the page in bytes. + */ + int size() const; + + ByteVector render() const; + + /*! + * Defines a strategy for pagination, or grouping pages into Ogg packets, + * for use with pagination methods. + * + * \note Yes, I'm aware that this is not a canonical "Strategy Pattern", + * the term was simply convenient. + */ + enum PaginationStrategy { + /*! + * Attempt to put the specified set of packets into a single Ogg packet. + * If the sum of the packet data is greater than will fit into a single + * Ogg page -- 65280 bytes -- this will fall back to repagination using + * the recommended page sizes. + */ + SinglePagePerGroup, + /*! + * Split the packet or group of packets into pages that conform to the + * sizes recommended in the Ogg standard. + */ + Repaginate + }; + + /*! + * Pack \a packets into Ogg pages using the \a strategy for pagination. + * The page number indicater inside of the rendered packets will start + * with \a firstPage and be incremented for each page rendered. + * \a containsLastPacket should be set to true if \a packets contains the + * last page in the stream and will set the appropriate flag in the last + * rendered Ogg page's header. \a streamSerialNumber should be set to + * the serial number for this stream. + * + * \note The "absolute granule position" is currently always zeroed using + * this method as this suffices for the comment headers. + * + * \warning The pages returned by this method must be deleted by the user. + * You can use List::setAutoDelete(true) to set these pages to be + * automatically deleted when this list passes out of scope. + * + * \see PaginationStrategy + * \see List::setAutoDelete() + */ + static List paginate(const ByteVectorList &packets, + PaginationStrategy strategy, + uint streamSerialNumber, + int firstPage, + bool firstPacketContinued = false, + bool lastPacketCompleted = true, + bool containsLastPacket = false); + + protected: + /*! + * Creates an Ogg packet based on the data in \a packets. The page number + * for each page will be set to \a pageNumber. + */ + Page(const ByteVectorList &packets, + uint streamSerialNumber, + int pageNumber, + bool firstPacketContinued = false, + bool lastPacketCompleted = true, + bool containsLastPacket = false); + + private: + Page(const Page &); + Page &operator=(const Page &); + + class PagePrivate; + PagePrivate *d; + }; + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.cpp b/Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.cpp new file mode 100644 index 00000000..f9608ab7 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.cpp @@ -0,0 +1,323 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include "oggpageheader.h" +#include "oggfile.h" + +using namespace TagLib; + +class Ogg::PageHeader::PageHeaderPrivate +{ +public: + PageHeaderPrivate(File *f, long pageOffset) : + file(f), + fileOffset(pageOffset), + isValid(false), + firstPacketContinued(false), + lastPacketCompleted(false), + firstPageOfStream(false), + lastPageOfStream(false), + absoluteGranularPosition(0), + streamSerialNumber(0), + pageSequenceNumber(-1), + size(0), + dataSize(0) + {} + + File *file; + long fileOffset; + bool isValid; + List packetSizes; + bool firstPacketContinued; + bool lastPacketCompleted; + bool firstPageOfStream; + bool lastPageOfStream; + long long absoluteGranularPosition; + uint streamSerialNumber; + int pageSequenceNumber; + int size; + int dataSize; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) +{ + d = new PageHeaderPrivate(file, pageOffset); + if(file && pageOffset >= 0) + read(); +} + +Ogg::PageHeader::~PageHeader() +{ + delete d; +} + +bool Ogg::PageHeader::isValid() const +{ + return d->isValid; +} + +List Ogg::PageHeader::packetSizes() const +{ + return d->packetSizes; +} + +void Ogg::PageHeader::setPacketSizes(const List &sizes) +{ + d->packetSizes = sizes; +} + +bool Ogg::PageHeader::firstPacketContinued() const +{ + return d->firstPacketContinued; +} + +void Ogg::PageHeader::setFirstPacketContinued(bool continued) +{ + d->firstPacketContinued = continued; +} + +bool Ogg::PageHeader::lastPacketCompleted() const +{ + return d->lastPacketCompleted; +} + +void Ogg::PageHeader::setLastPacketCompleted(bool completed) +{ + d->lastPacketCompleted = completed; +} + +bool Ogg::PageHeader::firstPageOfStream() const +{ + return d->firstPageOfStream; +} + +void Ogg::PageHeader::setFirstPageOfStream(bool first) +{ + d->firstPageOfStream = first; +} + +bool Ogg::PageHeader::lastPageOfStream() const +{ + return d->lastPageOfStream; +} + +void Ogg::PageHeader::setLastPageOfStream(bool last) +{ + d->lastPageOfStream = last; +} + +long long Ogg::PageHeader::absoluteGranularPosition() const +{ + return d->absoluteGranularPosition; +} + +void Ogg::PageHeader::setAbsoluteGranularPosition(long long agp) +{ + d->absoluteGranularPosition = agp; +} + +int Ogg::PageHeader::pageSequenceNumber() const +{ + return d->pageSequenceNumber; +} + +void Ogg::PageHeader::setPageSequenceNumber(int sequenceNumber) +{ + d->pageSequenceNumber = sequenceNumber; +} + +TagLib::uint Ogg::PageHeader::streamSerialNumber() const +{ + return d->streamSerialNumber; +} + +void Ogg::PageHeader::setStreamSerialNumber(uint n) +{ + d->streamSerialNumber = n; +} + +int Ogg::PageHeader::size() const +{ + return d->size; +} + +int Ogg::PageHeader::dataSize() const +{ + return d->dataSize; +} + +ByteVector Ogg::PageHeader::render() const +{ + ByteVector data; + + // capture patern + + data.append("OggS"); + + // stream structure version + + data.append(char(0)); + + // header type flag + + std::bitset<8> flags; + flags[0] = d->firstPacketContinued; + flags[1] = d->pageSequenceNumber == 0; + flags[2] = d->lastPageOfStream; + + data.append(char(flags.to_ulong())); + + // absolute granular position + + data.append(ByteVector::fromLongLong(d->absoluteGranularPosition, false)); + + // stream serial number + + data.append(ByteVector::fromUInt(d->streamSerialNumber, false)); + + // page sequence number + + data.append(ByteVector::fromUInt(d->pageSequenceNumber, false)); + + // checksum -- this is left empty and should be filled in by the Ogg::Page + // class + + data.append(ByteVector(4, 0)); + + // page segment count and page segment table + + ByteVector pageSegments = lacingValues(); + + data.append(char(uchar(pageSegments.size()))); + data.append(pageSegments); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Ogg::PageHeader::read() +{ + d->file->seek(d->fileOffset); + + // An Ogg page header is at least 27 bytes, so we'll go ahead and read that + // much and then get the rest when we're ready for it. + + ByteVector data = d->file->readBlock(27); + + // Sanity check -- make sure that we were in fact able to read as much data as + // we asked for and that the page begins with "OggS". + + if(data.size() != 27 || !data.startsWith("OggS")) { + debug("Ogg::PageHeader::read() -- error reading page header"); + return; + } + + std::bitset<8> flags(data[5]); + + d->firstPacketContinued = flags.test(0); + d->firstPageOfStream = flags.test(1); + d->lastPageOfStream = flags.test(2); + + d->absoluteGranularPosition = data.mid(6, 8).toLongLong(false); + d->streamSerialNumber = data.mid(14, 4).toUInt(false); + d->pageSequenceNumber = data.mid(18, 4).toUInt(false); + + // Byte number 27 is the number of page segments, which is the only variable + // length portion of the page header. After reading the number of page + // segments we'll then read in the corresponding data for this count. + + int pageSegmentCount = uchar(data[26]); + + ByteVector pageSegments = d->file->readBlock(pageSegmentCount); + + // Another sanity check. + + if(pageSegmentCount < 1 || int(pageSegments.size()) != pageSegmentCount) + return; + + // The base size of an Ogg page 27 bytes plus the number of lacing values. + + d->size = 27 + pageSegmentCount; + + int packetSize = 0; + + for(int i = 0; i < pageSegmentCount; i++) { + d->dataSize += uchar(pageSegments[i]); + packetSize += uchar(pageSegments[i]); + + if(uchar(pageSegments[i]) < 255) { + d->packetSizes.append(packetSize); + packetSize = 0; + } + } + + if(packetSize > 0) { + d->packetSizes.append(packetSize); + d->lastPacketCompleted = false; + } + else + d->lastPacketCompleted = true; + + d->isValid = true; +} + +ByteVector Ogg::PageHeader::lacingValues() const +{ + ByteVector data; + + List sizes = d->packetSizes; + for(List::ConstIterator it = sizes.begin(); it != sizes.end(); ++it) { + + // The size of a packet in an Ogg page is indicated by a series of "lacing + // values" where the sum of the values is the packet size in bytes. Each of + // these values is a byte. A value of less than 255 (0xff) indicates the end + // of the packet. + + div_t n = div(*it, 255); + + for(int i = 0; i < n.quot; i++) + data.append(char(uchar(255))); + + if(it != --sizes.end() || d->lastPacketCompleted) + data.append(char(uchar(n.rem))); + } + + return data; +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.h b/Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.h new file mode 100644 index 00000000..742710a4 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/oggpageheader.h @@ -0,0 +1,232 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGPAGEHEADER_H +#define TAGLIB_OGGPAGEHEADER_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace Ogg { + + class File; + + //! An implementation of the page headers associated with each Ogg::Page + + /*! + * This class implements Ogg page headers which contain the information + * about Ogg pages needed to break them into packets which can be passed on + * to the codecs. + */ + + class TAGLIB_EXPORT PageHeader + { + public: + /*! + * Reads a PageHeader from \a file starting at \a pageOffset. The defaults + * create a page with no (and as such, invalid) data that must be set + * later. + */ + PageHeader(File *file = 0, long pageOffset = -1); + + /*! + * Deletes this instance of the PageHeader. + */ + virtual ~PageHeader(); + + /*! + * Returns true if the header parsed properly and is valid. + */ + bool isValid() const; + + /*! + * Ogg pages contain a list of packets (which are used by the contained + * codecs). The sizes of these pages is encoded in the page header. This + * returns a list of the packet sizes in bytes. + * + * \see setPacketSizes() + */ + List packetSizes() const; + + /*! + * Sets the sizes of the packets in this page to \a sizes. Internally this + * updates the lacing values in the header. + * + * \see packetSizes() + */ + void setPacketSizes(const List &sizes); + + /*! + * Some packets can be continued across multiple pages. If the + * first packet in the current page is a continuation this will return + * true. If this is page starts with a new packet this will return false. + * + * \see lastPacketCompleted() + * \see setFirstPacketContinued() + */ + bool firstPacketContinued() const; + + /*! + * Sets the internal flag indicating if the first packet in this page is + * continued to \a continued. + * + * \see firstPacketContinued() + */ + void setFirstPacketContinued(bool continued); + + /*! + * Returns true if the last packet of this page is completely contained in + * this page. + * + * \see firstPacketContinued() + * \see setLastPacketCompleted() + */ + bool lastPacketCompleted() const; + + /*! + * Sets the internal flag indicating if the last packet in this page is + * complete to \a completed. + * + * \see lastPacketCompleted() + */ + void setLastPacketCompleted(bool completed); + + /*! + * This returns true if this is the first page of the Ogg (logical) stream. + * + * \see setFirstPageOfStream() + */ + bool firstPageOfStream() const; + + /*! + * Marks this page as the first page of the Ogg stream. + * + * \see firstPageOfStream() + */ + void setFirstPageOfStream(bool first); + + /*! + * This returns true if this is the last page of the Ogg (logical) stream. + * + * \see setLastPageOfStream() + */ + bool lastPageOfStream() const; + + /*! + * Marks this page as the last page of the Ogg stream. + * + * \see lastPageOfStream() + */ + void setLastPageOfStream(bool last); + + /*! + * A special value of containing the position of the packet to be + * interpreted by the codec. In the case of Vorbis this contains the PCM + * value and is used to calculate the length of the stream. + * + * \see setAbsoluteGranularPosition() + */ + long long absoluteGranularPosition() const; + + /*! + * A special value of containing the position of the packet to be + * interpreted by the codec. It is only supported here so that it may be + * coppied from one page to another. + * + * \see absoluteGranularPosition() + */ + void setAbsoluteGranularPosition(long long agp); + + /*! + * Every Ogg logical stream is given a random serial number which is common + * to every page in that logical stream. This returns the serial number of + * the stream associated with this packet. + * + * \see setStreamSerialNumber() + */ + uint streamSerialNumber() const; + + /*! + * Every Ogg logical stream is given a random serial number which is common + * to every page in that logical stream. This sets this pages serial + * number. This method should be used when adding new pages to a logical + * stream. + * + * \see streamSerialNumber() + */ + void setStreamSerialNumber(uint n); + + /*! + * Returns the index of the page within the Ogg stream. This helps make it + * possible to determine if pages have been lost. + * + * \see setPageSequenceNumber() + */ + int pageSequenceNumber() const; + + /*! + * Sets the page's position in the stream to \a sequenceNumber. + * + * \see pageSequenceNumber() + */ + void setPageSequenceNumber(int sequenceNumber); + + /*! + * Returns the complete header size. + */ + int size() const; + + /*! + * Returns the size of the data portion of the page -- i.e. the size of the + * page less the header size. + */ + int dataSize() const; + + /*! + * Render the page header to binary data. + * + * \note The checksum -- bytes 22 - 25 -- will be left empty and must be + * filled in when rendering the entire page. + */ + ByteVector render() const; + + private: + PageHeader(const PageHeader &); + PageHeader &operator=(const PageHeader &); + + void read(); + ByteVector lacingValues() const; + + class PageHeaderPrivate; + PageHeaderPrivate *d; + }; + + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.cpp b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.cpp new file mode 100644 index 00000000..604ac7c6 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include + +#include "speexfile.h" + +using namespace TagLib; +using namespace TagLib::Ogg; + +class Speex::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +Speex::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Speex::File::tag() const +{ + return d->comment; +} + +Speex::Properties *Speex::File::audioProperties() const +{ + return d->properties; +} + +bool Speex::File::save() +{ + if(!d->comment) + d->comment = new Ogg::XiphComment; + + setPacket(1, d->comment->render()); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + ByteVector speexHeaderData = packet(0); + + if(!speexHeaderData.startsWith("Speex ")) { + debug("Speex::File::read() -- invalid Speex identification header"); + return; + } + + ByteVector commentHeaderData = packet(1); + + d->comment = new Ogg::XiphComment(commentHeaderData); + + if(readProperties) + d->properties = new Properties(this, propertiesStyle); +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.h b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.h new file mode 100644 index 00000000..508b7aaa --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexfile.h @@ -0,0 +1,99 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXFILE_H +#define TAGLIB_SPEEXFILE_H + +#include "oggfile.h" +#include "xiphcomment.h" + +#include "speexproperties.h" + +namespace TagLib { + + namespace Ogg { + + //! A namespace containing classes for Speex metadata + + namespace Speex { + + //! An implementation of Ogg::File with Speex specific methods + + /*! + * This is the central class in the Ogg Speex metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Speex specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Contructs a Speex 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, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Returns the Speex::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + virtual bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.cpp b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.cpp new file mode 100644 index 00000000..980f12df --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.cpp @@ -0,0 +1,170 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include + +#include "speexproperties.h" +#include "speexfile.h" + +using namespace TagLib; +using namespace TagLib::Ogg; + +class Speex::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(File *f, ReadStyle s) : + file(f), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + speexVersion(0), + vbr(false), + mode(0) {} + + File *file; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int speexVersion; + bool vbr; + int mode; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file, style); + read(); +} + +Speex::Properties::~Properties() +{ + delete d; +} + +int Speex::Properties::length() const +{ + return d->length; +} + +int Speex::Properties::bitrate() const +{ + return int(float(d->bitrate) / float(1000) + 0.5); +} + +int Speex::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int Speex::Properties::channels() const +{ + return d->channels; +} + +int Speex::Properties::speexVersion() const +{ + return d->speexVersion; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::Properties::read() +{ + // Get the identification header from the Ogg implementation. + + ByteVector data = d->file->packet(0); + + int pos = 28; + + // speex_version_id; /**< Version for Speex (for checking compatibility) */ + d->speexVersion = data.mid(pos, 4).toUInt(false); + pos += 4; + + // header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + pos += 4; + + // rate; /**< Sampling rate used */ + d->sampleRate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + d->mode = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode_bitstream_version; /**< Version ID of the bit-stream */ + pos += 4; + + // nb_channels; /**< Number of channels encoded */ + d->channels = data.mid(pos, 4).toUInt(false); + pos += 4; + + // bitrate; /**< Bit-rate used */ + d->bitrate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // frame_size; /**< Size of frames */ + // unsigned int frameSize = data.mid(pos, 4).toUInt(false); + pos += 4; + + // vbr; /**< 1 for a VBR encoding, 0 otherwise */ + d->vbr = data.mid(pos, 4).toUInt(false) == 1; + pos += 4; + + // frames_per_packet; /**< Number of frames stored per Ogg packet */ + // unsigned int framesPerPacket = data.mid(pos, 4).toUInt(false); + + const Ogg::PageHeader *first = d->file->firstPageHeader(); + const Ogg::PageHeader *last = d->file->lastPageHeader(); + + if(first && last) { + long long start = first->absoluteGranularPosition(); + long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0 && d->sampleRate > 0) + d->length = (int) ((end - start) / (long long) d->sampleRate); + else + debug("Speex::Properties::read() -- Either the PCM values for the start or " + "end of this file was incorrect or the sample rate is zero."); + } + else + debug("Speex::Properties::read() -- Could not find valid first and last Ogg pages."); +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.h b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.h new file mode 100644 index 00000000..4720bd88 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/speex/speexproperties.h @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXPROPERTIES_H +#define TAGLIB_SPEEXPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace Ogg { + + namespace Speex { + + class File; + + //! An implementation of audio property reading for Ogg Speex + + /*! + * This reads the data from an Ogg Speex stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Speex::Properties with the data read from the + * Speex::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this Speex::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns the Speex version, currently "0" (as specified by the spec). + */ + int speexVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.cpp b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.cpp new file mode 100644 index 00000000..1098ec38 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.cpp @@ -0,0 +1,117 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include + +#include "vorbisfile.h" + +using namespace TagLib; + +class Vorbis::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +namespace TagLib { + /*! + * Vorbis headers can be found with one type ID byte and the string "vorbis" in + * an Ogg stream. 0x03 indicates the comment header. + */ + static const char vorbisCommentHeaderID[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's', 0 }; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Vorbis::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +Vorbis::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Vorbis::File::tag() const +{ + return d->comment; +} + +Vorbis::Properties *Vorbis::File::audioProperties() const +{ + return d->properties; +} + +bool Vorbis::File::save() +{ + ByteVector v(vorbisCommentHeaderID); + + if(!d->comment) + d->comment = new Ogg::XiphComment; + v.append(d->comment->render()); + + setPacket(1, v); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Vorbis::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + ByteVector commentHeaderData = packet(1); + + if(commentHeaderData.mid(0, 7) != vorbisCommentHeaderID) { + debug("Vorbis::File::read() - Could not find the Vorbis comment header."); + setValid(false); + return; + } + + d->comment = new Ogg::XiphComment(commentHeaderData.mid(7)); + + if(readProperties) + d->properties = new Properties(this, propertiesStyle); +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.h b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.h new file mode 100644 index 00000000..3e33c113 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisfile.h @@ -0,0 +1,118 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISFILE_H +#define TAGLIB_VORBISFILE_H + +#include "taglib_export.h" +#include "oggfile.h" +#include "xiphcomment.h" + +#include "vorbisproperties.h" + +namespace TagLib { + +/* + * This is just to make this appear to be in the Ogg namespace in the + * documentation. The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg + * namespace. + */ + +#ifdef DOXYGEN + namespace Ogg { +#endif + + //! A namespace containing classes for Vorbis metadata + + namespace Vorbis { + + + //! An implementation of Ogg::File with Vorbis specific methods + + /*! + * This is the central class in the Ogg Vorbis metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Vorbis specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * 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(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Returns the Vorbis::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + virtual bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + class FilePrivate; + FilePrivate *d; + }; + } + +/* + * To keep compatibility with the current version put Vorbis in the Ogg namespace + * only in the docs and provide a typedef to make it work. In the next BIC + * version this will be removed and it will only exist in the Ogg namespace. + */ + +#ifdef DOXYGEN + } +#else + namespace Ogg { namespace Vorbis { typedef TagLib::Vorbis::File File; } } +#endif + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.cpp b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.cpp new file mode 100644 index 00000000..6de6a599 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.cpp @@ -0,0 +1,183 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include + +#include "vorbisproperties.h" +#include "vorbisfile.h" + +using namespace TagLib; + +class Vorbis::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(File *f, ReadStyle s) : + file(f), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + vorbisVersion(0), + bitrateMaximum(0), + bitrateNominal(0), + bitrateMinimum(0) {} + + File *file; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int vorbisVersion; + int bitrateMaximum; + int bitrateNominal; + int bitrateMinimum; +}; + +namespace TagLib { + /*! + * Vorbis headers can be found with one type ID byte and the string "vorbis" in + * an Ogg stream. 0x01 indicates the setup header. + */ + static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', 0 }; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Vorbis::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file, style); + read(); +} + +Vorbis::Properties::~Properties() +{ + delete d; +} + +int Vorbis::Properties::length() const +{ + return d->length; +} + +int Vorbis::Properties::bitrate() const +{ + return int(float(d->bitrate) / float(1000) + 0.5); +} + +int Vorbis::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int Vorbis::Properties::channels() const +{ + return d->channels; +} + +int Vorbis::Properties::vorbisVersion() const +{ + return d->vorbisVersion; +} + +int Vorbis::Properties::bitrateMaximum() const +{ + return d->bitrateMaximum; +} + +int Vorbis::Properties::bitrateNominal() const +{ + return d->bitrateNominal; +} + +int Vorbis::Properties::bitrateMinimum() const +{ + return d->bitrateMinimum; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Vorbis::Properties::read() +{ + // Get the identification header from the Ogg implementation. + + ByteVector data = d->file->packet(0); + + int pos = 0; + + if(data.mid(pos, 7) != vorbisSetupHeaderID) { + debug("Vorbis::Properties::read() -- invalid Vorbis identification header"); + return; + } + + pos += 7; + + d->vorbisVersion = data.mid(pos, 4).toUInt(false); + pos += 4; + + d->channels = uchar(data[pos]); + pos += 1; + + d->sampleRate = data.mid(pos, 4).toUInt(false); + pos += 4; + + d->bitrateMaximum = data.mid(pos, 4).toUInt(false); + pos += 4; + + d->bitrateNominal = data.mid(pos, 4).toUInt(false); + pos += 4; + + d->bitrateMinimum = data.mid(pos, 4).toUInt(false); + + // TODO: Later this should be only the "fast" mode. + d->bitrate = d->bitrateNominal; + + // Find the length of the file. See http://wiki.xiph.org/VorbisStreamLength/ + // for my notes on the topic. + + const Ogg::PageHeader *first = d->file->firstPageHeader(); + const Ogg::PageHeader *last = d->file->lastPageHeader(); + + if(first && last) { + long long start = first->absoluteGranularPosition(); + long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0 && d->sampleRate > 0) + d->length = (end - start) / (long long) d->sampleRate; + else + debug("Vorbis::Properties::read() -- Either the PCM values for the start or " + "end of this file was incorrect or the sample rate is zero."); + } + else + debug("Vorbis::Properties::read() -- Could not find valid first and last Ogg pages."); +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.h b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.h new file mode 100644 index 00000000..de46985b --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/vorbis/vorbisproperties.h @@ -0,0 +1,125 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISPROPERTIES_H +#define TAGLIB_VORBISPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + +/* + * This is just to make this appear to be in the Ogg namespace in the + * documentation. The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg + * namespace. + */ + +#ifdef DOXYGEN + namespace Ogg { +#endif + + namespace Vorbis { + + class File; + + //! An implementation of audio property reading for Ogg Vorbis + + /*! + * This reads the data from an Ogg Vorbis stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Vorbis::Properties with the data read from the + * Vorbis::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this VorbisProperties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns the Vorbis version, currently "0" (as specified by the spec). + */ + int vorbisVersion() const; + + /*! + * Returns the maximum bitrate as read from the Vorbis identification + * header. + */ + int bitrateMaximum() const; + + /*! + * Returns the nominal bitrate as read from the Vorbis identification + * header. + */ + int bitrateNominal() const; + + /*! + * Returns the minimum bitrate as read from the Vorbis identification + * header. + */ + int bitrateMinimum() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + +/* + * To keep compatibility with the current version put Vorbis in the Ogg namespace + * only in the docs and provide a typedef to make it work. In the next BIC + * version this will be removed and it will only exist in the Ogg namespace. + */ + +#ifdef DOXYGEN + } +#else + namespace Ogg { namespace Vorbis { typedef TagLib::AudioProperties AudioProperties; } } +#endif + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.cpp b/Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.cpp new file mode 100644 index 00000000..344d9cfc --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.cpp @@ -0,0 +1,319 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include + +using namespace TagLib; + +class Ogg::XiphComment::XiphCommentPrivate +{ +public: + FieldListMap fieldListMap; + String vendorID; + String commentField; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::XiphComment::XiphComment() : TagLib::Tag() +{ + d = new XiphCommentPrivate; +} + +Ogg::XiphComment::XiphComment(const ByteVector &data) : TagLib::Tag() +{ + d = new XiphCommentPrivate; + parse(data); +} + +Ogg::XiphComment::~XiphComment() +{ + delete d; +} + +String Ogg::XiphComment::title() const +{ + if(d->fieldListMap["TITLE"].isEmpty()) + return String::null; + return d->fieldListMap["TITLE"].front(); +} + +String Ogg::XiphComment::artist() const +{ + if(d->fieldListMap["ARTIST"].isEmpty()) + return String::null; + return d->fieldListMap["ARTIST"].front(); +} + +String Ogg::XiphComment::album() const +{ + if(d->fieldListMap["ALBUM"].isEmpty()) + return String::null; + return d->fieldListMap["ALBUM"].front(); +} + +String Ogg::XiphComment::comment() const +{ + if(!d->fieldListMap["DESCRIPTION"].isEmpty()) { + d->commentField = "DESCRIPTION"; + return d->fieldListMap["DESCRIPTION"].front(); + } + + if(!d->fieldListMap["COMMENT"].isEmpty()) { + d->commentField = "COMMENT"; + return d->fieldListMap["COMMENT"].front(); + } + + return String::null; +} + +String Ogg::XiphComment::genre() const +{ + if(d->fieldListMap["GENRE"].isEmpty()) + return String::null; + return d->fieldListMap["GENRE"].front(); +} + +TagLib::uint Ogg::XiphComment::year() const +{ + if(!d->fieldListMap["DATE"].isEmpty()) + return d->fieldListMap["DATE"].front().toInt(); + if(!d->fieldListMap["YEAR"].isEmpty()) + return d->fieldListMap["YEAR"].front().toInt(); + return 0; +} + +TagLib::uint Ogg::XiphComment::track() const +{ + if(!d->fieldListMap["TRACKNUMBER"].isEmpty()) + return d->fieldListMap["TRACKNUMBER"].front().toInt(); + if(!d->fieldListMap["TRACKNUM"].isEmpty()) + return d->fieldListMap["TRACKNUM"].front().toInt(); + return 0; +} + +void Ogg::XiphComment::setTitle(const String &s) +{ + addField("TITLE", s); +} + +void Ogg::XiphComment::setArtist(const String &s) +{ + addField("ARTIST", s); +} + +void Ogg::XiphComment::setAlbum(const String &s) +{ + addField("ALBUM", s); +} + +void Ogg::XiphComment::setComment(const String &s) +{ + addField(d->commentField.isEmpty() ? "DESCRIPTION" : d->commentField, s); +} + +void Ogg::XiphComment::setGenre(const String &s) +{ + addField("GENRE", s); +} + +void Ogg::XiphComment::setYear(uint i) +{ + removeField("YEAR"); + if(i == 0) + removeField("DATE"); + else + addField("DATE", String::number(i)); +} + +void Ogg::XiphComment::setTrack(uint i) +{ + removeField("TRACKNUM"); + if(i == 0) + removeField("TRACKNUMBER"); + else + addField("TRACKNUMBER", String::number(i)); +} + +bool Ogg::XiphComment::isEmpty() const +{ + FieldListMap::ConstIterator it = d->fieldListMap.begin(); + for(; it != d->fieldListMap.end(); ++it) + if(!(*it).second.isEmpty()) + return false; + + return true; +} + +TagLib::uint Ogg::XiphComment::fieldCount() const +{ + uint count = 0; + + FieldListMap::ConstIterator it = d->fieldListMap.begin(); + for(; it != d->fieldListMap.end(); ++it) + count += (*it).second.size(); + + return count; +} + +const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const +{ + return d->fieldListMap; +} + +String Ogg::XiphComment::vendorID() const +{ + return d->vendorID; +} + +void Ogg::XiphComment::addField(const String &key, const String &value, bool replace) +{ + if(replace) + removeField(key.upper()); + + if(!key.isEmpty() && !value.isEmpty()) + d->fieldListMap[key.upper()].append(value); +} + +void Ogg::XiphComment::removeField(const String &key, const String &value) +{ + if(!value.isNull()) { + StringList::Iterator it = d->fieldListMap[key].begin(); + while(it != d->fieldListMap[key].end()) { + if(value == *it) + it = d->fieldListMap[key].erase(it); + else + it++; + } + } + else + d->fieldListMap.erase(key); +} + +bool Ogg::XiphComment::contains(const String &key) const +{ + return d->fieldListMap.contains(key) && !d->fieldListMap[key].isEmpty(); +} + +ByteVector Ogg::XiphComment::render() const +{ + return render(true); +} + +ByteVector Ogg::XiphComment::render(bool addFramingBit) const +{ + ByteVector data; + + // Add the vendor ID length and the vendor ID. It's important to use the + // length of the data(String::UTF8) rather than the length of the the string + // since this is UTF8 text and there may be more characters in the data than + // in the UTF16 string. + + ByteVector vendorData = d->vendorID.data(String::UTF8); + + data.append(ByteVector::fromUInt(vendorData.size(), false)); + data.append(vendorData); + + // Add the number of fields. + + data.append(ByteVector::fromUInt(fieldCount(), false)); + + // Iterate over the the field lists. Our iterator returns a + // std::pair where the first String is the field name and + // the StringList is the values associated with that field. + + FieldListMap::ConstIterator it = d->fieldListMap.begin(); + for(; it != d->fieldListMap.end(); ++it) { + + // And now iterate over the values of the current list. + + String fieldName = (*it).first; + StringList values = (*it).second; + + StringList::ConstIterator valuesIt = values.begin(); + for(; valuesIt != values.end(); ++valuesIt) { + ByteVector fieldData = fieldName.data(String::UTF8); + fieldData.append('='); + fieldData.append((*valuesIt).data(String::UTF8)); + + data.append(ByteVector::fromUInt(fieldData.size(), false)); + data.append(fieldData); + } + } + + // Append the "framing bit". + + if(addFramingBit) + data.append(char(1)); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void Ogg::XiphComment::parse(const ByteVector &data) +{ + // The first thing in the comment data is the vendor ID length, followed by a + // UTF8 string with the vendor ID. + + int pos = 0; + + int vendorLength = data.mid(0, 4).toUInt(false); + pos += 4; + + d->vendorID = String(data.mid(pos, vendorLength), String::UTF8); + pos += vendorLength; + + // Next the number of fields in the comment vector. + + int commentFields = data.mid(pos, 4).toUInt(false); + pos += 4; + + for(int i = 0; i < commentFields; i++) { + + // Each comment field is in the format "KEY=value" in a UTF8 string and has + // 4 bytes before the text starts that gives the length. + + int commentLength = data.mid(pos, 4).toUInt(false); + pos += 4; + + String comment = String(data.mid(pos, commentLength), String::UTF8); + pos += commentLength; + + int commentSeparatorPosition = comment.find("="); + + String key = comment.substr(0, commentSeparatorPosition); + String value = comment.substr(commentSeparatorPosition + 1); + + addField(key, value, false); + } +} diff --git a/Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.h b/Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.h new file mode 100644 index 00000000..b105dd6a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/ogg/xiphcomment.h @@ -0,0 +1,202 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISCOMMENT_H +#define TAGLIB_VORBISCOMMENT_H + +#include "tag.h" +#include "tlist.h" +#include "tmap.h" +#include "tstring.h" +#include "tstringlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace Ogg { + + /*! + * A mapping between a list of field names, or keys, and a list of values + * associated with that field. + * + * \see XiphComment::fieldListMap() + */ + typedef Map FieldListMap; + + //! Ogg Vorbis comment implementation + + /*! + * This class is an implementation of the Ogg Vorbis comment specification, + * to be found in section 5 of the Ogg Vorbis specification. Because this + * format is also used in other (currently unsupported) Xiph.org formats, it + * has been made part of a generic implementation rather than being limited + * to strictly Vorbis. + * + * Vorbis comments are a simple vector of keys and values, called fields. + * Multiple values for a given key are supported. + * + * \see fieldListMap() + */ + + class TAGLIB_EXPORT XiphComment : public TagLib::Tag + { + public: + /*! + * Constructs an empty Vorbis comment. + */ + XiphComment(); + + /*! + * Constructs a Vorbis comment from \a data. + */ + XiphComment(const ByteVector &data); + + /*! + * Destroys this instance of the XiphComment. + */ + virtual ~XiphComment(); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual uint year() const; + virtual uint track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(uint i); + virtual void setTrack(uint i); + + virtual bool isEmpty() const; + + /*! + * Returns the number of fields present in the comment. + */ + uint fieldCount() const; + + /*! + * Returns a reference to the map of field lists. Because Xiph comments + * support multiple fields with the same key, a pure Map would not work. + * As such this is a Map of string lists, keyed on the comment field name. + * + * The standard set of Xiph/Vorbis fields (which may or may not be + * contained in any specific comment) is: + * + *
    + *
  • TITLE
  • + *
  • VERSION
  • + *
  • ALBUM
  • + *
  • ARTIST
  • + *
  • PERFORMER
  • + *
  • COPYRIGHT
  • + *
  • ORGANIZATION
  • + *
  • DESCRIPTION
  • + *
  • GENRE
  • + *
  • DATE
  • + *
  • LOCATION
  • + *
  • CONTACT
  • + *
  • ISRC
  • + *
+ * + * For a more detailed description of these fields, please see the Ogg + * Vorbis specification, section 5.2.2.1. + * + * \note The Ogg Vorbis comment specification does allow these key values + * to be either upper or lower case. However, it is conventional for them + * to be upper case. As such, TagLib, when parsing a Xiph/Vorbis comment, + * converts all fields to uppercase. When you are using this data + * structure, you will need to specify the field name in upper case. + * + * \warning You should not modify this data structure directly, instead + * use addField() and removeField(). + */ + const FieldListMap &fieldListMap() const; + + /*! + * Returns the vendor ID of the Ogg Vorbis encoder. libvorbis 1.0 as the + * most common case always returns "Xiph.Org libVorbis I 20020717". + */ + String vendorID() const; + + /*! + * Add the field specified by \a key with the data \a value. If \a replace + * is true, then all of the other fields with the same key will be removed + * first. + * + * If the field value is empty, the field will be removed. + */ + void addField(const String &key, const String &value, bool replace = true); + + /*! + * Remove the field specified by \a key with the data \a value. If + * \a value is null, all of the fields with the given key will be removed. + */ + void removeField(const String &key, const String &value = String::null); + + /*! + * Returns true if the field is contained within the comment. + * + * \note This is safer than checking for membership in the FieldListMap. + */ + bool contains(const String &key) const; + + /*! + * Renders the comment to a ByteVector suitable for inserting into a file. + */ + ByteVector render() const; // BIC: remove and merge with below + + /*! + * Renders the comment to a ByteVector suitable for inserting into a file. + * + * If \a addFramingBit is true the standard Vorbis comment framing bit will + * be appended. However some formats (notably FLAC) do not work with this + * in place. + */ + ByteVector render(bool addFramingBit) const; + + protected: + /*! + * Reads the tag from the file specified in the constructor and fills the + * FieldListMap. + */ + void parse(const ByteVector &data); + + private: + XiphComment(const XiphComment &); + XiphComment &operator=(const XiphComment &); + + class XiphCommentPrivate; + XiphCommentPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.cpp b/Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.cpp new file mode 100644 index 00000000..425bfa02 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "aifffile.h" + +using namespace TagLib; + +class RIFF::AIFF::File::FilePrivate +{ +public: + FilePrivate() : + properties(0), + tag(0), + tagChunkID("ID3 ") + { + + } + + ~FilePrivate() + { + delete properties; + delete tag; + } + + Properties *properties; + ID3v2::Tag *tag; + ByteVector tagChunkID; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::AIFF::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : RIFF::File(file, BigEndian) +{ + d = new FilePrivate; + if(isOpen()) + read(readProperties, propertiesStyle); +} + +RIFF::AIFF::File::~File() +{ + delete d; +} + +ID3v2::Tag *RIFF::AIFF::File::tag() const +{ + return d->tag; +} + +RIFF::AIFF::Properties *RIFF::AIFF::File::audioProperties() const +{ + return d->properties; +} + +bool RIFF::AIFF::File::save() +{ + if(readOnly()) { + debug("RIFF::AIFF::File::save() -- File is read only."); + return false; + } + + setChunkData(d->tagChunkID, d->tag->render()); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::AIFF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + for(uint i = 0; i < chunkCount(); i++) { + if(chunkName(i) == "ID3 " || chunkName(i) == "id3 ") { + d->tagChunkID = chunkName(i); + d->tag = new ID3v2::Tag(this, chunkOffset(i)); + } + else if(chunkName(i) == "COMM" && readProperties) + d->properties = new Properties(chunkData(i), propertiesStyle); + } + + if(!d->tag) + d->tag = new ID3v2::Tag; +} diff --git a/Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.h b/Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.h new file mode 100644 index 00000000..b9b0809f --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/aiff/aifffile.h @@ -0,0 +1,102 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AIFFFILE_H +#define TAGLIB_AIFFFILE_H + +#include "rifffile.h" +#include "id3v2tag.h" +#include "aiffproperties.h" + +namespace TagLib { + + namespace RIFF { + + //! An implementation of AIFF metadata + + /*! + * This is implementation of AIFF metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ + + namespace AIFF { + + //! An implementation of TagLib::File with AIFF specific methods + + /*! + * This implements and provides an interface for AIFF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to AIFF files. + */ + + class TAGLIB_EXPORT File : public TagLib::RIFF::File + { + public: + /*! + * Contructs an AIFF 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, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. + */ + virtual ID3v2::Tag *tag() const; + + /*! + * Returns the AIFF::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.cpp b/Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.cpp new file mode 100644 index 00000000..77c3d277 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.cpp @@ -0,0 +1,153 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +// ldexp is a c99 function, which might not be defined in +// so we pull in math.h too and hope it does the right (wrong) thing +// wrt. c99 functions in C++ +#include + +#include "aiffproperties.h" + +//////////////////////////////////////////////////////////////////////////////// +// nasty 80-bit float helpers +//////////////////////////////////////////////////////////////////////////////// + +#define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0) + +static double ConvertFromIeeeExtended(unsigned char *bytes) +{ + double f; + int expon; + unsigned long hiMant, loMant; + + expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF); + + hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24) | + ((unsigned long)(bytes[3] & 0xFF) << 16) | + ((unsigned long)(bytes[4] & 0xFF) << 8) | + ((unsigned long)(bytes[5] & 0xFF)); + + loMant = ((unsigned long)(bytes[6] & 0xFF) << 24) | + ((unsigned long)(bytes[7] & 0xFF) << 16) | + ((unsigned long)(bytes[8] & 0xFF) << 8) | + ((unsigned long)(bytes[9] & 0xFF)); + + if (expon == 0 && hiMant == 0 && loMant == 0) + f = 0; + else { + if(expon == 0x7FFF) /* Infinity or NaN */ + f = HUGE_VAL; + else { + expon -= 16383; + f = ldexp(UnsignedToFloat(hiMant), expon -= 31); + f += ldexp(UnsignedToFloat(loMant), expon -= 32); + } + } + + if(bytes[0] & 0x80) + return -f; + else + return f; +} + +using namespace TagLib; + +class RIFF::AIFF::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + sampleWidth(0) + { + + } + + int length; + int bitrate; + int sampleRate; + int channels; + int sampleWidth; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::AIFF::Properties::Properties(const ByteVector &data, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate; + read(data); +} + +RIFF::AIFF::Properties::~Properties() +{ + delete d; +} + +int RIFF::AIFF::Properties::length() const +{ + return d->length; +} + +int RIFF::AIFF::Properties::bitrate() const +{ + return d->bitrate; +} + +int RIFF::AIFF::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int RIFF::AIFF::Properties::channels() const +{ + return d->channels; +} + +int RIFF::AIFF::Properties::sampleWidth() const +{ + return d->sampleWidth; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::AIFF::Properties::read(const ByteVector &data) +{ + d->channels = data.mid(0, 2).toShort(); + uint sampleFrames = data.mid(2, 4).toUInt(); + d->sampleWidth = data.mid(6, 2).toShort(); + double sampleRate = ConvertFromIeeeExtended(reinterpret_cast(data.mid(8, 10).data())); + d->sampleRate = sampleRate; + d->bitrate = (sampleRate * d->sampleWidth * d->channels) / 1000.0; + d->length = sampleFrames / d->sampleRate; +} diff --git a/Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.h b/Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.h new file mode 100644 index 00000000..4c578dc6 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/aiff/aiffproperties.h @@ -0,0 +1,82 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AIFFPROPERTIES_H +#define TAGLIB_AIFFPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace RIFF { + + namespace AIFF { + + class File; + + //! An implementation of audio property reading for AIFF + + /*! + * This reads the data from an AIFF stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of AIFF::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, ReadStyle style); + + /*! + * Destroys this AIFF::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + int sampleWidth() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(const ByteVector &data); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/riff/rifffile.cpp b/Plugins/PluginNowPlaying/taglib/riff/rifffile.cpp new file mode 100644 index 00000000..8d23bcd6 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/rifffile.cpp @@ -0,0 +1,254 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "rifffile.h" +#include + +using namespace TagLib; + +struct Chunk +{ + ByteVector name; + TagLib::uint offset; + TagLib::uint size; + char padding; +}; + +class RIFF::File::FilePrivate +{ +public: + FilePrivate() : + endianness(BigEndian), + size(0) + { + + } + Endianness endianness; + ByteVector type; + TagLib::uint size; + ByteVector format; + + std::vector chunks; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::File::~File() +{ + delete d; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::File::File(FileName file, Endianness endianness) : TagLib::File(file) +{ + d = new FilePrivate; + d->endianness = endianness; + + if(isOpen()) + read(); +} + +TagLib::uint RIFF::File::riffSize() const +{ + return d->size; +} + +TagLib::uint RIFF::File::chunkCount() const +{ + return d->chunks.size(); +} + +TagLib::uint RIFF::File::chunkDataSize(uint i) const +{ + return d->chunks[i].size; +} + +TagLib::uint RIFF::File::chunkOffset(uint i) const +{ + return d->chunks[i].offset; +} + +TagLib::uint RIFF::File::chunkPadding(uint i) const +{ + return d->chunks[i].padding; +} + +ByteVector RIFF::File::chunkName(uint i) const +{ + if(i >= chunkCount()) + return ByteVector::null; + + return d->chunks[i].name; +} + +ByteVector RIFF::File::chunkData(uint i) +{ + if(i >= chunkCount()) + return ByteVector::null; + + // Offset for the first subchunk's data + + long begin = 12 + 8; + + for(uint it = 0; it < i; it++) + begin += 8 + d->chunks[it].size + d->chunks[it].padding; + + seek(begin); + + return readBlock(d->chunks[i].size); +} + +void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data) +{ + if(d->chunks.size() == 0) { + debug("RIFF::File::setChunkData - No valid chunks found."); + return; + } + + for(uint i = 0; i < d->chunks.size(); i++) { + if(d->chunks[i].name == name) { + + // First we update the global size + + d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding); + insert(ByteVector::fromUInt(d->size, d->endianness == BigEndian), 4, 4); + + // Now update the specific chunk + + writeChunk(name, data, d->chunks[i].offset - 8, d->chunks[i].size + d->chunks[i].padding + 8); + + d->chunks[i].size = data.size(); + d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0; + + // Now update the internal offsets + + for(i++; i < d->chunks.size(); i++) + d->chunks[i].offset = d->chunks[i-1].offset + 8 + d->chunks[i-1].size + d->chunks[i-1].padding; + + return; + } + } + + // Couldn't find an existing chunk, so let's create a new one. + + uint i = d->chunks.size() - 1; + ulong offset = d->chunks[i].offset + d->chunks[i].size; + + // First we update the global size + + d->size += (offset & 1) + data.size() + 8; + insert(ByteVector::fromUInt(d->size, d->endianness == BigEndian), 4, 4); + + // Now add the chunk to the file + + writeChunk(name, data, offset, std::max(ulong(0), length() - offset), (offset & 1) ? 1 : 0); + + // And update our internal structure + + if (offset & 1) { + d->chunks[i].padding = 1; + offset++; + } + + Chunk chunk; + chunk.name = name; + chunk.size = data.size(); + chunk.offset = offset + 8; + chunk.padding = (data.size() & 0x01) ? 1 : 0; + + d->chunks.push_back(chunk); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::File::read() +{ + bool bigEndian = (d->endianness == BigEndian); + + d->type = readBlock(4); + d->size = readBlock(4).toUInt(bigEndian); + d->format = readBlock(4); + + // + 8: chunk header at least, fix for additional junk bytes + while(tell() + 8 <= length()) { + ByteVector chunkName = readBlock(4); + uint chunkSize = readBlock(4).toUInt(bigEndian); + + if(tell() + chunkSize > uint(length())) { + // something wrong + break; + } + + Chunk chunk; + chunk.name = chunkName; + chunk.size = chunkSize; + chunk.offset = tell(); + + seek(chunk.size, Current); + + // check padding + chunk.padding = 0; + long uPosNotPadded = tell(); + if((uPosNotPadded & 0x01) != 0) { + ByteVector iByte = readBlock(1); + if((iByte.size() != 1) || (iByte[0] != 0)) { + // not well formed, re-seek + seek(uPosNotPadded, Beginning); + } + else { + chunk.padding = 1; + } + } + d->chunks.push_back(chunk); + + } +} + +void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, + ulong offset, ulong replace, uint leadingPadding) +{ + ByteVector combined; + if(leadingPadding) { + combined.append(ByteVector(leadingPadding, '\x00')); + } + combined.append(name); + combined.append(ByteVector::fromUInt(data.size(), d->endianness == BigEndian)); + combined.append(data); + if((data.size() & 0x01) != 0) { + combined.append('\x00'); + } + insert(combined, offset, replace); +} diff --git a/Plugins/PluginNowPlaying/taglib/riff/rifffile.h b/Plugins/PluginNowPlaying/taglib/riff/rifffile.h new file mode 100644 index 00000000..99282564 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/rifffile.h @@ -0,0 +1,121 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RIFFFILE_H +#define TAGLIB_RIFFFILE_H + +#include "taglib_export.h" +#include "tfile.h" + +namespace TagLib { + + //! An implementation of TagLib::File with RIFF specific methods + + namespace RIFF { + + //! An RIFF file class with some useful methods specific to RIFF + + /*! + * This implements the generic TagLib::File API and additionally provides + * access to properties that are distinct to RIFF files, notably access + * to the different ID3 tags. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + protected: + + enum Endianness { BigEndian, LittleEndian }; + + File(FileName file, Endianness endianness); + + /*! + * \return The size of the main RIFF chunk. + */ + uint riffSize() const; + + /*! + * \return The number of chunks in the file. + */ + uint chunkCount() const; + + /*! + * \return The offset within the file for the selected chunk number. + */ + uint chunkOffset(uint i) const; + + /*! + * \return The size of the chunk data. + */ + uint chunkDataSize(uint i) const; + + /*! + * \return The size of the padding after the chunk (can be either 0 or 1). + */ + uint chunkPadding(uint i) const; + + /*! + * \return The name of the specified chunk, for instance, "COMM" or "ID3 " + */ + ByteVector chunkName(uint i) const; + + /*! + * Reads the chunk data from the file and returns it. + * + * \note This \e will move the read pointer for the file. + */ + ByteVector chunkData(uint i); + + /*! + * Sets the data for the chunk \a name to \a data. If a chunk with the + * given name already exists it will be overwritten, otherwise it will be + * created after the existing chunks. + * + * \warning This will update the file immediately. + */ + void setChunkData(const ByteVector &name, const ByteVector &data); + + private: + File(const File &); + File &operator=(const File &); + + void read(); + void writeChunk(const ByteVector &name, const ByteVector &data, + ulong offset, ulong replace = 0, + uint leadingPadding = 0); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.cpp b/Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.cpp new file mode 100644 index 00000000..9ec3b510 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.cpp @@ -0,0 +1,119 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "wavfile.h" + +using namespace TagLib; + +class RIFF::WAV::File::FilePrivate +{ +public: + FilePrivate() : + properties(0), + tag(0), + tagChunkID("ID3 ") + { + + } + + ~FilePrivate() + { + delete properties; + delete tag; + } + + Properties *properties; + ID3v2::Tag *tag; + ByteVector tagChunkID; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::WAV::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : RIFF::File(file, LittleEndian) +{ + d = new FilePrivate; + if(isOpen()) + read(readProperties, propertiesStyle); +} + +RIFF::WAV::File::~File() +{ + delete d; +} + +ID3v2::Tag *RIFF::WAV::File::tag() const +{ + return d->tag; +} + +RIFF::WAV::Properties *RIFF::WAV::File::audioProperties() const +{ + return d->properties; +} + +bool RIFF::WAV::File::save() +{ + if(readOnly()) { + debug("RIFF::WAV::File::save() -- File is read only."); + return false; + } + + setChunkData(d->tagChunkID, d->tag->render()); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::WAV::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + ByteVector formatData; + uint streamLength = 0; + for(uint i = 0; i < chunkCount(); i++) { + if(chunkName(i) == "ID3 " || chunkName(i) == "id3 ") { + d->tagChunkID = chunkName(i); + d->tag = new ID3v2::Tag(this, chunkOffset(i)); + } + else if(chunkName(i) == "fmt " && readProperties) + formatData = chunkData(i); + else if(chunkName(i) == "data" && readProperties) + streamLength = chunkDataSize(i); + } + + if(!formatData.isEmpty()) + d->properties = new Properties(formatData, streamLength, propertiesStyle); + + if(!d->tag) + d->tag = new ID3v2::Tag; +} diff --git a/Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.h b/Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.h new file mode 100644 index 00000000..b44668c3 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/wav/wavfile.h @@ -0,0 +1,102 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WAVFILE_H +#define TAGLIB_WAVFILE_H + +#include "rifffile.h" +#include "id3v2tag.h" +#include "wavproperties.h" + +namespace TagLib { + + namespace RIFF { + + //! An implementation of WAV metadata + + /*! + * This is implementation of WAV metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ + + namespace WAV { + + //! An implementation of TagLib::File with WAV specific methods + + /*! + * This implements and provides an interface for WAV files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WAV files. + */ + + class TAGLIB_EXPORT File : public TagLib::RIFF::File + { + public: + /*! + * Contructs an WAV 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, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. + */ + virtual ID3v2::Tag *tag() const; + + /*! + * Returns the WAV::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.cpp b/Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.cpp new file mode 100644 index 00000000..37216860 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "wavproperties.h" + +#include +#include +#include +#include + +using namespace TagLib; + +class RIFF::WAV::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(uint streamLength = 0) : + format(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + sampleWidth(0), + streamLength(streamLength) + { + + } + + short format; + int length; + int bitrate; + int sampleRate; + int channels; + int sampleWidth; + uint streamLength; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::WAV::Properties::Properties(const ByteVector &data, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(); + read(data); +} + +RIFF::WAV::Properties::Properties(const ByteVector &data, uint streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(streamLength); + read(data); +} + +RIFF::WAV::Properties::~Properties() +{ + delete d; +} + +int RIFF::WAV::Properties::length() const +{ + return d->length; +} + +int RIFF::WAV::Properties::bitrate() const +{ + return d->bitrate; +} + +int RIFF::WAV::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int RIFF::WAV::Properties::channels() const +{ + return d->channels; +} + +int RIFF::WAV::Properties::sampleWidth() const +{ + return d->sampleWidth; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::WAV::Properties::read(const ByteVector &data) +{ + d->format = data.mid(0, 2).toShort(false); + d->channels = data.mid(2, 2).toShort(false); + d->sampleRate = data.mid(4, 4).toUInt(false); + d->sampleWidth = data.mid(14, 2).toShort(false); + + uint byteRate = data.mid(8, 4).toUInt(false); + d->bitrate = byteRate * 8 / 1000; + + d->length = byteRate > 0 ? d->streamLength / byteRate : 0; +} diff --git a/Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.h b/Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.h new file mode 100644 index 00000000..bf87ffe2 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/riff/wav/wavproperties.h @@ -0,0 +1,91 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WAVPROPERTIES_H +#define TAGLIB_WAVPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + + class ByteVector; + + namespace RIFF { + + namespace WAV { + + class File; + + //! An implementation of audio property reading for WAV + + /*! + * This reads the data from an WAV stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of WAV::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, ReadStyle style); + + /*! + * Create an instance of WAV::Properties with the data read from the + * ByteVector \a data and the length calculated using \a streamLength. + */ + Properties(const ByteVector &data, uint streamLength, ReadStyle style); + + /*! + * Destroys this WAV::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + int sampleWidth() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(const ByteVector &data); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/tag.cpp b/Plugins/PluginNowPlaying/taglib/tag.cpp new file mode 100644 index 00000000..8be33c80 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/tag.cpp @@ -0,0 +1,83 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tag.h" + +using namespace TagLib; + +class Tag::TagPrivate +{ + +}; + +Tag::Tag() +{ + +} + +Tag::~Tag() +{ + +} + +bool Tag::isEmpty() const +{ + return (title().isEmpty() && + artist().isEmpty() && + album().isEmpty() && + comment().isEmpty() && + genre().isEmpty() && + year() == 0 && + track() == 0); +} + +void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static +{ + if(overwrite) { + target->setTitle(source->title()); + target->setArtist(source->artist()); + target->setAlbum(source->album()); + target->setComment(source->comment()); + target->setGenre(source->genre()); + target->setYear(source->year()); + target->setTrack(source->track()); + } + else { + if(target->title().isEmpty()) + target->setTitle(source->title()); + if(target->artist().isEmpty()) + target->setArtist(source->artist()); + if(target->album().isEmpty()) + target->setAlbum(source->album()); + if(target->comment().isEmpty()) + target->setComment(source->comment()); + if(target->genre().isEmpty()) + target->setGenre(source->genre()); + if(target->year() <= 0) + target->setYear(source->year()); + if(target->track() <= 0) + target->setTrack(source->track()); + } +} diff --git a/Plugins/PluginNowPlaying/taglib/tag.h b/Plugins/PluginNowPlaying/taglib/tag.h new file mode 100644 index 00000000..c8f12a85 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/tag.h @@ -0,0 +1,173 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAG_H +#define TAGLIB_TAG_H + +#include "taglib_export.h" +#include "tstring.h" + +namespace TagLib { + + //! A simple, generic interface to common audio meta data fields + + /*! + * This is an attempt to abstract away the difference in the meta data formats + * of various audio codecs and tagging schemes. As such it is generally a + * subset of what is available in the specific formats but should be suitable + * for most applications. This is meant to compliment the generic APIs found + * in TagLib::AudioProperties, TagLib::File and TagLib::FileRef. + */ + + class TAGLIB_EXPORT Tag + { + public: + + /*! + * Detroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Returns the track name; if no track name is present in the tag + * String::null will be returned. + */ + virtual String title() const = 0; + + /*! + * Returns the artist name; if no artist name is present in the tag + * String::null will be returned. + */ + virtual String artist() const = 0; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const = 0; + + /*! + * Returns the track comment; if no comment is present in the tag + * String::null will be returned. + */ + virtual String comment() const = 0; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const = 0; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual uint year() const = 0; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual uint track() const = 0; + + /*! + * Sets the title to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setTitle(const String &s) = 0; + + /*! + * Sets the artist to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setArtist(const String &s) = 0; + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s) = 0; + + /*! + * Sets the comment to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setComment(const String &s) = 0; + + /*! + * Sets the genre to \a s. If \a s is String::null then this value will be + * cleared. For tag formats that use a fixed set of genres, the appropriate + * value will be selected based on a string comparison. A list of available + * genres for those formats should be available in that type's + * implementation. + */ + virtual void setGenre(const String &s) = 0; + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(uint i) = 0; + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(uint i) = 0; + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Copies the generic data from one tag to another. + * + * \note This will no affect any of the lower level details of the tag. For + * instance if any of the tag type specific data (maybe a URL for a band) is + * set, this will not modify or copy that. This just copies using the API + * in this class. + * + * If \a overwrite is true then the values will be unconditionally copied. + * If false only empty values will be overwritten. + */ + static void duplicate(const Tag *source, Tag *target, bool overwrite = true); + + protected: + /*! + * Construct a Tag. This is protected since tags should only be instantiated + * through subclasses. + */ + Tag(); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/taglib_config.h b/Plugins/PluginNowPlaying/taglib/taglib_config.h new file mode 100644 index 00000000..44f47f34 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/taglib_config.h @@ -0,0 +1,2 @@ +#define TAGLIB_WITH_ASF 1 +#define TAGLIB_WITH_MP4 1 diff --git a/Plugins/PluginNowPlaying/taglib/taglib_export.h b/Plugins/PluginNowPlaying/taglib/taglib_export.h new file mode 100644 index 00000000..82122af5 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/taglib_export.h @@ -0,0 +1,46 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_EXPORT_H +#define TAGLIB_EXPORT_H + + +/* +#if (defined(_WIN32) || defined(_WIN64)) && (!defined(MAKE_TAGLIB_STATIC)) + #ifdef MAKE_TAGLIB_LIB + #define TAGLIB_EXPORT __declspec(dllexport) + #else + #define TAGLIB_EXPORT __declspec(dllimport) + #endif +#else +*/ + #define TAGLIB_EXPORT +//#endif + +#ifndef TAGLIB_NO_CONFIG +#include "taglib_config.h" +#endif + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/tagunion.cpp b/Plugins/PluginNowPlaying/taglib/tagunion.cpp new file mode 100644 index 00000000..4a9978d0 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/tagunion.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tagunion.h" + +using namespace TagLib; + +#define stringUnion(method) \ + if(tag(0) && !tag(0)->method().isEmpty()) \ + return tag(0)->method(); \ + if(tag(1) && !tag(1)->method().isEmpty()) \ + return tag(1)->method(); \ + if(tag(2) && !tag(2)->method().isEmpty()) \ + return tag(2)->method(); \ + return String::null \ + +#define numberUnion(method) \ + if(tag(0) && tag(0)->method() > 0) \ + return tag(0)->method(); \ + if(tag(1) && tag(1)->method() > 0) \ + return tag(1)->method(); \ + if(tag(2) && tag(2)->method() > 0) \ + return tag(2)->method(); \ + return 0 + +#define setUnion(method, value) \ + if(tag(0)) \ + tag(0)->set##method(value); \ + if(tag(1)) \ + tag(1)->set##method(value); \ + if(tag(2)) \ + tag(2)->set##method(value); \ + +class TagUnion::TagUnionPrivate +{ +public: + TagUnionPrivate() : tags(3, static_cast(0)) + { + + } + + ~TagUnionPrivate() + { + delete tags[0]; + delete tags[1]; + delete tags[2]; + } + + std::vector tags; +}; + +TagUnion::TagUnion(Tag *first, Tag *second, Tag *third) +{ + d = new TagUnionPrivate; + + d->tags[0] = first; + d->tags[1] = second; + d->tags[2] = third; +} + +TagUnion::~TagUnion() +{ + delete d; +} + +Tag *TagUnion::operator[](int index) const +{ + return tag(index); +} + +Tag *TagUnion::tag(int index) const +{ + return d->tags[index]; +} + +void TagUnion::set(int index, Tag *tag) +{ + delete d->tags[index]; + d->tags[index] = tag; +} + +String TagUnion::title() const +{ + stringUnion(title); +} + +String TagUnion::artist() const +{ + stringUnion(artist); +} + +String TagUnion::album() const +{ + stringUnion(album); +} + +String TagUnion::comment() const +{ + stringUnion(comment); +} + +String TagUnion::genre() const +{ + stringUnion(genre); +} + +TagLib::uint TagUnion::year() const +{ + numberUnion(year); +} + +TagLib::uint TagUnion::track() const +{ + numberUnion(track); +} + +void TagUnion::setTitle(const String &s) +{ + setUnion(Title, s); +} + +void TagUnion::setArtist(const String &s) +{ + setUnion(Artist, s); +} + +void TagUnion::setAlbum(const String &s) +{ + setUnion(Album, s); +} + +void TagUnion::setComment(const String &s) +{ + setUnion(Comment, s); +} + +void TagUnion::setGenre(const String &s) +{ + setUnion(Genre, s); +} + +void TagUnion::setYear(uint i) +{ + setUnion(Year, i); +} + +void TagUnion::setTrack(uint i) +{ + setUnion(Track, i); +} + +bool TagUnion::isEmpty() const +{ + if(d->tags[0] && !d->tags[0]->isEmpty()) + return false; + if(d->tags[1] && !d->tags[1]->isEmpty()) + return false; + if(d->tags[2] && !d->tags[2]->isEmpty()) + return false; + + return true; +} + diff --git a/Plugins/PluginNowPlaying/taglib/tagunion.h b/Plugins/PluginNowPlaying/taglib/tagunion.h new file mode 100644 index 00000000..e94d523a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/tagunion.h @@ -0,0 +1,95 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAGUNION_H +#define TAGLIB_TAGUNION_H + +#include "tag.h" + +#ifndef DO_NOT_DOCUMENT + +namespace TagLib { + + /*! + * \internal + */ + + class TagUnion : public Tag + { + public: + + enum AccessType { Read, Write }; + + /*! + * Creates a TagLib::Tag that is the union of \a first, \a second, and + * \a third. The TagUnion takes ownership of these tags and will handle + * their deletion. + */ + TagUnion(Tag *first = 0, Tag *second = 0, Tag *third = 0); + + virtual ~TagUnion(); + + Tag *operator[](int index) const; + Tag *tag(int index) const; + + void set(int index, Tag *tag); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual uint year() const; + virtual uint track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(uint i); + virtual void setTrack(uint i); + virtual bool isEmpty() const; + + template T *access(int index, bool create) + { + if(!create || tag(index)) + return static_cast(tag(index)); + + set(index, new T); + return static_cast(tag(index)); + } + + private: + TagUnion(const Tag &); + TagUnion &operator=(const Tag &); + + class TagUnionPrivate; + TagUnionPrivate *d; + }; +} + +#endif +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/taglib.h b/Plugins/PluginNowPlaying/taglib/toolkit/taglib.h new file mode 100644 index 00000000..65a0c0b2 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/taglib.h @@ -0,0 +1,186 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_H +#define TAGLIB_H + +#define TAGLIB_MAJOR_VERSION 1 +#define TAGLIB_MINOR_VERSION 7 +#define TAGLIB_PATCH_VERSION 0 + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) +#define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"") +#else +#define TAGLIB_IGNORE_MISSING_DESTRUCTOR +#endif + +#if (defined(_MSC_VER) && _MSC_VER >= 1600) +#define TAGLIB_CONSTRUCT_BITSET(x) static_cast(x) +#else +#define TAGLIB_CONSTRUCT_BITSET(x) static_cast(x) +#endif + +#include + +//! A namespace for all TagLib related classes and functions + +/*! + * This namespace contains everything in TagLib. For projects working with + * TagLib extensively it may be conveniten to add a + * \code + * using namespace TagLib; + * \endcode + */ + +namespace TagLib { + + class String; + + typedef wchar_t wchar; + typedef unsigned char uchar; + typedef unsigned int uint; + typedef unsigned long ulong; + + /*! + * Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3) + * so I'm providing something here that should be constant. + */ + typedef std::basic_string wstring; + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class. + /*! + * \internal + * This is just used as a base class for shared classes in TagLib. + * + * \warning This is not part of the TagLib public API! + */ + + class RefCounter + { + public: + RefCounter() : refCount(1) {} + void ref() { refCount++; } + bool deref() { return ! --refCount ; } + int count() { return refCount; } + private: + uint refCount; + }; + +#endif // DO_NOT_DOCUMENT + +} + +/*! + * \mainpage TagLib + * + * \section intro Introduction + * + * TagLib is a library for reading and editing audio meta data, commonly know as \e tags. + * + * Features: + * - A clean, high level, C++ API to handling audio meta data. + * - Format specific APIs for advanced API users. + * - ID3v1, ID3v2, APE, FLAC, Xiph, iTunes-style MP4 and WMA tag formats. + * - MP3, MPC, FLAC, MP4, ASF, AIFF, WAV, TrueAudio, WavPack, Ogg FLAC, Ogg Vorbis and Speex file formats. + * - Basic audio file properties such as length, sample rate, etc. + * - Long term binary and source compatibility. + * - Extensible design, notably the ability to add other formats or extend current formats as a library user. + * - Full support for unicode and internationalized tags. + * - Dual MPL and + * LGPL licenses. + * - No external toolkit dependancies. + * + * \section why Why TagLib? + * + * TagLib originally was written to provide an updated and improved ID3v2 implementation in C++ for use + * in a variety of Open Source projects. Since development began in 2002 and the 1.0 release in 2004 + * it has expanded to cover a wide variety of tag and file formats and is used in a wide variety of + * Open Source and proprietary applications. It now supports a variety of UNIXes, including Apple's OS + * X, as well as Microsoft Windows. + * + * \section commercial Usage in Commercial Applications + * + * TagLib's licenses \e do allow usage within propriety (\e closed) applications, however TagLib is \e not + * public domain. Please note the requirements of the LGPL or MPL, and adhere to at least one of them. + * In simple terms, you must at a minimum note your usage of TagLib, note the licensing terms of TagLib and + * if you make changes to TagLib publish them. Please review the licenses above before using TagLib in your + * software. Note that you may choose either the MPL or the LGPL, you do not have to fulfill the + * requirements of both. + * + * \section installing Installing TagLib + * + * Please see the TagLib website for the latest + * downloads. + * + * TagLib can be built using the CMake build system. TagLib installs a taglib-config and pkg-config file to + * make it easier to integrate into various build systems. Note that TagLib's include install directory \e must + * be included in the header include path. Simply adding will \e not work. + * + * \section start Getting Started + * + * TagLib provides both simple, abstract APIs which make it possible to ignore the differences between tagging + * formats and format specific APIs which allow programmers to work with the features of specific tagging + * schemes. There is a similar abstraction mechanism for AudioProperties. + * + * The best place to start is with the Class Hierarchy linked at the top of the page. The File and + * AudioProperties classes and their subclasses are the core of TagLib. The FileRef class is also a convenient + * way for using a value-based handle. + * + * \note When working with FileRef please consider that it has only the most basic (extension-based) file + * type resolution. Please see its documentation on how to plug in more advanced file type resolution. (Such + * resolution may be part of later TagLib releases by default.) + * + * Here's a very simple example with TagLib: + * + * \code + * + * TagLib::FileRef f("Latex Solar Beef.mp3"); + * TagLib::String artist = f.tag()->artist(); // artist == "Frank Zappa" + * + * f.tag()->setAlbum("Fillmore East"); + * f.save(); + * + * TagLib::FileRef g("Free City Rhymes.ogg"); + * TagLib::String album = g.tag()->album(); // album == "NYC Ghosts & Flowers" + * + * g.tag()->setTrack(1); + * g.save(); + * + * \endcode + * + * More examples can be found in the \e examples directory of the source distribution. + * + * \section Contact + * + * Questions about TagLib should be directed to the TagLib mailing list, not directly to the author. + * + * - TagLib Homepage + * - TagLib Mailing List (taglib-devel@kde.org) + * + * \author Scott Wheeler et al. + * + */ + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.cpp b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.cpp new file mode 100644 index 00000000..9fb77b12 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.cpp @@ -0,0 +1,698 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include + +#include + +#include "tbytevector.h" + +// This is a bit ugly to keep writing over and over again. + +// A rather obscure feature of the C++ spec that I hadn't thought of that makes +// working with C libs much more effecient. There's more here: +// +// http://www.informit.com/isapi/product_id~{9C84DAB4-FE6E-49C5-BB0A-FB50331233EA}/content/index.asp + +#define DATA(x) (&(x->data[0])) + +namespace TagLib { + static const char hexTable[17] = "0123456789abcdef"; + + static const uint crcTable[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + + /*! + * A templatized KMP find that works both with a ByteVector and a ByteVectorMirror. + */ + + template + int vectorFind(const Vector &v, const Vector &pattern, uint offset, int byteAlign) + { + if(pattern.size() > v.size() || offset > v.size() - 1) + return -1; + + // Let's go ahead and special case a pattern of size one since that's common + // and easy to make fast. + + if(pattern.size() == 1) { + char p = pattern[0]; + for(uint i = offset; i < v.size(); i++) { + if(v[i] == p && (i - offset) % byteAlign == 0) + return i; + } + return -1; + } + + uchar lastOccurrence[256]; + + for(uint i = 0; i < 256; ++i) + lastOccurrence[i] = uchar(pattern.size()); + + for(uint i = 0; i < pattern.size() - 1; ++i) + lastOccurrence[uchar(pattern[i])] = uchar(pattern.size() - i - 1); + + for(uint i = pattern.size() - 1 + offset; i < v.size(); i += lastOccurrence[uchar(v.at(i))]) { + int iBuffer = i; + int iPattern = pattern.size() - 1; + + while(iPattern >= 0 && v.at(iBuffer) == pattern[iPattern]) { + --iBuffer; + --iPattern; + } + + if(-1 == iPattern && (iBuffer + 1 - offset) % byteAlign == 0) + return iBuffer + 1; + } + + return -1; + } + + /*! + * Wraps the accessors to a ByteVector to make the search algorithm access the + * elements in reverse. + * + * \see vectorFind() + * \see ByteVector::rfind() + */ + + class ByteVectorMirror + { + public: + ByteVectorMirror(const ByteVector &source) : v(source) {} + + char operator[](int index) const + { + return v[v.size() - index - 1]; + } + + char at(int index) const + { + return v.at(v.size() - index - 1); + } + + ByteVectorMirror mid(uint index, uint length = 0xffffffff) const + { + return length == 0xffffffff ? v.mid(0, index) : v.mid(index - length, length); + } + + uint size() const + { + return v.size(); + } + + int find(const ByteVectorMirror &pattern, uint offset = 0, int byteAlign = 1) const + { + ByteVectorMirror v(*this); + + if(offset > 0) { + offset = size() - offset - pattern.size(); + if(offset >= size()) + offset = 0; + } + + const int pos = vectorFind(v, pattern, offset, byteAlign); + + // If the offset is zero then we need to adjust the location in the search + // to be appropriately reversed. If not we need to account for the fact + // that the recursive call (called from the above line) has already ajusted + // for this but that the normal templatized find above will add the offset + // to the returned value. + // + // This is a little confusing at first if you don't first stop to think + // through the logic involved in the forward search. + + if(pos == -1) + return -1; + + return size() - pos - pattern.size(); + } + + private: + const ByteVector &v; + }; + + template + T toNumber(const std::vector &data, bool mostSignificantByteFirst) + { + T sum = 0; + + if(data.size() <= 0) { + debug("ByteVectorMirror::toNumber() -- data is empty, returning 0"); + return sum; + } + + uint size = sizeof(T); + uint last = data.size() > size ? size - 1 : data.size() - 1; + + for(uint i = 0; i <= last; i++) + sum |= (T) uchar(data[i]) << ((mostSignificantByteFirst ? last - i : i) * 8); + + return sum; + } + + template + ByteVector fromNumber(T value, bool mostSignificantByteFirst) + { + int size = sizeof(T); + + ByteVector v(size, 0); + + for(int i = 0; i < size; i++) + v[i] = uchar(value >> ((mostSignificantByteFirst ? size - 1 - i : i) * 8) & 0xff); + + return v; + } +} + +using namespace TagLib; + +class ByteVector::ByteVectorPrivate : public RefCounter +{ +public: + ByteVectorPrivate() : RefCounter(), size(0) {} + ByteVectorPrivate(const std::vector &v) : RefCounter(), data(v), size(v.size()) {} + ByteVectorPrivate(TagLib::uint len, char value) : RefCounter(), data(len, value), size(len) {} + + std::vector data; + + // std::vector::size() is very slow, so we'll cache the value + + uint size; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +ByteVector ByteVector::null; + +ByteVector ByteVector::fromCString(const char *s, uint length) +{ + ByteVector v; + + if(length == 0xffffffff) + v.setData(s); + else + v.setData(s, length); + + return v; +} + +ByteVector ByteVector::fromUInt(uint value, bool mostSignificantByteFirst) +{ + return fromNumber(value, mostSignificantByteFirst); +} + +ByteVector ByteVector::fromShort(short value, bool mostSignificantByteFirst) +{ + return fromNumber(value, mostSignificantByteFirst); +} + +ByteVector ByteVector::fromLongLong(long long value, bool mostSignificantByteFirst) +{ + return fromNumber(value, mostSignificantByteFirst); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ByteVector::ByteVector() +{ + d = new ByteVectorPrivate; +} + +ByteVector::ByteVector(uint size, char value) +{ + d = new ByteVectorPrivate(size, value); +} + +ByteVector::ByteVector(const ByteVector &v) : d(v.d) +{ + d->ref(); +} + +ByteVector::ByteVector(char c) +{ + d = new ByteVectorPrivate; + d->data.push_back(c); + d->size = 1; +} + +ByteVector::ByteVector(const char *data, uint length) +{ + d = new ByteVectorPrivate; + setData(data, length); +} + +ByteVector::ByteVector(const char *data) +{ + d = new ByteVectorPrivate; + setData(data); +} + +ByteVector::~ByteVector() +{ + if(d->deref()) + delete d; +} + +ByteVector &ByteVector::setData(const char *data, uint length) +{ + detach(); + + resize(length); + + if(length > 0) + ::memcpy(DATA(d), data, length); + + return *this; +} + +ByteVector &ByteVector::setData(const char *data) +{ + return setData(data, ::strlen(data)); +} + +char *ByteVector::data() +{ + detach(); + return size() > 0 ? DATA(d) : 0; +} + +const char *ByteVector::data() const +{ + return size() > 0 ? DATA(d) : 0; +} + +ByteVector ByteVector::mid(uint index, uint length) const +{ + ByteVector v; + + if(index > size()) + return v; + + ConstIterator endIt; + + if(length < 0xffffffff && length + index < size()) + endIt = d->data.begin() + index + length; + else + endIt = d->data.end(); + + v.d->data.insert(v.d->data.begin(), ConstIterator(d->data.begin() + index), endIt); + v.d->size = v.d->data.size(); + + return v; +} + +char ByteVector::at(uint index) const +{ + return index < size() ? d->data[index] : 0; +} + +int ByteVector::find(const ByteVector &pattern, uint offset, int byteAlign) const +{ + return vectorFind(*this, pattern, offset, byteAlign); +} + +int ByteVector::rfind(const ByteVector &pattern, uint offset, int byteAlign) const +{ + // Ok, this is a little goofy, but pretty cool after it sinks in. Instead of + // reversing the find method's Boyer-Moore search algorithm I created a "mirror" + // for a ByteVector to reverse the behavior of the accessors. + + ByteVectorMirror v(*this); + ByteVectorMirror p(pattern); + + return v.find(p, offset, byteAlign); +} + +bool ByteVector::containsAt(const ByteVector &pattern, uint offset, uint patternOffset, uint patternLength) const +{ + if(pattern.size() < patternLength) + patternLength = pattern.size(); + + // do some sanity checking -- all of these things are needed for the search to be valid + + if(patternLength > size() || offset >= size() || patternOffset >= pattern.size() || patternLength == 0) + return false; + + // loop through looking for a mismatch + + for(uint i = 0; i < patternLength - patternOffset; i++) { + if(at(i + offset) != pattern[i + patternOffset]) + return false; + } + + return true; +} + +bool ByteVector::startsWith(const ByteVector &pattern) const +{ + return containsAt(pattern, 0); +} + +bool ByteVector::endsWith(const ByteVector &pattern) const +{ + return containsAt(pattern, size() - pattern.size()); +} + +ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &with) +{ + if(pattern.size() == 0 || pattern.size() > size()) + return *this; + + const int patternSize = pattern.size(); + const int withSize = with.size(); + + int offset = find(pattern); + + while(offset >= 0) { + + const int originalSize = size(); + + if(withSize > patternSize) + resize(originalSize + withSize - patternSize); + + if(patternSize != withSize) + ::memcpy(data() + offset + withSize, mid(offset + patternSize).data(), originalSize - offset - patternSize); + + if(withSize < patternSize) + resize(originalSize + withSize - patternSize); + + ::memcpy(data() + offset, with.data(), withSize); + + offset = find(pattern, offset + withSize); + } + + return *this; +} + +int ByteVector::endsWithPartialMatch(const ByteVector &pattern) const +{ + if(pattern.size() > size()) + return -1; + + const int startIndex = size() - pattern.size(); + + // try to match the last n-1 bytes from the vector (where n is the pattern + // size) -- continue trying to match n-2, n-3...1 bytes + + for(uint i = 1; i < pattern.size(); i++) { + if(containsAt(pattern, startIndex + i, 0, pattern.size() - i)) + return startIndex + i; + } + + return -1; +} + +ByteVector &ByteVector::append(const ByteVector &v) +{ + if(v.d->size == 0) + return *this; // Simply return if appending nothing. + + detach(); + + uint originalSize = d->size; + resize(d->size + v.d->size); + ::memcpy(DATA(d) + originalSize, DATA(v.d), v.size()); + + return *this; +} + +ByteVector &ByteVector::clear() +{ + detach(); + d->data.clear(); + d->size = 0; + + return *this; +} + +TagLib::uint ByteVector::size() const +{ + return d->size; +} + +ByteVector &ByteVector::resize(uint size, char padding) +{ + if(d->size < size) { + d->data.reserve(size); + d->data.insert(d->data.end(), size - d->size, padding); + } + else + d->data.erase(d->data.begin() + size, d->data.end()); + + d->size = size; + + return *this; +} + +ByteVector::Iterator ByteVector::begin() +{ + return d->data.begin(); +} + +ByteVector::ConstIterator ByteVector::begin() const +{ + return d->data.begin(); +} + +ByteVector::Iterator ByteVector::end() +{ + return d->data.end(); +} + +ByteVector::ConstIterator ByteVector::end() const +{ + return d->data.end(); +} + +bool ByteVector::isNull() const +{ + return d == null.d; +} + +bool ByteVector::isEmpty() const +{ + return d->data.size() == 0; +} + +TagLib::uint ByteVector::checksum() const +{ + uint sum = 0; + for(ByteVector::ConstIterator it = begin(); it != end(); ++it) + sum = (sum << 8) ^ crcTable[((sum >> 24) & 0xff) ^ uchar(*it)]; + return sum; +} + +TagLib::uint ByteVector::toUInt(bool mostSignificantByteFirst) const +{ + return toNumber(d->data, mostSignificantByteFirst); +} + +short ByteVector::toShort(bool mostSignificantByteFirst) const +{ + return toNumber(d->data, mostSignificantByteFirst); +} + +unsigned short ByteVector::toUShort(bool mostSignificantByteFirst) const +{ + return toNumber(d->data, mostSignificantByteFirst); +} + +long long ByteVector::toLongLong(bool mostSignificantByteFirst) const +{ + return toNumber(d->data, mostSignificantByteFirst); +} + +const char &ByteVector::operator[](int index) const +{ + return d->data[index]; +} + +char &ByteVector::operator[](int index) +{ + detach(); + + return d->data[index]; +} + +bool ByteVector::operator==(const ByteVector &v) const +{ + if(d->size != v.d->size) + return false; + + return ::memcmp(data(), v.data(), size()) == 0; +} + +bool ByteVector::operator!=(const ByteVector &v) const +{ + return !operator==(v); +} + +bool ByteVector::operator==(const char *s) const +{ + if(d->size != ::strlen(s)) + return false; + + return ::memcmp(data(), s, d->size) == 0; +} + +bool ByteVector::operator!=(const char *s) const +{ + return !operator==(s); +} + +bool ByteVector::operator<(const ByteVector &v) const +{ + int result = ::memcmp(data(), v.data(), d->size < v.d->size ? d->size : v.d->size); + + if(result != 0) + return result < 0; + else + return size() < v.size(); +} + +bool ByteVector::operator>(const ByteVector &v) const +{ + return v < *this; +} + +ByteVector ByteVector::operator+(const ByteVector &v) const +{ + ByteVector sum(*this); + sum.append(v); + return sum; +} + +ByteVector &ByteVector::operator=(const ByteVector &v) +{ + if(&v == this) + return *this; + + if(d->deref()) + delete d; + + d = v.d; + d->ref(); + return *this; +} + +ByteVector &ByteVector::operator=(char c) +{ + *this = ByteVector(c); + return *this; +} + +ByteVector &ByteVector::operator=(const char *data) +{ + *this = ByteVector(data); + return *this; +} + +ByteVector ByteVector::toHex() const +{ + ByteVector encoded(size() * 2); + + uint j = 0; + for(uint i = 0; i < size(); i++) { + unsigned char c = d->data[i]; + encoded[j++] = hexTable[(c >> 4) & 0x0F]; + encoded[j++] = hexTable[(c ) & 0x0F]; + } + + return encoded; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void ByteVector::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new ByteVectorPrivate(d->data); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// related functions +//////////////////////////////////////////////////////////////////////////////// + +std::ostream &operator<<(std::ostream &s, const ByteVector &v) +{ + for(TagLib::uint i = 0; i < v.size(); i++) + s << v[i]; + return s; +} diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.h b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.h new file mode 100644 index 00000000..b7fffdde --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevector.h @@ -0,0 +1,425 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTOR_H +#define TAGLIB_BYTEVECTOR_H + +#include "taglib.h" +#include "taglib_export.h" + +#include +#include + +namespace TagLib { + + //! A byte vector + + /*! + * This class provides a byte vector with some methods that are useful for + * tagging purposes. Many of the search functions are tailored to what is + * useful for finding tag related paterns in a data array. + */ + + class TAGLIB_EXPORT ByteVector + { + public: +#ifndef DO_NOT_DOCUMENT + typedef std::vector::iterator Iterator; + typedef std::vector::const_iterator ConstIterator; +#endif + + /*! + * Constructs an empty byte vector. + */ + ByteVector(); + + /*! + * Construct a vector of size \a size with all values set to \a value by + * default. + */ + ByteVector(uint size, char value = 0); + + /*! + * Contructs a byte vector that is a copy of \a v. + */ + ByteVector(const ByteVector &v); + + /*! + * Contructs a byte vector that contains \a c. + */ + ByteVector(char c); + + /*! + * Constructs a byte vector that copies \a data for up to \a length bytes. + */ + ByteVector(const char *data, uint length); + + /*! + * Constructs a byte vector that copies \a data up to the first null + * byte. The behavior is undefined if \a data is not null terminated. + * This is particularly useful for constructing byte arrays from string + * constants. + */ + ByteVector(const char *data); + + /*! + * Destroys this ByteVector instance. + */ + virtual ~ByteVector(); + + /*! + * Sets the data for the byte array using the first \a length bytes of \a data + */ + ByteVector &setData(const char *data, uint length); + + /*! + * Sets the data for the byte array copies \a data up to the first null + * byte. The behavior is undefined if \a data is not null terminated. + */ + ByteVector &setData(const char *data); + + /*! + * Returns a pointer to the internal data structure. + * + * \warning Care should be taken when modifying this data structure as it is + * easy to corrupt the ByteVector when doing so. Specifically, while the + * data may be changed, its length may not be. + */ + char *data(); + + /*! + * Returns a pointer to the internal data structure which may not be modified. + */ + const char *data() const; + + /*! + * Returns a byte vector made up of the bytes starting at \a index and + * for \a length bytes. If \a length is not specified it will return the bytes + * from \a index to the end of the vector. + */ + ByteVector mid(uint index, uint length = 0xffffffff) const; + + /*! + * This essentially performs the same as operator[](), but instead of causing + * a runtime error if the index is out of bounds, it will return a null byte. + */ + char at(uint index) const; + + /*! + * Searches the ByteVector for \a pattern starting at \a offset and returns + * the offset. Returns -1 if the pattern was not found. If \a byteAlign is + * specified the pattern will only be matched if it starts on a byte divisible + * by \a byteAlign (starting from \a offset). + */ + int find(const ByteVector &pattern, uint offset = 0, int byteAlign = 1) const; + + /*! + * Searches the ByteVector for \a pattern starting from either the end of the + * vector or \a offset and returns the offset. Returns -1 if the pattern was + * not found. If \a byteAlign is specified the pattern will only be matched + * if it starts on a byte divisible by \a byteAlign (starting from \a offset). + */ + int rfind(const ByteVector &pattern, uint offset = 0, int byteAlign = 1) const; + + /*! + * Checks to see if the vector contains the \a pattern starting at position + * \a offset. Optionally, if you only want to search for part of the pattern + * you can specify an offset within the pattern to start from. Also, you can + * specify to only check for the first \a patternLength bytes of \a pattern with + * the \a patternLength argument. + */ + bool containsAt(const ByteVector &pattern, uint offset, uint patternOffset = 0, uint patternLength = 0xffffffff) const; + + /*! + * Returns true if the vector starts with \a pattern. + */ + bool startsWith(const ByteVector &pattern) const; + + /*! + * Returns true if the vector ends with \a pattern. + */ + bool endsWith(const ByteVector &pattern) const; + + /*! + * Replaces \a pattern with \a with and returns a reference to the ByteVector + * after the operation. This \e does modify the vector. + */ + ByteVector &replace(const ByteVector &pattern, const ByteVector &with); + + /*! + * Checks for a partial match of \a pattern at the end of the vector. It + * returns the offset of the partial match within the vector, or -1 if the + * pattern is not found. This method is particularly useful when searching for + * patterns that start in one vector and end in another. When combined with + * startsWith() it can be used to find a pattern that overlaps two buffers. + * + * \note This will not match the complete pattern at the end of the string; use + * endsWith() for that. + */ + int endsWithPartialMatch(const ByteVector &pattern) const; + + /*! + * Appends \a v to the end of the ByteVector. + */ + ByteVector &append(const ByteVector &v); + + /*! + * Clears the data. + */ + ByteVector &clear(); + + /*! + * Returns the size of the array. + */ + uint size() const; + + /*! + * Resize the vector to \a size. If the vector is currently less than + * \a size, pad the remaining spaces with \a padding. Returns a reference + * to the resized vector. + */ + ByteVector &resize(uint size, char padding = 0); + + /*! + * Returns an Iterator that points to the front of the vector. + */ + Iterator begin(); + + /*! + * Returns a ConstIterator that points to the front of the vector. + */ + ConstIterator begin() const; + + /*! + * Returns an Iterator that points to the back of the vector. + */ + Iterator end(); + + /*! + * Returns a ConstIterator that points to the back of the vector. + */ + ConstIterator end() const; + + /*! + * Returns true if the vector is null. + * + * \note A vector may be empty without being null. + * \see isEmpty() + */ + bool isNull() const; + + /*! + * Returns true if the ByteVector is empty. + * + * \see size() + * \see isNull() + */ + bool isEmpty() const; + + /*! + * Returns a CRC checksum of the byte vector's data. + */ + uint checksum() const; + + /*! + * Converts the first 4 bytes of the vector to an unsigned integer. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see fromUInt() + */ + uint toUInt(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 2 bytes of the vector to a short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + short toShort(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 2 bytes of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + unsigned short toUShort(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 8 bytes of the vector to a (signed) long long. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see fromUInt() + */ + long long toLongLong(bool mostSignificantByteFirst = true) const; + + /*! + * Creates a 4 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 00 00 01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see toUInt() + */ + static ByteVector fromUInt(uint value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 2 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 01 == 0x0001 == 1, if false, $01 00 == 0x0100 == 1. + * + * \see toShort() + */ + static ByteVector fromShort(short value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 8 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 00 00 01 == 0x0000000000000001 == 1, if false, + * $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see toLongLong() + */ + static ByteVector fromLongLong(long long value, bool mostSignificantByteFirst = true); + + /*! + * Returns a ByteVector based on the CString \a s. + */ + static ByteVector fromCString(const char *s, uint length = 0xffffffff); + + /*! + * Returns a const refernence to the byte at \a index. + */ + const char &operator[](int index) const; + + /*! + * Returns a reference to the byte at \a index. + */ + char &operator[](int index); + + /*! + * Returns true if this ByteVector and \a v are equal. + */ + bool operator==(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector and \a v are not equal. + */ + bool operator!=(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector and the null terminated C string \a s + * contain the same data. + */ + bool operator==(const char *s) const; + + /*! + * Returns true if this ByteVector and the null terminated C string \a s + * do not contain the same data. + */ + bool operator!=(const char *s) const; + + /*! + * Returns true if this ByteVector is less than \a v. The value of the + * vectors is determined by evaluating the character from left to right, and + * in the event one vector is a superset of the other, the size is used. + */ + bool operator<(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector is greater than \a v. + */ + bool operator>(const ByteVector &v) const; + + /*! + * Returns a vector that is \a v appended to this vector. + */ + ByteVector operator+(const ByteVector &v) const; + + /*! + * Copies ByteVector \a v. + */ + ByteVector &operator=(const ByteVector &v); + + /*! + * Copies ByteVector \a v. + */ + ByteVector &operator=(char c); + + /*! + * Copies ByteVector \a v. + */ + ByteVector &operator=(const char *data); + + /*! + * A static, empty ByteVector which is convenient and fast (since returning + * an empty or "null" value does not require instantiating a new ByteVector). + */ + static ByteVector null; + + /*! + * Returns a hex-encoded copy of the byte vector. + */ + ByteVector toHex() const; + + protected: + /* + * If this ByteVector is being shared via implicit sharing, do a deep copy + * of the data and separate from the shared members. This should be called + * by all non-const subclass members. + */ + void detach(); + + private: + class ByteVectorPrivate; + ByteVectorPrivate *d; + }; + +} + +/*! + * \relates TagLib::ByteVector + * Streams the ByteVector \a v to the output stream \a s. + */ +TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const TagLib::ByteVector &v); + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.cpp b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.cpp new file mode 100644 index 00000000..7ea893f1 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tbytevectorlist.h" + +using namespace TagLib; + +class ByteVectorListPrivate +{ + +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, + int byteAlign) +{ + return split(v, pattern, byteAlign, 0); +} + +ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, + int byteAlign, int max) +{ + ByteVectorList l; + + uint previousOffset = 0; + for(int offset = v.find(pattern, 0, byteAlign); + offset != -1 && (max == 0 || max > int(l.size()) + 1); + offset = v.find(pattern, offset + pattern.size(), byteAlign)) + { + if(offset - previousOffset >= 1) + l.append(v.mid(previousOffset, offset - previousOffset)); + else + l.append(ByteVector::null); + + previousOffset = offset + pattern.size(); + } + + if(previousOffset < v.size()) + l.append(v.mid(previousOffset, v.size() - previousOffset)); + + return l; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ByteVectorList::ByteVectorList() : List() +{ + +} + +ByteVectorList::ByteVectorList(const ByteVectorList &l) : List(l) +{ + +} + +ByteVectorList::~ByteVectorList() +{ + +} + +ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const +{ + ByteVector v; + + ConstIterator it = begin(); + + while(it != end()) { + v.append(*it); + it++; + if(it != end()) + v.append(separator); + } + + return v; +} diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.h b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.h new file mode 100644 index 00000000..5852583a --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tbytevectorlist.h @@ -0,0 +1,91 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTORLIST_H +#define TAGLIB_BYTEVECTORLIST_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "tlist.h" + +namespace TagLib { + + //! A list of ByteVectors + + /*! + * A List specialization with some handy features useful for ByteVectors. + */ + + class TAGLIB_EXPORT ByteVectorList : public List + { + public: + + /*! + * Construct an empty ByteVectorList. + */ + ByteVectorList(); + + /*! + * Destroys this ByteVectorList instance. + */ + virtual ~ByteVectorList(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + ByteVectorList(const ByteVectorList &l); + + /*! + * Convert the ByteVectorList to a ByteVector separated by \a separator. By + * default a space is used. + */ + ByteVector toByteVector(const ByteVector &separator = " ") const; + + /*! + * Splits the ByteVector \a v into several strings at \a pattern. This will + * not include the pattern in the returned ByteVectors. + */ + static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, + int byteAlign = 1); + /*! + * Splits the ByteVector \a v into several strings at \a pattern. This will + * not include the pattern in the returned ByteVectors. \a max is the + * maximum number of entries that will be separated. If \a max for instance + * is 2 then a maximum of 1 match will be found and the vector will be split + * on that match. + */ + // BIC: merge with the function above + static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, + int byteAlign, int max); + private: + class ByteVectorListPrivate; + ByteVectorListPrivate *d; + }; + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tdebug.cpp b/Plugins/PluginNowPlaying/taglib/toolkit/tdebug.cpp new file mode 100644 index 00000000..522b68c9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tdebug.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef NDEBUG +#include +#include + +#include "tdebug.h" +#include "tstring.h" + +using namespace TagLib; + +void TagLib::debug(const String &s) +{ + std::cerr << "TagLib: " << s << std::endl; +} + +void TagLib::debugData(const ByteVector &v) +{ + for(uint i = 0; i < v.size(); i++) { + + std::cout << "*** [" << i << "] - '" << char(v[i]) << "' - int " << int(v[i]) + << std::endl; + + std::bitset<8> b(v[i]); + + for(int j = 0; j < 8; j++) + std::cout << i << ":" << j << " " << b.test(j) << std::endl; + + std::cout << std::endl; + } +} +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tdebug.h b/Plugins/PluginNowPlaying/taglib/toolkit/tdebug.h new file mode 100644 index 00000000..5204fe70 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tdebug.h @@ -0,0 +1,71 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_DEBUG_H +#define TAGLIB_DEBUG_H + +namespace TagLib { + + class String; + class ByteVector; + +#ifndef DO_NOT_DOCUMENT +#ifndef NDEBUG + + /*! + * A simple function that prints debugging output to cerr if debugging is + * not disabled. + * + * \warning Do not use this outside of TagLib, it could lead to undefined + * symbols in your build if TagLib is built with NDEBUG defined and your + * application is not. + * + * \internal + */ + void debug(const String &s); + + /*! + * For debugging binary data. + * + * \warning Do not use this outside of TagLib, it could lead to undefined + * symbols in your build if TagLib is built with NDEBUG defined and your + * application is not. + * + * \internal + */ + void debugData(const ByteVector &v); + +#else + + // Define these to an empty statement if debugging is disabled. + +#define debug(x) +#define debugData(x) + +#endif +#endif +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tfile.cpp b/Plugins/PluginNowPlaying/taglib/toolkit/tfile.cpp new file mode 100644 index 00000000..f0b3c80d --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tfile.cpp @@ -0,0 +1,564 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tfile.h" +#include "tstring.h" +#include "tdebug.h" + +#include +#include +#include + +#ifdef _WIN32 +# include +# include +# include +# define ftruncate _chsize +#else +# include +#endif + +#include + +#ifndef R_OK +# define R_OK 4 +#endif +#ifndef W_OK +# define W_OK 2 +#endif + +using namespace TagLib; + +#ifdef _WIN32 + +typedef FileName FileNameHandle; + +#else + +struct FileNameHandle : public std::string +{ + FileNameHandle(FileName name) : std::string(name) {} + operator FileName () const { return c_str(); } +}; + +#endif + +class File::FilePrivate +{ +public: + FilePrivate(FileName fileName); + + FILE *file; + + FileNameHandle name; + + bool readOnly; + bool valid; + ulong size; + static const uint bufferSize = 1024; +}; + +File::FilePrivate::FilePrivate(FileName fileName) : + file(0), + name(fileName), + readOnly(true), + valid(true), + size(0) +{ + // First try with read / write mode, if that fails, fall back to read only. + +#ifdef _WIN32 + + if(wcslen((const wchar_t *) fileName) > 0) { + + file = _wfopen(name, L"rb+"); + + if(file) + readOnly = false; + else + file = _wfopen(name, L"rb"); + + if(file) + return; + + } + +#endif + + file = fopen(name, "rb+"); + + if(file) + readOnly = false; + else + file = fopen(name, "rb"); + + if(!file) + debug("Could not open file " + String((const char *) name)); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +File::File(FileName file) +{ + d = new FilePrivate(file); +} + +File::~File() +{ + if(d->file) + fclose(d->file); + delete d; +} + +FileName File::name() const +{ + return d->name; +} + +ByteVector File::readBlock(ulong length) +{ + if(!d->file) { + debug("File::readBlock() -- Invalid File"); + return ByteVector::null; + } + + if(length == 0) + return ByteVector::null; + + if(length > FilePrivate::bufferSize && + length > ulong(File::length())) + { + length = File::length(); + } + + ByteVector v(static_cast(length)); + const int count = fread(v.data(), sizeof(char), length, d->file); + v.resize(count); + return v; +} + +void File::writeBlock(const ByteVector &data) +{ + if(!d->file) + return; + + if(d->readOnly) { + debug("File::writeBlock() -- attempted to write to a file that is not writable"); + return; + } + + fwrite(data.data(), sizeof(char), data.size(), d->file); +} + +long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &before) +{ + if(!d->file || pattern.size() > d->bufferSize) + return -1; + + // The position in the file that the current buffer starts at. + + long bufferOffset = fromOffset; + ByteVector buffer; + + // These variables are used to keep track of a partial match that happens at + // the end of a buffer. + + int previousPartialMatch = -1; + int beforePreviousPartialMatch = -1; + + // Save the location of the current read pointer. We will restore the + // position using seek() before all returns. + + long originalPosition = tell(); + + // Start the search at the offset. + + seek(fromOffset); + + // This loop is the crux of the find method. There are three cases that we + // want to account for: + // + // (1) The previously searched buffer contained a partial match of the search + // pattern and we want to see if the next one starts with the remainder of + // that pattern. + // + // (2) The search pattern is wholly contained within the current buffer. + // + // (3) The current buffer ends with a partial match of the pattern. We will + // note this for use in the next itteration, where we will check for the rest + // of the pattern. + // + // All three of these are done in two steps. First we check for the pattern + // and do things appropriately if a match (or partial match) is found. We + // then check for "before". The order is important because it gives priority + // to "real" matches. + + for(buffer = readBlock(d->bufferSize); buffer.size() > 0; buffer = readBlock(d->bufferSize)) { + + // (1) previous partial match + + if(previousPartialMatch >= 0 && int(d->bufferSize) > previousPartialMatch) { + const int patternOffset = (d->bufferSize - previousPartialMatch); + if(buffer.containsAt(pattern, 0, patternOffset)) { + seek(originalPosition); + return bufferOffset - d->bufferSize + previousPartialMatch; + } + } + + if(!before.isNull() && beforePreviousPartialMatch >= 0 && int(d->bufferSize) > beforePreviousPartialMatch) { + const int beforeOffset = (d->bufferSize - beforePreviousPartialMatch); + if(buffer.containsAt(before, 0, beforeOffset)) { + seek(originalPosition); + return -1; + } + } + + // (2) pattern contained in current buffer + + long location = buffer.find(pattern); + if(location >= 0) { + seek(originalPosition); + return bufferOffset + location; + } + + if(!before.isNull() && buffer.find(before) >= 0) { + seek(originalPosition); + return -1; + } + + // (3) partial match + + previousPartialMatch = buffer.endsWithPartialMatch(pattern); + + if(!before.isNull()) + beforePreviousPartialMatch = buffer.endsWithPartialMatch(before); + + bufferOffset += d->bufferSize; + } + + // Since we hit the end of the file, reset the status before continuing. + + clear(); + + seek(originalPosition); + + return -1; +} + + +long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &before) +{ + if(!d->file || pattern.size() > d->bufferSize) + return -1; + + // The position in the file that the current buffer starts at. + + ByteVector buffer; + + // These variables are used to keep track of a partial match that happens at + // the end of a buffer. + + /* + int previousPartialMatch = -1; + int beforePreviousPartialMatch = -1; + */ + + // Save the location of the current read pointer. We will restore the + // position using seek() before all returns. + + long originalPosition = tell(); + + // Start the search at the offset. + + long bufferOffset; + if(fromOffset == 0) { + seek(-1 * int(d->bufferSize), End); + bufferOffset = tell(); + } + else { + seek(fromOffset + -1 * int(d->bufferSize), Beginning); + bufferOffset = tell(); + } + + // See the notes in find() for an explanation of this algorithm. + + for(buffer = readBlock(d->bufferSize); buffer.size() > 0; buffer = readBlock(d->bufferSize)) { + + // TODO: (1) previous partial match + + // (2) pattern contained in current buffer + + long location = buffer.rfind(pattern); + if(location >= 0) { + seek(originalPosition); + return bufferOffset + location; + } + + if(!before.isNull() && buffer.find(before) >= 0) { + seek(originalPosition); + return -1; + } + + // TODO: (3) partial match + + bufferOffset -= d->bufferSize; + seek(bufferOffset); + } + + // Since we hit the end of the file, reset the status before continuing. + + clear(); + + seek(originalPosition); + + return -1; +} + +void File::insert(const ByteVector &data, ulong start, ulong replace) +{ + if(!d->file) + return; + + if(data.size() == replace) { + seek(start); + writeBlock(data); + return; + } + else if(data.size() < replace) { + seek(start); + writeBlock(data); + removeBlock(start + data.size(), replace - data.size()); + return; + } + + // Woohoo! Faster (about 20%) than id3lib at last. I had to get hardcore + // and avoid TagLib's high level API for rendering just copying parts of + // the file that don't contain tag data. + // + // Now I'll explain the steps in this ugliness: + + // First, make sure that we're working with a buffer that is longer than + // the *differnce* in the tag sizes. We want to avoid overwriting parts + // that aren't yet in memory, so this is necessary. + + ulong bufferLength = bufferSize(); + + while(data.size() - replace > bufferLength) + bufferLength += bufferSize(); + + // Set where to start the reading and writing. + + long readPosition = start + replace; + long writePosition = start; + + ByteVector buffer; + ByteVector aboutToOverwrite(static_cast(bufferLength)); + + // This is basically a special case of the loop below. Here we're just + // doing the same steps as below, but since we aren't using the same buffer + // size -- instead we're using the tag size -- this has to be handled as a + // special case. We're also using File::writeBlock() just for the tag. + // That's a bit slower than using char *'s so, we're only doing it here. + + seek(readPosition); + int bytesRead = fread(aboutToOverwrite.data(), sizeof(char), bufferLength, d->file); + readPosition += bufferLength; + + seek(writePosition); + writeBlock(data); + writePosition += data.size(); + + buffer = aboutToOverwrite; + + // In case we've already reached the end of file... + + buffer.resize(bytesRead); + + // Ok, here's the main loop. We want to loop until the read fails, which + // means that we hit the end of the file. + + while(!buffer.isEmpty()) { + + // Seek to the current read position and read the data that we're about + // to overwrite. Appropriately increment the readPosition. + + seek(readPosition); + bytesRead = fread(aboutToOverwrite.data(), sizeof(char), bufferLength, d->file); + aboutToOverwrite.resize(bytesRead); + readPosition += bufferLength; + + // Check to see if we just read the last block. We need to call clear() + // if we did so that the last write succeeds. + + if(ulong(bytesRead) < bufferLength) + clear(); + + // Seek to the write position and write our buffer. Increment the + // writePosition. + + seek(writePosition); + fwrite(buffer.data(), sizeof(char), buffer.size(), d->file); + writePosition += buffer.size(); + + // Make the current buffer the data that we read in the beginning. + + buffer = aboutToOverwrite; + + // Again, we need this for the last write. We don't want to write garbage + // at the end of our file, so we need to set the buffer size to the amount + // that we actually read. + + bufferLength = bytesRead; + } +} + +void File::removeBlock(ulong start, ulong length) +{ + if(!d->file) + return; + + ulong bufferLength = bufferSize(); + + long readPosition = start + length; + long writePosition = start; + + ByteVector buffer(static_cast(bufferLength)); + + ulong bytesRead = 1; + + while(bytesRead != 0) { + seek(readPosition); + bytesRead = fread(buffer.data(), sizeof(char), bufferLength, d->file); + readPosition += bytesRead; + + // Check to see if we just read the last block. We need to call clear() + // if we did so that the last write succeeds. + + if(bytesRead < bufferLength) + clear(); + + seek(writePosition); + fwrite(buffer.data(), sizeof(char), bytesRead, d->file); + writePosition += bytesRead; + } + truncate(writePosition); +} + +bool File::readOnly() const +{ + return d->readOnly; +} + +bool File::isReadable(const char *file) +{ + return access(file, R_OK) == 0; +} + +bool File::isOpen() const +{ + return (d->file != NULL); +} + +bool File::isValid() const +{ + return isOpen() && d->valid; +} + +void File::seek(long offset, Position p) +{ + if(!d->file) { + debug("File::seek() -- trying to seek in a file that isn't opened."); + return; + } + + switch(p) { + case Beginning: + fseek(d->file, offset, SEEK_SET); + break; + case Current: + fseek(d->file, offset, SEEK_CUR); + break; + case End: + fseek(d->file, offset, SEEK_END); + break; + } +} + +void File::clear() +{ + clearerr(d->file); +} + +long File::tell() const +{ + return ftell(d->file); +} + +long File::length() +{ + // Do some caching in case we do multiple calls. + + if(d->size > 0) + return d->size; + + if(!d->file) + return 0; + + long curpos = tell(); + + seek(0, End); + long endpos = tell(); + + seek(curpos, Beginning); + + d->size = endpos; + return endpos; +} + +bool File::isWritable(const char *file) +{ + return access(file, W_OK) == 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void File::setValid(bool valid) +{ + d->valid = valid; +} + +void File::truncate(long length) +{ + ftruncate(fileno(d->file), length); +} + +TagLib::uint File::bufferSize() +{ + return FilePrivate::bufferSize; +} diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tfile.h b/Plugins/PluginNowPlaying/taglib/toolkit/tfile.h new file mode 100644 index 00000000..da322809 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tfile.h @@ -0,0 +1,270 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FILE_H +#define TAGLIB_FILE_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" + +namespace TagLib { + + class String; + class Tag; + class AudioProperties; + +#ifdef _WIN32 + class TAGLIB_EXPORT FileName + { + public: + FileName(const wchar_t *name) : m_wname(name) {} + FileName(const char *name) : m_name(name) {} + operator const wchar_t *() const { return m_wname.c_str(); } + operator const char *() const { return m_name.c_str(); } + private: + std::string m_name; + std::wstring m_wname; + }; +#else + typedef const char *FileName; +#endif + + //! A file class with some useful methods for tag manipulation + + /*! + * This class is a basic file class with some methods that are particularly + * useful for tag editors. It has methods to take advantage of + * ByteVector and a binary search method for finding patterns in a file. + */ + + class TAGLIB_EXPORT File + { + public: + /*! + * Position in the file used for seeking. + */ + enum Position { + //! Seek from the beginning of the file. + Beginning, + //! Seek from the current position in the file. + Current, + //! Seek from the end of the file. + End + }; + + /*! + * Destroys this File instance. + */ + virtual ~File(); + + /*! + * Returns the file name in the local file system encoding. + */ + FileName name() const; + + /*! + * Returns a pointer to this file's tag. This should be reimplemented in + * the concrete subclasses. + */ + virtual Tag *tag() const = 0; + + /*! + * Returns a pointer to this file's audio properties. This should be + * reimplemented in the concrete subclasses. If no audio properties were + * read then this will return a null pointer. + */ + virtual AudioProperties *audioProperties() const = 0; + + /*! + * Save the file and its associated tags. This should be reimplemented in + * the concrete subclasses. Returns true if the save succeeds. + * + * \warning On UNIX multiple processes are able to write to the same file at + * the same time. This can result in serious file corruption. If you are + * developing a program that makes use of TagLib from multiple processes you + * must insure that you are only doing writes to a particular file from one + * of them. + */ + virtual bool save() = 0; + + /*! + * Reads a block of size \a length at the current get pointer. + */ + ByteVector readBlock(ulong length); + + /*! + * Attempts to write the block \a data at the current get pointer. If the + * file is currently only opened read only -- i.e. readOnly() returns true -- + * this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator + * for a ByteVector. And even this function is significantly slower than + * doing output with a char[]. + */ + void writeBlock(const ByteVector &data); + + /*! + * Returns the offset in the file that \a pattern occurs at or -1 if it can + * not be found. If \a before is set, the search will only continue until the + * pattern \a before is found. This is useful for tagging purposes to search + * for a tag before the synch frame. + * + * Searching starts at \a fromOffset, which defaults to the beginning of the + * file. + * + * \note This has the practial limitation that \a pattern can not be longer + * than the buffer size used by readBlock(). Currently this is 1024 bytes. + */ + long find(const ByteVector &pattern, + long fromOffset = 0, + const ByteVector &before = ByteVector::null); + + /*! + * Returns the offset in the file that \a pattern occurs at or -1 if it can + * not be found. If \a before is set, the search will only continue until the + * pattern \a before is found. This is useful for tagging purposes to search + * for a tag before the synch frame. + * + * Searching starts at \a fromOffset and proceeds from the that point to the + * beginning of the file and defaults to the end of the file. + * + * \note This has the practial limitation that \a pattern can not be longer + * than the buffer size used by readBlock(). Currently this is 1024 bytes. + */ + long rfind(const ByteVector &pattern, + long fromOffset = 0, + const ByteVector &before = ByteVector::null); + + /*! + * Insert \a data at position \a start in the file overwriting \a replace + * bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file + * after the insertion point. + */ + void insert(const ByteVector &data, ulong start = 0, ulong replace = 0); + + /*! + * Removes a block of the file starting a \a start and continuing for + * \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file + * after the removed portion. + */ + void removeBlock(ulong start = 0, ulong length = 0); + + /*! + * Returns true if the file is read only (or if the file can not be opened). + */ + bool readOnly() const; + + /*! + * Since the file can currently only be opened as an argument to the + * constructor (sort-of by design), this returns if that open succeeded. + */ + bool isOpen() const; + + /*! + * Returns true if the file is open and readble. + */ + bool isValid() const; + + /*! + * Move the I/O pointer to \a offset in the file from position \a p. This + * defaults to seeking from the beginning of the file. + * + * \see Position + */ + void seek(long offset, Position p = Beginning); + + /*! + * Reset the end-of-file and error flags on the file. + */ + void clear(); + + /*! + * Returns the current offset within the file. + */ + long tell() const; + + /*! + * Returns the length of the file. + */ + long length(); + + /*! + * Returns true if \a file can be opened for reading. If the file does not + * exist, this will return false. + * + * \deprecated + */ + static bool isReadable(const char *file); + + /*! + * Returns true if \a file can be opened for writing. + * + * \deprecated + */ + static bool isWritable(const char *name); + + protected: + /*! + * Construct a File object and opens the \a file. \a file should be a + * be a C-string in the local file system encoding. + * + * \note Constructor is protected since this class should only be + * instantiated through subclasses. + */ + File(FileName file); + + /*! + * Marks the file as valid or invalid. + * + * \see isValid() + */ + void setValid(bool valid); + + /*! + * Truncates the file to a \a length. + */ + void truncate(long length); + + /*! + * Returns the buffer size that is used for internal buffering. + */ + static uint bufferSize(); + + private: + File(const File &); + File &operator=(const File &); + + class FilePrivate; + FilePrivate *d; + }; + +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tlist.h b/Plugins/PluginNowPlaying/taglib/toolkit/tlist.h new file mode 100644 index 00000000..dce0e1c6 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tlist.h @@ -0,0 +1,252 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_LIST_H +#define TAGLIB_LIST_H + +#include "taglib.h" + +#include + +namespace TagLib { + + //! A generic, implicitly shared list. + + /*! + * This is basic generic list that's somewhere between a std::list and a + * QValueList. This class is implicitly shared. For example: + * + * \code + * + * TagLib::List l = someOtherIntList; + * + * \endcode + * + * The above example is very cheap. This also makes lists suitable for the + * return types of functions. The above example will just copy a pointer rather + * than copying the data in the list. When your \e shared list's data changes, + * only \e then will the data be copied. + */ + + template class List + { + public: +#ifndef DO_NOT_DOCUMENT + typedef typename std::list::iterator Iterator; + typedef typename std::list::const_iterator ConstIterator; +#endif + + /*! + * Constructs an empty list. + */ + List(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + List(const List &l); + + /*! + * Destroys this List instance. If auto deletion is enabled and this list + * contains a pointer type all of the memebers are also deleted. + */ + virtual ~List(); + + /*! + * Returns an STL style iterator to the beginning of the list. See + * std::list::const_iterator for the semantics. + */ + Iterator begin(); + + /*! + * Returns an STL style constant iterator to the beginning of the list. See + * std::list::iterator for the semantics. + */ + ConstIterator begin() const; + + /*! + * Returns an STL style iterator to the end of the list. See + * std::list::iterator for the semantics. + */ + Iterator end(); + + /*! + * Returns an STL style constant iterator to the end of the list. See + * std::list::const_iterator for the semantics. + */ + ConstIterator end() const; + + /*! + * Inserts a copy of \a value before \a it. + */ + Iterator insert(Iterator it, const T &value); + + /*! + * Inserts the \a value into the list. This assumes that the list is + * currently sorted. If \a unique is true then the value will not + * be inserted if it is already in the list. + */ + List &sortedInsert(const T &value, bool unique = false); + + /*! + * Appends \a item to the end of the list and returns a reference to the + * list. + */ + List &append(const T &item); + + /*! + * Appends all of the values in \a l to the end of the list and returns a + * reference to the list. + */ + List &append(const List &l); + + /*! + * Prepends \a item to the beginning list and returns a reference to the + * list. + */ + List &prepend(const T &item); + + /*! + * Prepends all of the items in \a l to the beginning list and returns a + * reference to the list. + */ + List &prepend(const List &l); + + /*! + * Clears the list. If auto deletion is enabled and this list contains a + * pointer type the members are also deleted. + * + * \see setAutoDelete() + */ + List &clear(); + + /*! + * Returns the number of elements in the list. + */ + uint size() const; + bool isEmpty() const; + + /*! + * Find the first occurrence of \a value. + */ + Iterator find(const T &value); + + /*! + * Find the first occurrence of \a value. + */ + ConstIterator find(const T &value) const; + + /*! + * Returns true if the list contains \a value. + */ + bool contains(const T &value) const; + + /*! + * Erase the item at \a it from the list. + */ + Iterator erase(Iterator it); + + /*! + * Returns a reference to the first item in the list. + */ + const T &front() const; + + /*! + * Returns a reference to the first item in the list. + */ + T &front(); + + /*! + * Returns a reference to the last item in the list. + */ + const T &back() const; + + /*! + * Returns a reference to the last item in the list. + */ + T &back(); + + /*! + * Auto delete the members of the list when the last reference to the list + * passes out of scope. This will have no effect on lists which do not + * contain a pointer type. + * + * \note This relies on partial template instantiation -- most modern C++ + * compilers should now support this. + */ + void setAutoDelete(bool autoDelete); + + /*! + * Returns a reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ + T &operator[](uint i); + + /*! + * Returns a const reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ + const T &operator[](uint i) const; + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + List &operator=(const List &l); + + /*! + * Compares this list with \a l and returns true if all of the elements are + * the same. + */ + bool operator==(const List &l) const; + + protected: + /* + * If this List is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: +#ifndef DO_NOT_DOCUMENT + template class ListPrivate; + ListPrivate *d; +#endif + }; + +} + +// Since GCC doesn't support the "export" keyword, we have to include the +// implementation. + +#include "tlist.tcc" + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tlist.tcc b/Plugins/PluginNowPlaying/taglib/toolkit/tlist.tcc new file mode 100644 index 00000000..a11887d8 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tlist.tcc @@ -0,0 +1,316 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +namespace TagLib { + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +// The functionality of List::setAutoDelete() is implemented here partial +// template specialization. This is implemented in such a way that calling +// setAutoDelete() on non-pointer types will simply have no effect. + +// A base for the generic and specialized private class types. New +// non-templatized members should be added here. + +class ListPrivateBase : public RefCounter +{ +public: + ListPrivateBase() : autoDelete(false) {} + bool autoDelete; +}; + +// A generic implementation + +template +template class List::ListPrivate : public ListPrivateBase +{ +public: + ListPrivate() : ListPrivateBase() {} + ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + void clear() { + list.clear(); + } + std::list list; +}; + +// A partial specialization for all pointer types that implements the +// setAutoDelete() functionality. + +template +template class List::ListPrivate : public ListPrivateBase +{ +public: + ListPrivate() : ListPrivateBase() {} + ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + ~ListPrivate() { + clear(); + } + void clear() { + if(autoDelete) { + typename std::list::const_iterator it = list.begin(); + for(; it != list.end(); ++it) + delete *it; + } + list.clear(); + } + std::list list; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +template +List::List() +{ + d = new ListPrivate; +} + +template +List::List(const List &l) : d(l.d) +{ + d->ref(); +} + +template +List::~List() +{ + if(d->deref()) + delete d; +} + +template +typename List::Iterator List::begin() +{ + detach(); + return d->list.begin(); +} + +template +typename List::ConstIterator List::begin() const +{ + return d->list.begin(); +} + +template +typename List::Iterator List::end() +{ + detach(); + return d->list.end(); +} + +template +typename List::ConstIterator List::end() const +{ + return d->list.end(); +} + +template +typename List::Iterator List::insert(Iterator it, const T &item) +{ + detach(); + return d->list.insert(it, item); +} + +template +List &List::sortedInsert(const T &value, bool unique) +{ + detach(); + Iterator it = begin(); + while(it != end() && *it < value) + ++it; + if(unique && it != end() && *it == value) + return *this; + insert(it, value); + return *this; +} + +template +List &List::append(const T &item) +{ + detach(); + d->list.push_back(item); + return *this; +} + +template +List &List::append(const List &l) +{ + detach(); + d->list.insert(d->list.end(), l.begin(), l.end()); + return *this; +} + +template +List &List::prepend(const T &item) +{ + detach(); + d->list.push_front(item); + return *this; +} + +template +List &List::prepend(const List &l) +{ + detach(); + d->list.insert(d->list.begin(), l.begin(), l.end()); + return *this; +} + +template +List &List::clear() +{ + detach(); + d->clear(); + return *this; +} + +template +TagLib::uint List::size() const +{ + return d->list.size(); +} + +template +bool List::isEmpty() const +{ + return d->list.empty(); +} + +template +typename List::Iterator List::find(const T &value) +{ + return std::find(d->list.begin(), d->list.end(), value); +} + +template +typename List::ConstIterator List::find(const T &value) const +{ + return std::find(d->list.begin(), d->list.end(), value); +} + +template +bool List::contains(const T &value) const +{ + return std::find(d->list.begin(), d->list.end(), value) != d->list.end(); +} + +template +typename List::Iterator List::erase(Iterator it) +{ + return d->list.erase(it); +} + +template +const T &List::front() const +{ + return d->list.front(); +} + +template +T &List::front() +{ + detach(); + return d->list.front(); +} + +template +const T &List::back() const +{ + return d->list.back(); +} + +template +void List::setAutoDelete(bool autoDelete) +{ + d->autoDelete = autoDelete; +} + +template +T &List::back() +{ + detach(); + return d->list.back(); +} + +template +T &List::operator[](uint i) +{ + Iterator it = d->list.begin(); + + for(uint j = 0; j < i; j++) + ++it; + + return *it; +} + +template +const T &List::operator[](uint i) const +{ + ConstIterator it = d->list.begin(); + + for(uint j = 0; j < i; j++) + ++it; + + return *it; +} + +template +List &List::operator=(const List &l) +{ + if(&l == this) + return *this; + + if(d->deref()) + delete d; + d = l.d; + d->ref(); + return *this; +} + +template +bool List::operator==(const List &l) const +{ + return d->list == l.d->list; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +template +void List::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new ListPrivate(d->list); + } +} + +} // namespace TagLib diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tmap.h b/Plugins/PluginNowPlaying/taglib/toolkit/tmap.h new file mode 100644 index 00000000..f2f8364c --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tmap.h @@ -0,0 +1,200 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MAP_H +#define TAGLIB_MAP_H + +#include +using namespace std; + +#include "taglib.h" + +namespace TagLib { + + //! A generic, implicitly shared map. + + /*! + * This implements a standard map container that associates a key with a value + * and has fast key-based lookups. This map is also implicitly shared making + * it suitable for pass-by-value usage. + */ + + template class Map + { + public: +#ifndef DO_NOT_DOCUMENT +#ifdef WANT_CLASS_INSTANTIATION_OF_MAP + // Some STL implementations get snippy over the use of the + // class keyword to distinguish different templates; Sun Studio + // in particular finds multiple specializations in certain rare + // cases and complains about that. GCC doesn't seem to mind, + // and uses the typedefs further below without the class keyword. + // Not all the specializations of Map can use the class keyword + // (when T is not actually a class type), so don't apply this + // generally. + typedef typename std::map::iterator Iterator; + typedef typename std::map::const_iterator ConstIterator; +#else + typedef typename std::map::iterator Iterator; + typedef typename std::map::const_iterator ConstIterator; +#endif +#endif + + /*! + * Constructs an empty Map. + */ + Map(); + + /*! + * Make a shallow, implicitly shared, copy of \a m. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + Map(const Map &m); + + /*! + * Destroys this instance of the Map. + */ + virtual ~Map(); + + /*! + * Returns an STL style iterator to the beginning of the map. See + * std::map::iterator for the semantics. + */ + Iterator begin(); + + /*! + * Returns an STL style iterator to the beginning of the map. See + * std::map::const_iterator for the semantics. + */ + ConstIterator begin() const; + + /*! + * Returns an STL style iterator to the end of the map. See + * std::map::iterator for the semantics. + */ + Iterator end(); + + /*! + * Returns an STL style iterator to the end of the map. See + * std::map::const_iterator for the semantics. + */ + ConstIterator end() const; + + /*! + * Inserts \a value under \a key in the map. If a value for \a key already + * exists it will be overwritten. + */ + Map &insert(const Key &key, const T &value); + + /*! + * Removes all of the elements from elements from the map. This however + * will not delete pointers if the mapped type is a pointer type. + */ + Map &clear(); + + /*! + * The number of elements in the map. + * + * \see isEmpty() + */ + uint size() const; + + /*! + * Returns true if the map is empty. + * + * \see size() + */ + bool isEmpty() const; + + /*! + * Find the first occurrence of \a key. + */ + Iterator find(const Key &key); + + /*! + * Find the first occurrence of \a key. + */ + ConstIterator find(const Key &key) const; + + /*! + * Returns true if the map contains an instance of \a key. + */ + bool contains(const Key &key) const; + + /*! + * Erase the item at \a it from the list. + */ + Map &erase(Iterator it); + + /*! + * Erase the item with \a key from the list. + */ + Map &erase(const Key &key); + + /*! + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ + const T &operator[](const Key &key) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ + T &operator[](const Key &key); + + /*! + * Make a shallow, implicitly shared, copy of \a m. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + Map &operator=(const Map &m); + + protected: + /* + * If this List is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: +#ifndef DO_NOT_DOCUMENT + template class MapPrivate; + MapPrivate *d; +#endif + }; + +} + +// Since GCC doesn't support the "export" keyword, we have to include the +// implementation. + +#include "tmap.tcc" + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tmap.tcc b/Plugins/PluginNowPlaying/taglib/toolkit/tmap.tcc new file mode 100644 index 00000000..0f2b9933 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tmap.tcc @@ -0,0 +1,196 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +namespace TagLib { + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +template +template +class Map::MapPrivate : public RefCounter +{ +public: + MapPrivate() : RefCounter() {} +#ifdef WANT_CLASS_INSTANTIATION_OF_MAP + MapPrivate(const std::map& m) : RefCounter(), map(m) {} + std::map map; +#else + MapPrivate(const std::map& m) : RefCounter(), map(m) {} + std::map map; +#endif +}; + +template +Map::Map() +{ + d = new MapPrivate; +} + +template +Map::Map(const Map &m) : d(m.d) +{ + d->ref(); +} + +template +Map::~Map() +{ + if(d->deref()) + delete(d); +} + +template +typename Map::Iterator Map::begin() +{ + detach(); + return d->map.begin(); +} + +template +typename Map::ConstIterator Map::begin() const +{ + return d->map.begin(); +} + +template +typename Map::Iterator Map::end() +{ + detach(); + return d->map.end(); +} + +template +typename Map::ConstIterator Map::end() const +{ + return d->map.end(); +} + +template +Map &Map::insert(const Key &key, const T &value) +{ + detach(); + d->map[key] = value; + return *this; +} + +template +Map &Map::clear() +{ + detach(); + d->map.clear(); + return *this; +} + +template +bool Map::isEmpty() const +{ + return d->map.empty(); +} + +template +typename Map::Iterator Map::find(const Key &key) +{ + detach(); + return d->map.find(key); +} + +template +typename Map::ConstIterator Map::find(const Key &key) const +{ + return d->map.find(key); +} + +template +bool Map::contains(const Key &key) const +{ + return d->map.find(key) != d->map.end(); +} + +template +Map &Map::erase(Iterator it) +{ + detach(); + d->map.erase(it); + return *this; +} + +template +Map &Map::erase(const Key &key) +{ + detach(); + Iterator it = d->map.find(key); + if(it != d->map.end()) + d->map.erase(it); + return *this; +} + +template +TagLib::uint Map::size() const +{ + return d->map.size(); +} + +template +const T &Map::operator[](const Key &key) const +{ + return d->map[key]; +} + +template +T &Map::operator[](const Key &key) +{ + detach(); + return d->map[key]; +} + +template +Map &Map::operator=(const Map &m) +{ + if(&m == this) + return *this; + + if(d->deref()) + delete(d); + d = m.d; + d->ref(); + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +template +void Map::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new MapPrivate(d->map); + } +} + +} // namespace TagLib diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tstring.cpp b/Plugins/PluginNowPlaying/taglib/toolkit/tstring.cpp new file mode 100644 index 00000000..99a10b10 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tstring.cpp @@ -0,0 +1,811 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tstring.h" +#include "unicode.h" +#include "tdebug.h" + +#include + +#include + +namespace TagLib { + + inline unsigned short byteSwap(unsigned short x) + { + return (((x) >> 8) & 0xff) | (((x) & 0xff) << 8); + } + + inline unsigned short combine(unsigned char c1, unsigned char c2) + { + return (c1 << 8) | c2; + } +} + +using namespace TagLib; + +class String::StringPrivate : public RefCounter +{ +public: + StringPrivate(const wstring &s) : + RefCounter(), + data(s), + CString(0) {} + + StringPrivate() : + RefCounter(), + CString(0) {} + + ~StringPrivate() { + delete [] CString; + } + + wstring data; + + /*! + * This is only used to hold the a pointer to the most recent value of + * toCString. + */ + char *CString; +}; + +String String::null; + +//////////////////////////////////////////////////////////////////////////////// + +String::String() +{ + d = new StringPrivate; +} + +String::String(const String &s) : d(s.d) +{ + d->ref(); +} + +String::String(const std::string &s, Type t) +{ + d = new StringPrivate; + + if(t == UTF16 || t == UTF16BE || t == UTF16LE) { + debug("String::String() -- A std::string should not contain UTF16."); + return; + } + + int length = s.length(); + d->data.resize(length); + wstring::iterator targetIt = d->data.begin(); + + for(std::string::const_iterator it = s.begin(); it != s.end(); it++) { + *targetIt = uchar(*it); + ++targetIt; + } + + prepare(t); +} + +String::String(const wstring &s, Type t) +{ + d = new StringPrivate(s); + prepare(t); +} + +String::String(const wchar_t *s, Type t) +{ + d = new StringPrivate(s); + prepare(t); +} + +String::String(const char *s, Type t) +{ + d = new StringPrivate; + + if(t == UTF16 || t == UTF16BE || t == UTF16LE) { + debug("String::String() -- A const char * should not contain UTF16."); + return; + } + + int length = ::strlen(s); + d->data.resize(length); + + wstring::iterator targetIt = d->data.begin(); + + for(int i = 0; i < length; i++) { + *targetIt = uchar(s[i]); + ++targetIt; + } + + prepare(t); +} + +String::String(wchar_t c, Type t) +{ + d = new StringPrivate; + d->data += c; + prepare(t); +} + +String::String(char c, Type t) +{ + d = new StringPrivate; + + if(t == UTF16 || t == UTF16BE || t == UTF16LE) { + debug("String::String() -- A std::string should not contain UTF16."); + return; + } + + d->data += uchar(c); + prepare(t); +} + +String::String(const ByteVector &v, Type t) +{ + d = new StringPrivate; + + if(v.isEmpty()) + return; + + if(t == Latin1 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); + wstring::iterator targetIt = d->data.begin(); + for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { + *targetIt = uchar(*it); + ++targetIt; + ++length; + } + d->data.resize(length); + } + else { + d->data.resize(v.size() / 2); + wstring::iterator targetIt = d->data.begin(); + + for(ByteVector::ConstIterator it = v.begin(); + it != v.end() && it + 1 != v.end() && combine(*it, *(it + 1)); + it += 2) + { + *targetIt = combine(*it, *(it + 1)); + ++targetIt; + } + } + prepare(t); +} + +//////////////////////////////////////////////////////////////////////////////// + +String::~String() +{ + if(d->deref()) + delete d; +} + +std::string String::to8Bit(bool unicode) const +{ + std::string s; + s.resize(d->data.size()); + + if(!unicode) { + std::string::iterator targetIt = s.begin(); + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { + *targetIt = char(*it); + ++targetIt; + } + return s; + } + + const int outputBufferSize = d->data.size() * 3 + 1; + + Unicode::UTF16 *sourceBuffer = new Unicode::UTF16[d->data.size() + 1]; + Unicode::UTF8 *targetBuffer = new Unicode::UTF8[outputBufferSize]; + + for(unsigned int i = 0; i < d->data.size(); i++) + sourceBuffer[i] = Unicode::UTF16(d->data[i]); + + const Unicode::UTF16 *source = sourceBuffer; + Unicode::UTF8 *target = targetBuffer; + + Unicode::ConversionResult result = + Unicode::ConvertUTF16toUTF8(&source, sourceBuffer + d->data.size(), + &target, targetBuffer + outputBufferSize, + Unicode::lenientConversion); + + if(result != Unicode::conversionOK) + debug("String::to8Bit() - Unicode conversion error."); + + int newSize = target - targetBuffer; + s.resize(newSize); + targetBuffer[newSize] = 0; + + s = (char *) targetBuffer; + + delete [] sourceBuffer; + delete [] targetBuffer; + + return s; +} + +TagLib::wstring String::toWString() const +{ + return d->data; +} + +const char *String::toCString(bool unicode) const +{ + delete [] d->CString; + + std::string buffer = to8Bit(unicode); + d->CString = new char[buffer.size() + 1]; + strcpy(d->CString, buffer.c_str()); + + return d->CString; +} + +String::Iterator String::begin() +{ + return d->data.begin(); +} + +String::ConstIterator String::begin() const +{ + return d->data.begin(); +} + +String::Iterator String::end() +{ + return d->data.end(); +} + +String::ConstIterator String::end() const +{ + return d->data.end(); +} + +int String::find(const String &s, int offset) const +{ + wstring::size_type position = d->data.find(s.d->data, offset); + + if(position != wstring::npos) + return position; + else + return -1; +} + +int String::rfind(const String &s, int offset) const +{ + wstring::size_type position = + d->data.rfind(s.d->data, offset == -1 ? wstring::npos : offset); + + if(position != wstring::npos) + return position; + else + return -1; +} + +bool String::startsWith(const String &s) const +{ + if(s.length() > length()) + return false; + + return substr(0, s.length()) == s; +} + +String String::substr(uint position, uint n) const +{ + if(n > position + d->data.size()) + n = d->data.size() - position; + + String s; + s.d->data = d->data.substr(position, n); + return s; +} + +String &String::append(const String &s) +{ + detach(); + d->data += s.d->data; + return *this; +} + +String String::upper() const +{ + String s; + + static int shift = 'A' - 'a'; + + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); ++it) { + if(*it >= 'a' && *it <= 'z') + s.d->data.push_back(*it + shift); + else + s.d->data.push_back(*it); + } + + return s; +} + +TagLib::uint String::size() const +{ + return d->data.size(); +} + +TagLib::uint String::length() const +{ + return size(); +} + +bool String::isEmpty() const +{ + return d->data.size() == 0; +} + +bool String::isNull() const +{ + return d == null.d; +} + +ByteVector String::data(Type t) const +{ + ByteVector v; + + switch(t) { + + case Latin1: + { + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; + } + case UTF8: + { + std::string s = to8Bit(true); + v.setData(s.c_str(), s.length()); + break; + } + case UTF16: + { + // Assume that if we're doing UTF16 and not UTF16BE that we want little + // endian encoding. (Byte Order Mark) + + v.append(char(0xff)); + v.append(char(0xfe)); + + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { + + char c1 = *it & 0xff; + char c2 = *it >> 8; + + v.append(c1); + v.append(c2); + } + break; + } + case UTF16BE: + { + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { + + char c1 = *it >> 8; + char c2 = *it & 0xff; + + v.append(c1); + v.append(c2); + } + break; + } + case UTF16LE: + { + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { + + char c1 = *it & 0xff; + char c2 = *it >> 8; + + v.append(c1); + v.append(c2); + } + break; + } + } + + return v; +} + +int String::toInt() const +{ + return toInt(0); +} + +int String::toInt(bool *ok) const +{ + int value = 0; + + uint size = d->data.size(); + bool negative = size > 0 && d->data[0] == '-'; + uint start = negative ? 1 : 0; + uint i = start; + + for(; i < size && d->data[i] >= '0' && d->data[i] <= '9'; i++) + value = value * 10 + (d->data[i] - '0'); + + if(negative) + value = value * -1; + + if(ok) + *ok = (size > start && i == size); + + return value; +} + +String String::stripWhiteSpace() const +{ + wstring::const_iterator begin = d->data.begin(); + wstring::const_iterator end = d->data.end(); + + while(begin != end && + (*begin == '\t' || *begin == '\n' || *begin == '\f' || + *begin == '\r' || *begin == ' ')) + { + ++begin; + } + + if(begin == end) + return null; + + // There must be at least one non-whitespace character here for us to have + // gotten this far, so we should be safe not doing bounds checking. + + do { + --end; + } while(*end == '\t' || *end == '\n' || + *end == '\f' || *end == '\r' || *end == ' '); + + return String(wstring(begin, end + 1)); +} + +bool String::isLatin1() const +{ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { + if(*it >= 256) + return false; + } + return true; +} + +bool String::isAscii() const +{ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) { + if(*it >= 128) + return false; + } + return true; +} + +String String::number(int n) // static +{ + if(n == 0) + return String("0"); + + String charStack; + + bool negative = n < 0; + + if(negative) + n = n * -1; + + while(n > 0) { + int remainder = n % 10; + charStack += char(remainder + '0'); + n = (n - remainder) / 10; + } + + String s; + + if(negative) + s += '-'; + + for(int i = charStack.d->data.size() - 1; i >= 0; i--) + s += charStack.d->data[i]; + + return s; +} + +TagLib::wchar &String::operator[](int i) +{ + detach(); + + return d->data[i]; +} + +const TagLib::wchar &String::operator[](int i) const +{ + return d->data[i]; +} + +bool String::operator==(const String &s) const +{ + return d == s.d || d->data == s.d->data; +} + +String &String::operator+=(const String &s) +{ + detach(); + + d->data += s.d->data; + return *this; +} + +String &String::operator+=(const wchar_t *s) +{ + detach(); + + d->data += s; + return *this; +} + +String &String::operator+=(const char *s) +{ + detach(); + + for(int i = 0; s[i] != 0; i++) + d->data += uchar(s[i]); + return *this; +} + +String &String::operator+=(wchar_t c) +{ + detach(); + + d->data += c; + return *this; +} + +String &String::operator+=(char c) +{ + detach(); + + d->data += uchar(c); + return *this; +} + +String &String::operator=(const String &s) +{ + if(&s == this) + return *this; + + if(d->deref()) + delete d; + d = s.d; + d->ref(); + return *this; +} + +String &String::operator=(const std::string &s) +{ + if(d->deref()) + delete d; + + d = new StringPrivate; + + d->data.resize(s.size()); + + wstring::iterator targetIt = d->data.begin(); + for(std::string::const_iterator it = s.begin(); it != s.end(); it++) { + *targetIt = uchar(*it); + ++targetIt; + } + + return *this; +} + +String &String::operator=(const wstring &s) +{ + if(d->deref()) + delete d; + d = new StringPrivate(s); + return *this; +} + +String &String::operator=(const wchar_t *s) +{ + if(d->deref()) + delete d; + d = new StringPrivate(s); + return *this; +} + +String &String::operator=(char c) +{ + if(d->deref()) + delete d; + d = new StringPrivate; + d->data += uchar(c); + return *this; +} + +String &String::operator=(wchar_t c) +{ + if(d->deref()) + delete d; + d = new StringPrivate; + d->data += c; + return *this; +} + +String &String::operator=(const char *s) +{ + if(d->deref()) + delete d; + + d = new StringPrivate; + + int length = ::strlen(s); + d->data.resize(length); + + wstring::iterator targetIt = d->data.begin(); + for(int i = 0; i < length; i++) { + *targetIt = uchar(s[i]); + ++targetIt; + } + + return *this; +} + +String &String::operator=(const ByteVector &v) +{ + if(d->deref()) + delete d; + + d = new StringPrivate; + d->data.resize(v.size()); + wstring::iterator targetIt = d->data.begin(); + + uint i = 0; + + for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { + *targetIt = uchar(*it); + ++targetIt; + ++i; + } + + // If we hit a null in the ByteVector, shrink the string again. + + d->data.resize(i); + + return *this; +} + +bool String::operator<(const String &s) const +{ + return d->data < s.d->data; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void String::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new StringPrivate(d->data); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void String::prepare(Type t) +{ + switch(t) { + case UTF16: + { + if(d->data.size() >= 1 && (d->data[0] == 0xfeff || d->data[0] == 0xfffe)) { + bool swap = d->data[0] != 0xfeff; + d->data.erase(d->data.begin(), d->data.begin() + 1); + if(swap) { + for(uint i = 0; i < d->data.size(); i++) + d->data[i] = byteSwap((unsigned short)d->data[i]); + } + } + else { + debug("String::prepare() - Invalid UTF16 string."); + d->data.erase(d->data.begin(), d->data.end()); + } + break; + } + case UTF8: + { + int bufferSize = d->data.size() + 1; + Unicode::UTF8 *sourceBuffer = new Unicode::UTF8[bufferSize]; + Unicode::UTF16 *targetBuffer = new Unicode::UTF16[bufferSize]; + + unsigned int i = 0; + for(; i < d->data.size(); i++) + sourceBuffer[i] = Unicode::UTF8(d->data[i]); + sourceBuffer[i] = 0; + + const Unicode::UTF8 *source = sourceBuffer; + Unicode::UTF16 *target = targetBuffer; + + Unicode::ConversionResult result = + Unicode::ConvertUTF8toUTF16(&source, sourceBuffer + bufferSize, + &target, targetBuffer + bufferSize, + Unicode::lenientConversion); + + if(result != Unicode::conversionOK) + debug("String::prepare() - Unicode conversion error."); + + + int newSize = target != targetBuffer ? target - targetBuffer - 1 : 0; + d->data.resize(newSize); + + for(int i = 0; i < newSize; i++) + d->data[i] = targetBuffer[i]; + + delete [] sourceBuffer; + delete [] targetBuffer; + + break; + } + case UTF16LE: + { + for(uint i = 0; i < d->data.size(); i++) + d->data[i] = byteSwap((unsigned short)d->data[i]); + break; + } + default: + break; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// related functions +//////////////////////////////////////////////////////////////////////////////// + +const TagLib::String operator+(const TagLib::String &s1, const TagLib::String &s2) +{ + String s(s1); + s.append(s2); + return s; +} + +const TagLib::String operator+(const char *s1, const TagLib::String &s2) +{ + String s(s1); + s.append(s2); + return s; +} + +const TagLib::String operator+(const TagLib::String &s1, const char *s2) +{ + String s(s1); + s.append(s2); + return s; +} + +std::ostream &operator<<(std::ostream &s, const String &str) +{ + s << str.to8Bit(); + return s; +} diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tstring.h b/Plugins/PluginNowPlaying/taglib/toolkit/tstring.h new file mode 100644 index 00000000..693d043f --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tstring.h @@ -0,0 +1,483 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_STRING_H +#define TAGLIB_STRING_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" + +#include +#include + +/*! + * \relates TagLib::String + * + * Converts a QString to a TagLib::String without a requirement to link to Qt. + * + * \note consider conversion via usual char-by-char for loop to avoid UTF16->UTF8->UTF16 + * conversion happening in the background + */ +#define QStringToTString(s) TagLib::String(s.utf8().data(), TagLib::String::UTF8) + +/*! + * \relates TagLib::String + * + * Converts a TagLib::String to a QString without a requirement to link to Qt. + * + * \note consider conversion via usual char-by-char for loop to avoid UTF16->UTF8->UTF16 + * conversion happening in the background + * + */ +#define TStringToQString(s) QString::fromUtf8(s.toCString(true)) + +namespace TagLib { + + //! A \e wide string class suitable for unicode. + + /*! + * This is an implicitly shared \e wide string. For storage it uses + * TagLib::wstring, but as this is an implementation detail this of + * course could change. Strings are stored internally as UTF-16BE. (Without + * the BOM (Byte Order Mark) + * + * The use of implicit sharing means that copying a string is cheap, the only + * \e cost comes into play when the copy is modified. Prior to that the string + * just has a pointer to the data of the \e parent String. This also makes + * this class suitable as a function return type. + * + * In addition to adding implicit sharing, this class keeps track of four + * possible encodings, which are the four supported by the ID3v2 standard. + */ + + class TAGLIB_EXPORT String + { + public: + +#ifndef DO_NOT_DOCUMENT + typedef std::basic_string::iterator Iterator; + typedef std::basic_string::const_iterator ConstIterator; +#endif + + /** + * The four types of string encodings supported by the ID3v2 specification. + * ID3v1 is assumed to be Latin1 and Ogg Vorbis comments use UTF8. + */ + enum Type { + /*! + * IS08859-1, or Latin1 encoding. 8 bit characters. + */ + Latin1 = 0, + /*! + * UTF16 with a byte order mark. 16 bit characters. + */ + UTF16 = 1, + /*! + * UTF16 big endian. 16 bit characters. This is the encoding used + * internally by TagLib. + */ + UTF16BE = 2, + /*! + * UTF8 encoding. Characters are usually 8 bits but can be up to 32. + */ + UTF8 = 3, + /*! + * UTF16 little endian. 16 bit characters. + */ + UTF16LE = 4 + }; + + /*! + * Constructs an empty String. + */ + String(); + + /*! + * Make a shallow, implicitly shared, copy of \a s. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + String(const String &s); + + /*! + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(const std::string &s, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a s. + */ + String(const wstring &s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a s. + */ + String(const wchar_t *s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a c. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(char c, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a c. + */ + String(wchar_t c, Type t = Latin1); + + + /*! + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(const char *s, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(const ByteVector &v, Type t = Latin1); + + /*! + * Destroys this String instance. + */ + virtual ~String(); + + /*! + * If \a unicode if false (the default) this will return a \e Latin1 encoded + * std::string. If it is true the returned std::wstring will be UTF-8 + * encoded. + */ + std::string to8Bit(bool unicode = false) const; + + /*! + * Returns a wstring version of the TagLib string as a wide string. + */ + wstring toWString() const; + + /*! + * Creates and returns a C-String based on the data. This string is still + * owned by the String (class) and as such should not be deleted by the user. + * + * If \a unicode if false (the default) this string will be encoded in + * \e Latin1. If it is true the returned C-String will be UTF-8 encoded. + * + * This string remains valid until the String instance is destroyed or + * another export method is called. + * + * \warning This however has the side effect that this C-String will remain + * in memory in addition to other memory that is consumed by the + * String instance. So, this method should not be used on large strings or + * where memory is critical. + */ + const char *toCString(bool unicode = false) const; + + /*! + * Returns an iterator pointing to the beginning of the string. + */ + Iterator begin(); + + /*! + * Returns a const iterator pointing to the beginning of the string. + */ + ConstIterator begin() const; + + /*! + * Returns an iterator pointing to the end of the string (the position + * after the last character). + */ + Iterator end(); + + /*! + * Returns a const iterator pointing to the end of the string (the position + * after the last character). + */ + ConstIterator end() const; + + /*! + * Finds the first occurrence of pattern \a s in this string starting from + * \a offset. If the pattern is not found, -1 is returned. + */ + int find(const String &s, int offset = 0) const; + + /*! + * Finds the last occurrence of pattern \a s in this string, searched backwards, + * either from the end of the string or starting from \a offset. If the pattern + * is not found, -1 is returned. + */ + int rfind(const String &s, int offset = -1) const; + + /*! + * Returns true if the strings starts with the substring \a s. + */ + bool startsWith(const String &s) const; + + /*! + * Extract a substring from this string starting at \a position and + * continuing for \a n characters. + */ + String substr(uint position, uint n = 0xffffffff) const; + + /*! + * Append \a s to the current string and return a reference to the current + * string. + */ + String &append(const String &s); + + /*! + * Returns an upper case version of the string. + * + * \warning This only works for the characters in US-ASCII, i.e. A-Z. + */ + String upper() const; + + /*! + * Returns the size of the string. + */ + uint size() const; + + /*! + * Returns the length of the string. Equivalent to size(). + */ + uint length() const; + + /*! + * Returns true if the string is empty. + * + * \see isNull() + */ + bool isEmpty() const; + + /*! + * Returns true if this string is null -- i.e. it is a copy of the + * String::null string. + * + * \note A string can be empty and not null. + * \see isEmpty() + */ + bool isNull() const; + + /*! + * Returns a ByteVector containing the string's data. If \a t is Latin1 or + * UTF8, this will return a vector of 8 bit characters, otherwise it will use + * 16 bit characters. + */ + ByteVector data(Type t) const; + + /*! + * Convert the string to an integer. + * + * Returns the integer if the conversion was successfull or 0 if the + * string does not represent a number. + */ + // BIC: merge with the method below + int toInt() const; + + /*! + * Convert the string to an integer. + * + * If the conversion was successfull, it sets the value of \a *ok to + * true and returns the integer. Otherwise it sets \a *ok to false + * and the result is undefined. + */ + int toInt(bool *ok) const; + + /*! + * Returns a string with the leading and trailing whitespace stripped. + */ + String stripWhiteSpace() const; + + /*! + * Returns true if the file only uses characters required by Latin1. + */ + bool isLatin1() const; + + /*! + * Returns true if the file only uses characters required by (7-bit) ASCII. + */ + bool isAscii() const; + + /*! + * Converts the base-10 integer \a n to a string. + */ + static String number(int n); + + /*! + * Returns a reference to the character at position \a i. + */ + wchar &operator[](int i); + + /*! + * Returns a const reference to the character at position \a i. + */ + const wchar &operator[](int i) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns true if the strings match. + */ + bool operator==(const String &s) const; + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const String &s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const wchar_t* s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const char* s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(wchar_t c); + + /*! + * Appends \a c to the end of the String. + */ + String &operator+=(char c); + + /*! + * Performs a shallow, implicitly shared, copy of \a s, overwriting the + * String's current data. + */ + String &operator=(const String &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const std::string &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const wstring &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const wchar_t *s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(char c); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(wchar_t c); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const char *s); + + /*! + * Performs a deep copy of the data in \a v. + */ + String &operator=(const ByteVector &v); + + /*! + * To be able to use this class in a Map, this operator needed to be + * implemented. Returns true if \a s is less than this string in a bytewise + * comparison. + */ + bool operator<(const String &s) const; + + /*! + * A null string provided for convenience. + */ + static String null; + + protected: + /*! + * If this String is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: + /*! + * This checks to see if the string is in \e UTF-16 (with BOM) or \e UTF-8 + * format and if so converts it to \e UTF-16BE for internal use. \e Latin1 + * does not require conversion since it is a subset of \e UTF-16BE and + * \e UTF16-BE requires no conversion since it is used internally. + */ + void prepare(Type t); + + class StringPrivate; + StringPrivate *d; + }; + +} + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const TagLib::String &s1, const TagLib::String &s2); + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const char *s1, const TagLib::String &s2); + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const TagLib::String &s1, const char *s2); + + +/*! + * \relates TagLib::String + * + * Send the string to an output stream. + */ +TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const TagLib::String &str); + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.cpp b/Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.cpp new file mode 100644 index 00000000..655fe6c4 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.cpp @@ -0,0 +1,123 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tstringlist.h" + +using namespace TagLib; + +class StringListPrivate +{ + +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +StringList StringList::split(const String &s, const String &pattern) +{ + StringList l; + + int previousOffset = 0; + for(int offset = s.find(pattern); offset != -1; offset = s.find(pattern, offset + 1)) { + l.append(s.substr(previousOffset, offset - previousOffset)); + previousOffset = offset + 1; + } + + l.append(s.substr(previousOffset, s.size() - previousOffset)); + + return l; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +StringList::StringList() : List() +{ + +} + +StringList::StringList(const StringList &l) : List(l) +{ + +} + +StringList::StringList(const String &s) : List() +{ + append(s); +} + +StringList::StringList(const ByteVectorList &bl, String::Type t) : List() +{ + ByteVectorList::ConstIterator i = bl.begin(); + for(;i != bl.end(); i++) { + append(String(*i, t)); + } +} + +StringList::~StringList() +{ + +} + +String StringList::toString(const String &separator) const +{ + String s; + + ConstIterator it = begin(); + ConstIterator itEnd = end(); + + while(it != itEnd) { + s += *it; + it++; + if(it != itEnd) + s += separator; + } + + return s; +} + +StringList &StringList::append(const String &s) +{ + List::append(s); + return *this; +} + +StringList &StringList::append(const StringList &l) +{ + List::append(l); + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +// related functions +//////////////////////////////////////////////////////////////////////////////// + +std::ostream &operator<<(std::ostream &s, const StringList &l) +{ + s << l.toString(); + return s; +} diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.h b/Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.h new file mode 100644 index 00000000..3ef131dc --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/tstringlist.h @@ -0,0 +1,115 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_STRINGLIST_H +#define TAGLIB_STRINGLIST_H + +#include "tstring.h" +#include "tlist.h" +#include "tbytevectorlist.h" +#include "taglib_export.h" + +#include + +namespace TagLib { + + //! A list of strings + + /*! + * This is a spcialization of the List class with some members convention for + * string operations. + */ + + class TAGLIB_EXPORT StringList : public List + { + public: + + /*! + * Constructs an empty StringList. + */ + StringList(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + StringList(const StringList &l); + + /*! + * Constructs a StringList with \a s as a member. + */ + StringList(const String &s); + + /*! + * Makes a deep copy of the data in \a vl. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + StringList(const ByteVectorList &vl, String::Type t = String::Latin1); + + /*! + * Destroys this StringList instance. + */ + virtual ~StringList(); + + /*! + * Concatenate the list of strings into one string separated by \a separator. + */ + String toString(const String &separator = " ") const; + + /*! + * Appends \a s to the end of the list and returns a reference to the + * list. + */ + StringList &append(const String &s); + + /*! + * Appends all of the values in \a l to the end of the list and returns a + * reference to the list. + */ + StringList &append(const StringList &l); + + /*! + * Splits the String \a s into several strings at \a pattern. This will not include + * the pattern in the returned strings. + */ + static StringList split(const String &s, const String &pattern); + + private: + class StringListPrivate; + StringListPrivate *d; + }; + +} + +/*! + * \related TagLib::StringList + * Send the StringList to an output stream. + */ +std::ostream &operator<<(std::ostream &s, const TagLib::StringList &l); + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/unicode.cpp b/Plugins/PluginNowPlaying/taglib/toolkit/unicode.cpp new file mode 100644 index 00000000..b60264d9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/unicode.cpp @@ -0,0 +1,303 @@ +/******************************************************************************* + * * + * THIS FILE IS INCLUDED IN TAGLIB, BUT IS NOT COPYRIGHTED BY THE TAGLIB * + * AUTHORS, NOT PART OF THE TAGLIB API AND COULD GO AWAY AT ANY POINT IN TIME. * + * AS SUCH IT SHOULD BE CONSIERED FOR INTERNAL USE ONLY. * + * * + *******************************************************************************/ + +/* + * Copyright 2001 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* + * This file has been modified by Scott Wheeler to remove + * the UTF32 conversion functions and to place the appropriate functions + * in their own C++ namespace. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "unicode.h" +#include + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +namespace Unicode { + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + */ +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... six byte sequence.) + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END && source < sourceEnd) { + UTF32 ch2 = *source; + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else if ((flags == strictConversion) && (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x200000) { bytesToWrite = 4; + } else { bytesToWrite = 2; + ch = UNI_REPLACEMENT_CHAR; + } + // printf("bytes to write = %i\n", bytesToWrite); + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (ch | byteMark) & byteMask; ch >>= 6; + case 3: *--target = (ch | byteMark) & byteMask; ch >>= 6; + case 2: *--target = (ch | byteMark) & byteMask; ch >>= 6; + case 1: *--target = ch | firstByteMark[bytesToWrite]; + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) > 0xBF) return false; + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + if (*source > 0xF4) return false; + } + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source]+1; + if (source+length > sourceEnd) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + if ((flags == strictConversion) && (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (ch >> halfShift) + UNI_SUR_HIGH_START; + *target++ = (ch & halfMask) + UNI_SUR_LOW_START; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */ + + diff --git a/Plugins/PluginNowPlaying/taglib/toolkit/unicode.h b/Plugins/PluginNowPlaying/taglib/toolkit/unicode.h new file mode 100644 index 00000000..cf7eb3c5 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/toolkit/unicode.h @@ -0,0 +1,149 @@ +#ifndef TAGLIB_UNICODE_H +#define TAGLIB_UNICODE_H + +/******************************************************************************* + * * + * THIS FILE IS INCLUDED IN TAGLIB, BUT IS NOT COPYRIGHTED BY THE TAGLIB * + * AUTHORS, NOT PART OF THE TAGLIB API AND COULD GO AWAY AT ANY POINT IN TIME. * + * AS SUCH IT SHOULD BE CONSIERED FOR INTERNAL USE ONLY. * + * * + *******************************************************************************/ + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +/* + * Copyright 2001 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* + * This file has been modified by Scott Wheeler to remove + * the UTF32 conversion functions and to place the appropriate functions + * in their own C++ namespace. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several functions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: , , + or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF + +namespace Unicode { + +typedef unsigned long UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +typedef enum { + conversionOK = 0, /* conversion successful */ + sourceExhausted = 1, /* partial character in source, but hit end */ + targetExhausted = 2, /* insuff. room in target for conversion */ + sourceIllegal = 3 /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +} // namespace Unicode + +/* --------------------------------------------------------------------- */ + +#endif +#endif diff --git a/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.cpp b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.cpp new file mode 100644 index 00000000..0f362da9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.cpp @@ -0,0 +1,272 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "trueaudiofile.h" +#include "id3v1tag.h" +#include "id3v2tag.h" +#include "id3v2header.h" + +using namespace TagLib; + +namespace +{ + enum { ID3v2Index = 0, ID3v1Index = 1 }; +} + +class TrueAudio::File::FilePrivate +{ +public: + FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : + ID3v2FrameFactory(frameFactory), + ID3v2Location(-1), + ID3v2OriginalSize(0), + ID3v1Location(-1), + properties(0), + hasID3v1(false), + hasID3v2(false) {} + + ~FilePrivate() + { + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + long ID3v2Location; + uint ID3v2OriginalSize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasID3v1; + bool hasID3v2; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TrueAudio::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + if(isOpen()) + read(readProperties, propertiesStyle); +} + +TrueAudio::File::File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate(frameFactory); + if(isOpen()) + read(readProperties, propertiesStyle); +} + +TrueAudio::File::~File() +{ + delete d; +} + +TagLib::Tag *TrueAudio::File::tag() const +{ + return &d->tag; +} + +TrueAudio::Properties *TrueAudio::File::audioProperties() const +{ + return d->properties; +} + +void TrueAudio::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + +bool TrueAudio::File::save() +{ + if(readOnly()) { + debug("TrueAudio::File::save() -- File is read only."); + return false; + } + + // Update ID3v2 tag + + if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) { + if(!d->hasID3v2) { + d->ID3v2Location = 0; + d->ID3v2OriginalSize = 0; + } + ByteVector data = ID3v2Tag()->render(); + insert(data, d->ID3v2Location, d->ID3v2OriginalSize); + d->ID3v1Location -= d->ID3v2OriginalSize - data.size(); + d->ID3v2OriginalSize = data.size(); + d->hasID3v2 = true; + } + else if(d->hasID3v2) { + removeBlock(d->ID3v2Location, d->ID3v2OriginalSize); + d->ID3v1Location -= d->ID3v2OriginalSize; + d->ID3v2Location = -1; + d->ID3v2OriginalSize = 0; + d->hasID3v2 = false; + } + + // Update ID3v1 tag + + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + if(!d->hasID3v1) { + seek(0, End); + d->ID3v1Location = tell(); + } + else + seek(d->ID3v1Location); + writeBlock(ID3v1Tag()->render()); + d->hasID3v1 = true; + } + else if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->ID3v1Location = -1; + d->hasID3v1 = false; + } + + return true; +} + +ID3v1::Tag *TrueAudio::File::ID3v1Tag(bool create) +{ + return d->tag.access(ID3v1Index, create); +} + +ID3v2::Tag *TrueAudio::File::ID3v2Tag(bool create) +{ + return d->tag.access(ID3v2Index, create); +} + +void TrueAudio::File::strip(int tags) +{ + if(tags & ID3v1) { + d->tag.set(ID3v1Index, 0); + ID3v2Tag(true); + } + + if(tags & ID3v2) { + d->tag.set(ID3v2Index, 0); + + if(!ID3v1Tag()) + ID3v2Tag(true); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TrueAudio::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + + d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory)); + + d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize(); + + if(ID3v2Tag()->header()->tagSize() <= 0) + d->tag.set(ID3v2Index, 0); + else + d->hasID3v2 = true; + } + + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + d->hasID3v1 = true; + } + + if(!d->hasID3v1) + ID3v2Tag(true); + + // Look for TrueAudio metadata + + if(readProperties) { + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location + d->ID3v2OriginalSize); + d->properties = new Properties(readBlock(TrueAudio::HeaderSize), + length() - d->ID3v2OriginalSize); + } + else { + seek(0); + d->properties = new Properties(readBlock(TrueAudio::HeaderSize), + length()); + } + } +} + +long TrueAudio::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} + +long TrueAudio::File::findID3v2() +{ + if(!isValid()) + return -1; + + seek(0); + + if(readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} diff --git a/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.h b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.h new file mode 100644 index 00000000..32cbf4b1 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudiofile.h @@ -0,0 +1,180 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOFILE_H +#define TAGLIB_TRUEAUDIOFILE_H + +#include "tfile.h" +#include "trueaudioproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + + //! An implementation of TrueAudio metadata + + /*! + * This is implementation of TrueAudio metadata. + * + * This supports ID3v1 and ID3v2 tags as well as reading stream + * properties from the file. + */ + + namespace TrueAudio { + + //! An implementation of TagLib::File with TrueAudio specific methods + + /*! + * This implements and provides an interface for TrueAudio files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to TrueAudio files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Contructs an TrueAudio 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, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Contructs an TrueAudio 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(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the TrueAudio::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + */ + void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the TrueAudio::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the TrueAudio::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findID3v1(); + long findID3v2(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.cpp b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.cpp new file mode 100644 index 00000000..5b1bf12d --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "trueaudioproperties.h" +#include "trueaudiofile.h" + +using namespace TagLib; + +class TrueAudio::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) : + data(d), + streamLength(length), + style(s), + version(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int version; + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +TrueAudio::Properties::~Properties() +{ + delete d; +} + +int TrueAudio::Properties::length() const +{ + return d->length; +} + +int TrueAudio::Properties::bitrate() const +{ + return d->bitrate; +} + +int TrueAudio::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int TrueAudio::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +int TrueAudio::Properties::channels() const +{ + return d->channels; +} + +int TrueAudio::Properties::ttaVersion() const +{ + return d->version; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TrueAudio::Properties::read() +{ + if(!d->data.startsWith("TTA")) + return; + + int pos = 3; + + d->version = d->data[pos] - '0'; + pos += 1 + 2; + + d->channels = d->data.mid(pos, 2).toShort(false); + pos += 2; + + d->bitsPerSample = d->data.mid(pos, 2).toShort(false); + pos += 2; + + d->sampleRate = d->data.mid(pos, 4).toUInt(false); + pos += 4; + + unsigned long samples = d->data.mid(pos, 4).toUInt(false); + d->length = samples / d->sampleRate; + + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} diff --git a/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.h b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.h new file mode 100644 index 00000000..f66fd2e9 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/trueaudio/trueaudioproperties.h @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOPROPERTIES_H +#define TAGLIB_TRUEAUDIOPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace TrueAudio { + + class File; + + static const uint HeaderSize = 18; + + //! An implementation of audio property reading for TrueAudio + + /*! + * This reads the data from an TrueAudio stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of TrueAudio::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this TrueAudio::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns number of bits per sample. + */ + int bitsPerSample() const; + + /*! + * Returns the major version number. + */ + int ttaVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.cpp b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.cpp new file mode 100644 index 00000000..999a5445 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.cpp @@ -0,0 +1,267 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "wavpackfile.h" +#include "id3v1tag.h" +#include "id3v2header.h" +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +namespace +{ + enum { APEIndex, ID3v1Index }; +} + +class WavPack::File::FilePrivate +{ +public: + FilePrivate() : + APELocation(-1), + APESize(0), + ID3v1Location(-1), + properties(0), + hasAPE(false), + hasID3v1(false) {} + + ~FilePrivate() + { + delete properties; + } + + long APELocation; + uint APESize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasAPE; + bool hasID3v1; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +WavPack::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +WavPack::File::~File() +{ + delete d; +} + +TagLib::Tag *WavPack::File::tag() const +{ + return &d->tag; +} + +WavPack::Properties *WavPack::File::audioProperties() const +{ + return d->properties; +} + +bool WavPack::File::save() +{ + if(readOnly()) { + debug("WavPack::File::save() -- File is read only."); + return false; + } + + // Update ID3v1 tag + + if(ID3v1Tag()) { + if(d->hasID3v1) { + seek(d->ID3v1Location); + writeBlock(ID3v1Tag()->render()); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + writeBlock(ID3v1Tag()->render()); + d->hasID3v1 = true; + } + } + else { + if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->hasID3v1 = false; + if(d->hasAPE) { + if(d->APELocation > d->ID3v1Location) + d->APELocation -= 128; + } + } + } + + // Update APE tag + + if(APETag()) { + if(d->hasAPE) + insert(APETag()->render(), d->APELocation, d->APESize); + else { + if(d->hasID3v1) { + insert(APETag()->render(), d->ID3v1Location, 0); + d->APESize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + d->APELocation = d->ID3v1Location; + d->ID3v1Location += d->APESize; + } + else { + seek(0, End); + d->APELocation = tell(); + writeBlock(APETag()->render()); + d->APESize = APETag()->footer()->completeTagSize(); + d->hasAPE = true; + } + } + } + else { + if(d->hasAPE) { + removeBlock(d->APELocation, d->APESize); + d->hasAPE = false; + if(d->hasID3v1) { + if(d->ID3v1Location > d->APELocation) { + d->ID3v1Location -= d->APESize; + } + } + } + } + + return true; +} + +ID3v1::Tag *WavPack::File::ID3v1Tag(bool create) +{ + return d->tag.access(ID3v1Index, create); +} + +APE::Tag *WavPack::File::APETag(bool create) +{ + return d->tag.access(APEIndex, create); +} + +void WavPack::File::strip(int tags) +{ + if(tags & ID3v1) { + d->tag.set(ID3v1Index, 0); + APETag(true); + } + + if(tags & APE) { + d->tag.set(APEIndex, 0); + + if(!ID3v1Tag()) + APETag(true); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void WavPack::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + d->hasID3v1 = true; + } + + // Look for an APE tag + + d->APELocation = findAPE(); + + if(d->APELocation >= 0) { + d->tag.set(APEIndex, new APE::Tag(this, d->APELocation)); + d->APESize = APETag()->footer()->completeTagSize(); + d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize; + d->hasAPE = true; + } + + if(!d->hasID3v1) + APETag(true); + + // Look for WavPack audio properties + + if(readProperties) { + seek(0); + d->properties = new Properties(this, length() - d->APESize); + } +} + +long WavPack::File::findAPE() +{ + if(!isValid()) + return -1; + + if(d->hasID3v1) + seek(-160, End); + else + seek(-32, End); + + long p = tell(); + + if(readBlock(8) == APE::Tag::fileIdentifier()) + return p; + + return -1; +} + +long WavPack::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} diff --git a/Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.h b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.h new file mode 100644 index 00000000..3415a329 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackfile.h @@ -0,0 +1,164 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WVFILE_H +#define TAGLIB_WVFILE_H + +#include "tfile.h" +#include "taglib_export.h" +#include "wavpackproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of WavPack metadata + + /*! + * This is implementation of WavPack metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace WavPack { + + //! An implementation of TagLib::File with WavPack specific methods + + /*! + * This implements and provides an interface for WavPack files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WavPack files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches APE tags. + APE = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Contructs an WavPack 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, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * a APE tag if one does not exist. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findID3v1(); + long findAPE(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.cpp b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.cpp new file mode 100644 index 00000000..52552a0d --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.cpp @@ -0,0 +1,194 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "wavpackproperties.h" +#include "wavpackfile.h" + +using namespace TagLib; + +class WavPack::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) : + data(d), + streamLength(length), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + version(0), + bitsPerSample(0), + file(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int version; + int bitsPerSample; + File *file; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +WavPack::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style) +{ + ByteVector data = file->readBlock(32); + d = new PropertiesPrivate(data, streamLength, style); + d->file = file; + read(); +} + +WavPack::Properties::~Properties() +{ + delete d; +} + +int WavPack::Properties::length() const +{ + return d->length; +} + +int WavPack::Properties::bitrate() const +{ + return d->bitrate; +} + +int WavPack::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int WavPack::Properties::channels() const +{ + return d->channels; +} + +int WavPack::Properties::version() const +{ + return d->version; +} + +int WavPack::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +static const unsigned int sample_rates[] = { 6000, 8000, 9600, 11025, 12000, + 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 }; + +#define BYTES_STORED 3 +#define MONO_FLAG 4 + +#define SHIFT_LSB 13 +#define SHIFT_MASK (0x1fL << SHIFT_LSB) + +#define SRATE_LSB 23 +#define SRATE_MASK (0xfL << SRATE_LSB) + +#define MIN_STREAM_VERS 0x402 +#define MAX_STREAM_VERS 0x410 + +#define FINAL_BLOCK 0x1000 + +void WavPack::Properties::read() +{ + if(!d->data.startsWith("wvpk")) + return; + + d->version = d->data.mid(8, 2).toShort(false); + if(d->version < MIN_STREAM_VERS || d->version > MAX_STREAM_VERS) + return; + + unsigned int flags = d->data.mid(24, 4).toUInt(false); + d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 - + ((flags & SHIFT_MASK) >> SHIFT_LSB); + d->sampleRate = sample_rates[(flags & SRATE_MASK) >> SRATE_LSB]; + d->channels = (flags & MONO_FLAG) ? 1 : 2; + + unsigned int samples = d->data.mid(12, 4).toUInt(false); + if(samples == ~0u) { + if(d->file && d->style != Fast) { + samples = seekFinalIndex(); + } + else { + samples = 0; + } + } + d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0; + + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} + +unsigned int WavPack::Properties::seekFinalIndex() +{ + ByteVector blockID("wvpk", 4); + + long offset = d->streamLength; + while(offset > 0) { + offset = d->file->rfind(blockID, offset); + if(offset == -1) + return 0; + d->file->seek(offset); + ByteVector data = d->file->readBlock(32); + if(data.size() != 32) + return 0; + int version = data.mid(8, 2).toShort(false); + if(version < MIN_STREAM_VERS || version > MAX_STREAM_VERS) + continue; + unsigned int flags = data.mid(24, 4).toUInt(false); + if(!(flags & FINAL_BLOCK)) + return 0; + unsigned int blockIndex = data.mid(16, 4).toUInt(false); + unsigned int blockSamples = data.mid(20, 4).toUInt(false); + return blockIndex + blockSamples; + } + + return 0; +} + diff --git a/Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.h b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.h new file mode 100644 index 00000000..74d18ea8 --- /dev/null +++ b/Plugins/PluginNowPlaying/taglib/wavpack/wavpackproperties.h @@ -0,0 +1,104 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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 * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WVPROPERTIES_H +#define TAGLIB_WVPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace WavPack { + + class File; + + static const uint HeaderSize = 32; + + //! An implementation of audio property reading for WavPack + + /*! + * This reads the data from an WavPack stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of WavPack::Properties with the data read from the + * ByteVector \a data. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Create an instance of WavPack::Properties. + */ + // BIC: merge with the above constructor + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this WavPack::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns number of bits per sample. + */ + int bitsPerSample() const; + + /*! + * Returns WavPack version. + */ + int version() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + unsigned int seekFinalIndex(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/Rainmeter.sln b/Rainmeter.sln index d3d8eabc..6c9e4870 100644 --- a/Rainmeter.sln +++ b/Rainmeter.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 +# Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Application", "Application\Application.vcxproj", "{D2A0903C-E760-4134-AE61-3D55BF8F760C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library", "Library\Library.vcxproj", "{BE9D2400-7F1C-49D6-8498-5CE495491AD6}" @@ -42,6 +42,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginFolderInfo", "Plugins EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginCoreTemp", "Plugins\PluginCoreTemp\PluginCoreTemp.vcxproj", "{F32FA418-8DF4-4E94-B92B-EBD502F5DC07}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginNowPlaying", "Plugins\PluginNowPlaying\PluginNowPlaying.vcxproj", "{C7FECFCD-E6C6-4F95-BB9A-E1762B043969}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -218,6 +220,10 @@ Global {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Win32.Build.0 = Release|Win32 {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|x64.ActiveCfg = Release|x64 {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|x64.Build.0 = Release|x64 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Win32.ActiveCfg = Debug|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|x64.ActiveCfg = Debug|x64 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Win32.ActiveCfg = Release|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|x64.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE