mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
Committing NowPlaying plugin. Because it requires VS2010 Pro to compile, it is not built by default.
This commit is contained in:
@@ -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
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License
|
modify it under the terms of the GNU General Public License
|
||||||
@@ -101,5 +101,5 @@ UINT GetPluginVersion()
|
|||||||
|
|
||||||
LPCTSTR GetPluginAuthor()
|
LPCTSTR GetPluginAuthor()
|
||||||
{
|
{
|
||||||
return L"poiru";
|
return L"Birunthan Mohanathas (www.poiru.net)";
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ BEGIN
|
|||||||
VALUE "FileDescription", "MediaKey Plugin for Rainmeter"
|
VALUE "FileDescription", "MediaKey Plugin for Rainmeter"
|
||||||
VALUE "FileVersion", "1.0.0.0"
|
VALUE "FileVersion", "1.0.0.0"
|
||||||
VALUE "InternalName", "PluginMediaKey"
|
VALUE "InternalName", "PluginMediaKey"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2010 - poiru"
|
VALUE "LegalCopyright", "Copyright (C) 2010 - Birunthan Mohanathas"
|
||||||
VALUE "OriginalFilename", "PluginMediaKey.dll"
|
VALUE "OriginalFilename", "PluginMediaKey.dll"
|
||||||
VALUE "ProductName", "Rainmeter"
|
VALUE "ProductName", "Rainmeter"
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
|||||||
478
Plugins/PluginNowPlaying/NowPlaying.cpp
Normal file
478
Plugins/PluginNowPlaying/NowPlaying.cpp
Normal file
@@ -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)";
|
||||||
|
}
|
||||||
51
Plugins/PluginNowPlaying/NowPlaying.h
Normal file
51
Plugins/PluginNowPlaying/NowPlaying.h
Normal file
@@ -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<UINT, MeasureData*> 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
|
||||||
390
Plugins/PluginNowPlaying/Player.cpp
Normal file
390
Plugins/PluginNowPlaying/Player.cpp
Normal file
@@ -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<TagLib::MPEG::File*>(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<TagLib::MP4::File*>(fr.file()))
|
||||||
|
{
|
||||||
|
if (file->tag())
|
||||||
|
{
|
||||||
|
found = GetArtMP4(file, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TagLib::FLAC::File* file = dynamic_cast<TagLib::FLAC::File*>(fr.file()))
|
||||||
|
{
|
||||||
|
found = GetArtFLAC(file, path);
|
||||||
|
|
||||||
|
if (!found && file->ID3v2Tag())
|
||||||
|
{
|
||||||
|
found = GetArtID3(file->ID3v2Tag(), path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TagLib::ASF::File* file = dynamic_cast<TagLib::ASF::File*>(fr.file()))
|
||||||
|
{
|
||||||
|
found = GetArtASF(file, path);
|
||||||
|
}
|
||||||
|
else if (TagLib::APE::File* file = dynamic_cast<TagLib::APE::File*>(fr.file()))
|
||||||
|
{
|
||||||
|
if (file->APETag())
|
||||||
|
{
|
||||||
|
found = GetArtAPE(file->APETag(), path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TagLib::MPC::File* file = dynamic_cast<TagLib::MPC::File*>(fr.file()))
|
||||||
|
{
|
||||||
|
if (file->APETag())
|
||||||
|
{
|
||||||
|
found = GetArtAPE(file->APETag(), path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TagLib::WavPack::File* file = dynamic_cast<TagLib::WavPack::File*>(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<TagLib::ID3v2::AttachedPictureFrame*>(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<TagLib::FLAC::Picture*>& 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;
|
||||||
|
}
|
||||||
135
Plugins/PluginNowPlaying/Player.h
Normal file
135
Plugins/PluginNowPlaying/Player.h
Normal file
@@ -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 "eU2euN0kBYRm/eZflj3hjt/Rm1IJR7TOgQBkvxTf"
|
||||||
|
|
||||||
|
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
|
||||||
464
Plugins/PluginNowPlaying/PlayerAIMP.cpp
Normal file
464
Plugins/PluginNowPlaying/PlayerAIMP.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
61
Plugins/PluginNowPlaying/PlayerAIMP.h
Normal file
61
Plugins/PluginNowPlaying/PlayerAIMP.h
Normal file
@@ -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 <windows.h>
|
||||||
|
#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
|
||||||
502
Plugins/PluginNowPlaying/PlayerFoobar.cpp
Normal file
502
Plugins/PluginNowPlaying/PlayerFoobar.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
84
Plugins/PluginNowPlaying/PlayerFoobar.h
Normal file
84
Plugins/PluginNowPlaying/PlayerFoobar.h
Normal file
@@ -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
|
||||||
163
Plugins/PluginNowPlaying/PlayerGeneric.cpp
Normal file
163
Plugins/PluginNowPlaying/PlayerGeneric.cpp
Normal file
@@ -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
|
||||||
|
}
|
||||||
46
Plugins/PluginNowPlaying/PlayerGeneric.h
Normal file
46
Plugins/PluginNowPlaying/PlayerGeneric.h
Normal file
@@ -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
|
||||||
587
Plugins/PluginNowPlaying/PlayerITunes.cpp
Normal file
587
Plugins/PluginNowPlaying/PlayerITunes.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
99
Plugins/PluginNowPlaying/PlayerITunes.h
Normal file
99
Plugins/PluginNowPlaying/PlayerITunes.h
Normal file
@@ -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 <atlbase.h>
|
||||||
|
#include <atlcom.h>
|
||||||
|
#include <atlhost.h>
|
||||||
|
#include <atlctl.h>
|
||||||
|
|
||||||
|
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
|
||||||
263
Plugins/PluginNowPlaying/PlayerSpotify.cpp
Normal file
263
Plugins/PluginNowPlaying/PlayerSpotify.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
57
Plugins/PluginNowPlaying/PlayerSpotify.h
Normal file
57
Plugins/PluginNowPlaying/PlayerSpotify.h
Normal file
@@ -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
|
||||||
723
Plugins/PluginNowPlaying/PlayerWMP.cpp
Normal file
723
Plugins/PluginNowPlaying/PlayerWMP.cpp
Normal file
@@ -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<IObjectWithSite> spHostObject;
|
||||||
|
CComPtr<IAxWinHostWindow> spHost;
|
||||||
|
CComObject<CRemoteHost>* 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<CRemoteHost>::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<IConnectionPointContainer> 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<IWMPMedia> 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<IWMPMedia> 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();
|
||||||
|
}
|
||||||
146
Plugins/PluginNowPlaying/PlayerWMP.h
Normal file
146
Plugins/PluginNowPlaying/PlayerWMP.h
Normal file
@@ -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 <wmp.h>
|
||||||
|
#include <atlbase.h>
|
||||||
|
#include <atlcom.h>
|
||||||
|
#include <atlhost.h>
|
||||||
|
#include <atlctl.h>
|
||||||
|
|
||||||
|
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<CComSingleThreadModel>,
|
||||||
|
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<IWMPPlayer4> m_IPlayer;
|
||||||
|
CComPtr<IWMPControls> m_IControls;
|
||||||
|
CComPtr<IWMPSettings> m_ISettings;
|
||||||
|
CComPtr<IConnectionPoint> m_IConnectionPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
481
Plugins/PluginNowPlaying/PlayerWinamp.cpp
Normal file
481
Plugins/PluginNowPlaying/PlayerWinamp.cpp
Normal file
@@ -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();
|
||||||
|
}
|
||||||
61
Plugins/PluginNowPlaying/PlayerWinamp.h
Normal file
61
Plugins/PluginNowPlaying/PlayerWinamp.h
Normal file
@@ -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
|
||||||
48
Plugins/PluginNowPlaying/PluginNowPlaying.rc
Normal file
48
Plugins/PluginNowPlaying/PluginNowPlaying.rc
Normal file
@@ -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
|
||||||
367
Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj
Normal file
367
Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{C7FECFCD-E6C6-4F95-BB9A-E1762B043969}</ProjectGuid>
|
||||||
|
<RootNamespace>PluginNowPlaying</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<Import Project="$(SolutionDir)\Rainmeter.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<PlatformToolset>$(COMPILER64)</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<PlatformToolset>$(COMPILER64)</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||||
|
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)TestBench\x32\$(Configuration)\Plugins\</OutDir>
|
||||||
|
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\x32\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
|
||||||
|
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)TestBench\x64\$(Configuration)\Plugins\</OutDir>
|
||||||
|
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\x64\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
|
||||||
|
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)TestBench\x32\$(Configuration)\Plugins\</OutDir>
|
||||||
|
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\x32\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||||
|
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)TestBench\x64\$(Configuration)\Plugins\</OutDir>
|
||||||
|
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\x64\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NowPlaying</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NowPlaying</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NowPlaying</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NowPlaying</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MkTypLibCompatible>true</MkTypLibCompatible>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<TargetEnvironment>Win32</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\x32/Debug/NowPlaying.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName>
|
||||||
|
</HeaderFileName>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PluginNowPlaying_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderOutputFile>.\x32/Debug/PluginNowPlaying.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<AssemblerListingLocation>.\x32/Debug/</AssemblerListingLocation>
|
||||||
|
<ObjectFileName>.\x32/Debug/</ObjectFileName>
|
||||||
|
<ProgramDataBaseFileName>.\x32/Debug/</ProgramDataBaseFileName>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
|
<DisableSpecificWarnings>4018;4090;4114;4351;4786;4800;4996</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0409</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<OutputFile>../../TestBench/x32/Debug/Plugins/NowPlaying.dll</OutputFile>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\x32/Debug/NowPlaying.pdb</ProgramDatabaseFile>
|
||||||
|
<ImportLibrary>.\x32/Debug/NowPlaying.lib</ImportLibrary>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MkTypLibCompatible>true</MkTypLibCompatible>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\x64/Debug/NowPlaying.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName>
|
||||||
|
</HeaderFileName>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NowPlaying_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderOutputFile>.\x64/Debug/NowPlaying.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<AssemblerListingLocation>.\x64/Debug/</AssemblerListingLocation>
|
||||||
|
<ObjectFileName>.\x64/Debug/</ObjectFileName>
|
||||||
|
<ProgramDataBaseFileName>.\x64/Debug/</ProgramDataBaseFileName>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<DisableSpecificWarnings>4018;4090;4114;4351;4786;4800;4996</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0409</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<OutputFile>../../TestBench/x64/Debug/Plugins/NowPlaying.dll</OutputFile>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\x64/Debug/NowPlaying.pdb</ProgramDatabaseFile>
|
||||||
|
<ImportLibrary>.\x64/Debug/NowPlaying.lib</ImportLibrary>
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MkTypLibCompatible>true</MkTypLibCompatible>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<TargetEnvironment>Win32</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\x32/Release/NowPlaying.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName>
|
||||||
|
</HeaderFileName>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TAGLIB_WITH_MP4;WITH_MP4;TAGLIB_WITH_ASF;WITH_ASF;PluginNowPlaying_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderOutputFile>.\x32/Release/PluginNowPlaying.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<AssemblerListingLocation>.\x32/Release/</AssemblerListingLocation>
|
||||||
|
<ObjectFileName>.\x32/Release/</ObjectFileName>
|
||||||
|
<ProgramDataBaseFileName>.\x32/Release/</ProgramDataBaseFileName>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<DisableSpecificWarnings>4018;4090;4099;4114;4244;4267;4309;4351;4390;4786;4800;4996</DisableSpecificWarnings>
|
||||||
|
<AdditionalIncludeDirectories>.\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)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0409</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>Rainmeter.lib;Wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>../../TestBench/x32/Release/Plugins/NowPlaying.dll</OutputFile>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<AdditionalLibraryDirectories>..\..\Library\x32\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\x32/Release/NowPlaying.pdb</ProgramDatabaseFile>
|
||||||
|
<ImportLibrary>.\x32/Release/NowPlaying.lib</ImportLibrary>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
<MergeSections>.rdata=.text</MergeSections>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MkTypLibCompatible>true</MkTypLibCompatible>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\x64/Release/NowPlaying.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName>
|
||||||
|
</HeaderFileName>
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/GL %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;HAVE_CONFIG_H;PluginNowPlaying_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\x64/Release/NowPlaying.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<AssemblerListingLocation>.\x64/Release/</AssemblerListingLocation>
|
||||||
|
<ObjectFileName>.\x64/Release/</ObjectFileName>
|
||||||
|
<ProgramDataBaseFileName>.\x64/Release/</ProgramDataBaseFileName>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<DisableSpecificWarnings>4018;4090;4099;4114;4244;4267;4309;4351;4390;4786;4800;4996</DisableSpecificWarnings>
|
||||||
|
<AdditionalIncludeDirectories>.\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)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0409</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<AdditionalDependencies>Rainmeter.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>../../TestBench/x64/Release/Plugins/NowPlaying.dll</OutputFile>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<AdditionalLibraryDirectories>..\..\Library\x64\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\x64/Release/NowPlaying.pdb</ProgramDatabaseFile>
|
||||||
|
<ImportLibrary>.\x64/Release/NowPlaying.lib</ImportLibrary>
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
<MergeSections>.rdata=.text</MergeSections>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="NowPlaying.cpp" />
|
||||||
|
<ClCompile Include="Player.cpp" />
|
||||||
|
<ClCompile Include="PlayerAIMP.cpp" />
|
||||||
|
<ClCompile Include="PlayerFoobar.cpp" />
|
||||||
|
<ClCompile Include="PlayerITunes.cpp" />
|
||||||
|
<ClCompile Include="PlayerSpotify.cpp" />
|
||||||
|
<ClCompile Include="PlayerWinamp.cpp" />
|
||||||
|
<ClCompile Include="PlayerWMP.cpp" />
|
||||||
|
<ClCompile Include="SDKs\iTunes\iTunesCOMInterface_i.c" />
|
||||||
|
<ClCompile Include="sha2\hmac_sha2.c" />
|
||||||
|
<ClCompile Include="sha2\sha2.c" />
|
||||||
|
<ClCompile Include="StdAfx.cpp" />
|
||||||
|
<ClCompile Include="taglib\ape\apefile.cpp" />
|
||||||
|
<ClCompile Include="taglib\ape\apefooter.cpp" />
|
||||||
|
<ClCompile Include="taglib\ape\apeitem.cpp" />
|
||||||
|
<ClCompile Include="taglib\ape\apeproperties.cpp" />
|
||||||
|
<ClCompile Include="taglib\ape\apetag.cpp" />
|
||||||
|
<ClCompile Include="taglib\asf\asfattribute.cpp" />
|
||||||
|
<ClCompile Include="taglib\asf\asffile.cpp" />
|
||||||
|
<ClCompile Include="taglib\asf\asfpicture.cpp" />
|
||||||
|
<ClCompile Include="taglib\asf\asfproperties.cpp" />
|
||||||
|
<ClCompile Include="taglib\asf\asftag.cpp" />
|
||||||
|
<ClCompile Include="taglib\audioproperties.cpp" />
|
||||||
|
<ClCompile Include="taglib\fileref.cpp" />
|
||||||
|
<ClCompile Include="taglib\flac\flacfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\flac\flacmetadatablock.cpp" />
|
||||||
|
<ClCompile Include="taglib\flac\flacpicture.cpp" />
|
||||||
|
<ClCompile Include="taglib\flac\flacproperties.cpp" />
|
||||||
|
<ClCompile Include="taglib\flac\flacunknownmetadatablock.cpp" />
|
||||||
|
<ClCompile Include="taglib\mp4\mp4atom.cpp" />
|
||||||
|
<ClCompile Include="taglib\mp4\mp4coverart.cpp" />
|
||||||
|
<ClCompile Include="taglib\mp4\mp4file.cpp" />
|
||||||
|
<ClCompile Include="taglib\mp4\mp4item.cpp" />
|
||||||
|
<ClCompile Include="taglib\mp4\mp4properties.cpp" />
|
||||||
|
<ClCompile Include="taglib\mp4\mp4tag.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpc\mpcfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpc\mpcproperties.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v1\id3v1genres.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v1\id3v1tag.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\attachedpictureframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\commentsframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\generalencapsulatedobjectframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\popularimeterframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\privateframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\relativevolumeframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\textidentificationframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\uniquefileidentifierframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\unknownframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\unsynchronizedlyricsframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\urllinkframe.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2extendedheader.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2footer.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2frame.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2framefactory.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2header.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2synchdata.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2tag.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\mpegfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\mpegheader.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\mpegproperties.cpp" />
|
||||||
|
<ClCompile Include="taglib\mpeg\xingheader.cpp" />
|
||||||
|
<ClCompile Include="taglib\ogg\flac\oggflacfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\ogg\oggfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\ogg\oggpage.cpp" />
|
||||||
|
<ClCompile Include="taglib\ogg\oggpageheader.cpp" />
|
||||||
|
<ClCompile Include="taglib\ogg\vorbis\vorbisfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\ogg\vorbis\vorbisproperties.cpp" />
|
||||||
|
<ClCompile Include="taglib\ogg\xiphcomment.cpp" />
|
||||||
|
<ClCompile Include="taglib\tag.cpp" />
|
||||||
|
<ClCompile Include="taglib\tagunion.cpp" />
|
||||||
|
<ClCompile Include="taglib\toolkit\tbytevector.cpp" />
|
||||||
|
<ClCompile Include="taglib\toolkit\tbytevectorlist.cpp" />
|
||||||
|
<ClCompile Include="taglib\toolkit\tdebug.cpp" />
|
||||||
|
<ClCompile Include="taglib\toolkit\tfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\toolkit\tstring.cpp" />
|
||||||
|
<ClCompile Include="taglib\toolkit\tstringlist.cpp" />
|
||||||
|
<ClCompile Include="taglib\toolkit\unicode.cpp" />
|
||||||
|
<ClCompile Include="taglib\wavpack\wavpackfile.cpp" />
|
||||||
|
<ClCompile Include="taglib\wavpack\wavpackproperties.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Library\Library.vcxproj">
|
||||||
|
<Project>{be9d2400-7f1c-49d6-8498-5ce495491ad6}</Project>
|
||||||
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="NowPlaying.h" />
|
||||||
|
<ClInclude Include="Player.h" />
|
||||||
|
<ClInclude Include="PlayerAIMP.h" />
|
||||||
|
<ClInclude Include="PlayerFoobar.h" />
|
||||||
|
<ClInclude Include="PlayerITunes.h" />
|
||||||
|
<ClInclude Include="PlayerSpotify.h" />
|
||||||
|
<ClInclude Include="PlayerWinamp.h" />
|
||||||
|
<ClInclude Include="PlayerWMP.h" />
|
||||||
|
<ClInclude Include="SDKs\AIMP\aimp2_sdk.h" />
|
||||||
|
<ClInclude Include="SDKs\iTunes\iTunesCOMInterface.h" />
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_cmd.h" />
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_dlg.h" />
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_hotkeys.h" />
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_ipc.h" />
|
||||||
|
<ClInclude Include="sha2\hmac_sha2.h" />
|
||||||
|
<ClInclude Include="sha2\sha2.h" />
|
||||||
|
<ClInclude Include="StdAfx.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="PluginNowPlaying.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
313
Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters
Normal file
313
Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="sha2">
|
||||||
|
<UniqueIdentifier>{1f50024f-4311-4946-b0a5-91dc7fb60453}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="taglib">
|
||||||
|
<UniqueIdentifier>{068012df-e981-4223-a90f-e0cc39dc46bb}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="SDKs">
|
||||||
|
<UniqueIdentifier>{1dbf5fab-83a1-45ab-8ab6-e5ae7b7b0516}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="SDKs\AIMP">
|
||||||
|
<UniqueIdentifier>{3ba19b2c-1c00-4093-a1b8-184aeaae6cc8}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="SDKs\Winamp">
|
||||||
|
<UniqueIdentifier>{18242178-1d8d-435b-8676-c5a0eb8c1f1b}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="SDKs\iTunes">
|
||||||
|
<UniqueIdentifier>{f632b821-b18a-445e-b7a2-2844b6633beb}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Players">
|
||||||
|
<UniqueIdentifier>{8be2f033-c29f-41d2-affd-c7721f0df88b}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="SDKs\iTunes\iTunesCOMInterface_i.c">
|
||||||
|
<Filter>SDKs\iTunes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PlayerWMP.cpp">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Player.cpp">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PlayerAIMP.cpp">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PlayerFoobar.cpp">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PlayerITunes.cpp">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PlayerSpotify.cpp">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PlayerWinamp.cpp">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="NowPlaying.cpp" />
|
||||||
|
<ClCompile Include="StdAfx.cpp" />
|
||||||
|
<ClCompile Include="sha2\sha2.c">
|
||||||
|
<Filter>sha2</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sha2\hmac_sha2.c">
|
||||||
|
<Filter>sha2</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ape\apefile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ape\apefooter.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ape\apeitem.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ape\apeproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ape\apetag.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\asf\asfattribute.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\asf\asfpicture.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\asf\asfproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\asf\asftag.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\attachedpictureframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\audioproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\commentsframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\flac\flacfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\flac\flacmetadatablock.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\flac\flacpicture.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\flac\flacproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\flac\flacunknownmetadatablock.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v1\id3v1genres.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v1\id3v1tag.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2extendedheader.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2footer.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2frame.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2framefactory.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2header.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2synchdata.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\id3v2tag.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mp4\mp4atom.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mp4\mp4coverart.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mp4\mp4file.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mp4\mp4item.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mp4\mp4properties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mp4\mp4tag.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\mpegfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\mpegheader.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\mpegproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ogg\oggfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ogg\flac\oggflacfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ogg\oggpage.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ogg\oggpageheader.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\privateframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\tag.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\tagunion.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\toolkit\tbytevector.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\toolkit\tbytevectorlist.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\toolkit\tdebug.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\textidentificationframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\toolkit\tfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\toolkit\tstring.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\toolkit\tstringlist.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\toolkit\unicode.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\uniquefileidentifierframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\unknownframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\urllinkframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ogg\vorbis\vorbisfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ogg\vorbis\vorbisproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\xingheader.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\ogg\xiphcomment.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\fileref.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\relativevolumeframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\popularimeterframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\generalencapsulatedobjectframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\asf\asffile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpeg\id3v2\frames\unsynchronizedlyricsframe.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\wavpack\wavpackproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\wavpack\wavpackfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpc\mpcproperties.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="taglib\mpc\mpcfile.cpp">
|
||||||
|
<Filter>taglib</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="SDKs\AIMP\aimp2_sdk.h">
|
||||||
|
<Filter>SDKs\AIMP</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SDKs\iTunes\iTunesCOMInterface.h">
|
||||||
|
<Filter>SDKs\iTunes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_dlg.h">
|
||||||
|
<Filter>SDKs\Winamp</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_hotkeys.h">
|
||||||
|
<Filter>SDKs\Winamp</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_ipc.h">
|
||||||
|
<Filter>SDKs\Winamp</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SDKs\Winamp\wa_cmd.h">
|
||||||
|
<Filter>SDKs\Winamp</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PlayerWinamp.h">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PlayerWMP.h">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Player.h">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PlayerAIMP.h">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PlayerFoobar.h">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PlayerITunes.h">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PlayerSpotify.h">
|
||||||
|
<Filter>Players</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="NowPlaying.h" />
|
||||||
|
<ClInclude Include="StdAfx.h" />
|
||||||
|
<ClInclude Include="sha2\hmac_sha2.h">
|
||||||
|
<Filter>sha2</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sha2\sha2.h">
|
||||||
|
<Filter>sha2</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="PluginNowPlaying.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
726
Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h
Normal file
726
Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h
Normal file
@@ -0,0 +1,726 @@
|
|||||||
|
// Translated by Vitaliy Diatlov
|
||||||
|
// AIMP2: SDK (02.07.2009), v2.60
|
||||||
|
|
||||||
|
#ifndef AIMP2_SDK_H
|
||||||
|
#define AIMP2_SDK_H
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <unknwn.h>
|
||||||
|
|
||||||
|
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
|
||||||
97
Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h
Normal file
97
Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h
Normal file
@@ -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 :)
|
||||||
353
Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h
Normal file
353
Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h
Normal file
@@ -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);i<len-1;i+=2)
|
||||||
|
{
|
||||||
|
if(vert) {
|
||||||
|
MoveToEx(hdc,left,top+i,NULL);
|
||||||
|
LineTo(hdc,left,top+i+1);
|
||||||
|
} else {
|
||||||
|
MoveToEx(hdc,left+i,top,NULL);
|
||||||
|
LineTo(hdc,left+i+1,top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (uMsg == WM_DRAWITEM)
|
||||||
|
{
|
||||||
|
DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
|
||||||
|
if (di->CtlType == 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_
|
||||||
39
Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h
Normal file
39
Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h
Normal file
@@ -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
|
||||||
1601
Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h
Normal file
1601
Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h
Normal file
File diff suppressed because it is too large
Load Diff
14384
Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h
Normal file
14384
Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h
Normal file
File diff suppressed because it is too large
Load Diff
175
Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c
Normal file
175
Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c
Normal file
@@ -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 <rpc.h>
|
||||||
|
#include <rpcndr.h>
|
||||||
|
|
||||||
|
#ifdef _MIDL_USE_GUIDDEF_
|
||||||
|
|
||||||
|
#ifndef INITGUID
|
||||||
|
#define INITGUID
|
||||||
|
#include <guiddef.h>
|
||||||
|
#undef INITGUID
|
||||||
|
#else
|
||||||
|
#include <guiddef.h>
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
19
Plugins/PluginNowPlaying/StdAfx.cpp
Normal file
19
Plugins/PluginNowPlaying/StdAfx.cpp
Normal file
@@ -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"
|
||||||
38
Plugins/PluginNowPlaying/StdAfx.h
Normal file
38
Plugins/PluginNowPlaying/StdAfx.h
Normal file
@@ -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 <windows.h>
|
||||||
|
|
||||||
|
// STL
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// Runtime
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
// Rainmeter's exported functions
|
||||||
|
#include "../../Library/Export.h"
|
||||||
|
|
||||||
|
// TagLib
|
||||||
|
#include "fileref.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
7
Plugins/PluginNowPlaying/readme.txt
Normal file
7
Plugins/PluginNowPlaying/readme.txt
Normal file
@@ -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)
|
||||||
544
Plugins/PluginNowPlaying/sha2/hmac_sha2.c
Normal file
544
Plugins/PluginNowPlaying/sha2/hmac_sha2.c
Normal file
@@ -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 <olivier.gay@a3.epfl.ch>
|
||||||
|
* 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 <string.h>
|
||||||
|
|
||||||
|
#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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
140
Plugins/PluginNowPlaying/sha2/hmac_sha2.h
Normal file
140
Plugins/PluginNowPlaying/sha2/hmac_sha2.h
Normal file
@@ -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 <olivier.gay@a3.epfl.ch>
|
||||||
|
* 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 */
|
||||||
|
|
||||||
950
Plugins/PluginNowPlaying/sha2/sha2.c
Normal file
950
Plugins/PluginNowPlaying/sha2/sha2.c
Normal file
@@ -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 <olivier.gay@a3.epfl.ch>
|
||||||
|
* 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 <string.h>
|
||||||
|
|
||||||
|
#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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
108
Plugins/PluginNowPlaying/sha2/sha2.h
Normal file
108
Plugins/PluginNowPlaying/sha2/sha2.h
Normal file
@@ -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 <olivier.gay@a3.epfl.ch>
|
||||||
|
* 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 */
|
||||||
|
|
||||||
502
Plugins/PluginNowPlaying/taglib/COPYING.LGPL
Normal file
502
Plugins/PluginNowPlaying/taglib/COPYING.LGPL
Normal file
@@ -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.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
470
Plugins/PluginNowPlaying/taglib/COPYING.MPL
Normal file
470
Plugins/PluginNowPlaying/taglib/COPYING.MPL
Normal file
@@ -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.]
|
||||||
|
|
||||||
170
Plugins/PluginNowPlaying/taglib/ape/ape-tag-format.txt
Normal file
170
Plugins/PluginNowPlaying/taglib/ape/ape-tag-format.txt
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
================================================================================
|
||||||
|
= APE Tag Specification, Version 2.000
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
Original Content (C) 2004, Frank Klemm <frank.klemm@elster.offl.uni-jena.de>
|
||||||
|
Formatting / Editing (C) 2004, Scott Wheeler <wheeler@kde.org>
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= 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
|
||||||
270
Plugins/PluginNowPlaying/taglib/ape/apefile.cpp
Normal file
270
Plugins/PluginNowPlaying/taglib/ape/apefile.cpp
Normal file
@@ -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 <tbytevector.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tagunion.h>
|
||||||
|
#include <id3v1tag.h>
|
||||||
|
|
||||||
|
#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<ID3v1::Tag>(ID3v1Index, create);
|
||||||
|
}
|
||||||
|
|
||||||
|
APE::Tag *APE::File::APETag(bool create)
|
||||||
|
{
|
||||||
|
return d->tag.access<APE::Tag>(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;
|
||||||
|
}
|
||||||
171
Plugins/PluginNowPlaying/taglib/ape/apefile.h
Normal file
171
Plugins/PluginNowPlaying/taglib/ape/apefile.h
Normal file
@@ -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 <b>is still</b> 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 <b>is still</b> 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
|
||||||
236
Plugins/PluginNowPlaying/taglib/ape/apefooter.cpp
Normal file
236
Plugins/PluginNowPlaying/taglib/ape/apefooter.cpp
Normal file
@@ -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 <ostream>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
173
Plugins/PluginNowPlaying/taglib/ape/apefooter.h
Normal file
173
Plugins/PluginNowPlaying/taglib/ape/apefooter.h
Normal file
@@ -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
|
||||||
230
Plugins/PluginNowPlaying/taglib/ape/apeitem.cpp
Normal file
230
Plugins/PluginNowPlaying/taglib/ape/apeitem.cpp
Normal file
@@ -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 <tbytevectorlist.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
204
Plugins/PluginNowPlaying/taglib/ape/apeitem.h
Normal file
204
Plugins/PluginNowPlaying/taglib/ape/apeitem.h
Normal file
@@ -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
|
||||||
|
|
||||||
|
|
||||||
224
Plugins/PluginNowPlaying/taglib/ape/apeproperties.cpp
Normal file
224
Plugins/PluginNowPlaying/taglib/ape/apeproperties.cpp
Normal file
@@ -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 <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <bitset>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
98
Plugins/PluginNowPlaying/taglib/ape/apeproperties.h
Normal file
98
Plugins/PluginNowPlaying/taglib/ape/apeproperties.h
Normal file
@@ -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
|
||||||
271
Plugins/PluginNowPlaying/taglib/ape/apetag.cpp
Normal file
271
Plugins/PluginNowPlaying/taglib/ape/apetag.cpp
Normal file
@@ -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 <tfile.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tmap.h>
|
||||||
|
|
||||||
|
#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<const String, Item>::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<const String, Item>::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();
|
||||||
|
}
|
||||||
|
}
|
||||||
170
Plugins/PluginNowPlaying/taglib/ape/apetag.h
Normal file
170
Plugins/PluginNowPlaying/taglib/ape/apetag.h
Normal file
@@ -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<const String, Item> 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
|
||||||
356
Plugins/PluginNowPlaying/taglib/asf/asfattribute.cpp
Normal file
356
Plugins/PluginNowPlaying/taglib/asf/asfattribute.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_ASF
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#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
|
||||||
203
Plugins/PluginNowPlaying/taglib/asf/asfattribute.h
Normal file
203
Plugins/PluginNowPlaying/taglib/asf/asfattribute.h
Normal file
@@ -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
|
||||||
543
Plugins/PluginNowPlaying/taglib/asf/asffile.cpp
Normal file
543
Plugins/PluginNowPlaying/taglib/asf/asffile.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_ASF
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tbytevectorlist.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#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<ASF::File::BaseObject *> 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<ASF::File::BaseObject *> 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
|
||||||
120
Plugins/PluginNowPlaying/taglib/asf/asffile.h
Normal file
120
Plugins/PluginNowPlaying/taglib/asf/asffile.h
Normal file
@@ -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 <b>is still</b> 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
|
||||||
185
Plugins/PluginNowPlaying/taglib/asf/asfpicture.cpp
Normal file
185
Plugins/PluginNowPlaying/taglib/asf/asfpicture.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_ASF
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#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
|
||||||
217
Plugins/PluginNowPlaying/taglib/asf/asfpicture.h
Normal file
217
Plugins/PluginNowPlaying/taglib/asf/asfpicture.h
Normal file
@@ -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
|
||||||
107
Plugins/PluginNowPlaying/taglib/asf/asfproperties.cpp
Normal file
107
Plugins/PluginNowPlaying/taglib/asf/asfproperties.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_ASF
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#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
|
||||||
74
Plugins/PluginNowPlaying/taglib/asf/asfproperties.h
Normal file
74
Plugins/PluginNowPlaying/taglib/asf/asfproperties.h
Normal file
@@ -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
|
||||||
201
Plugins/PluginNowPlaying/taglib/asf/asftag.cpp
Normal file
201
Plugins/PluginNowPlaying/taglib/asf/asftag.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#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
|
||||||
186
Plugins/PluginNowPlaying/taglib/asf/asftag.h
Normal file
186
Plugins/PluginNowPlaying/taglib/asf/asftag.h
Normal file
@@ -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<Attribute> AttributeList;
|
||||||
|
typedef Map<String, AttributeList> 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
|
||||||
51
Plugins/PluginNowPlaying/taglib/audioproperties.cpp
Normal file
51
Plugins/PluginNowPlaying/taglib/audioproperties.cpp
Normal file
@@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
110
Plugins/PluginNowPlaying/taglib/audioproperties.h
Normal file
110
Plugins/PluginNowPlaying/taglib/audioproperties.h
Normal file
@@ -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
|
||||||
2
Plugins/PluginNowPlaying/taglib/config.h
Normal file
2
Plugins/PluginNowPlaying/taglib/config.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define WITH_ASF 1
|
||||||
|
#define WITH_MP4 1
|
||||||
266
Plugins/PluginNowPlaying/taglib/fileref.cpp
Normal file
266
Plugins/PluginNowPlaying/taglib/fileref.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <tfile.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
|
||||||
|
#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<const FileTypeResolver *> fileTypeResolvers;
|
||||||
|
};
|
||||||
|
|
||||||
|
List<const FileRef::FileTypeResolver *> 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<const FileTypeResolver *>::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;
|
||||||
|
}
|
||||||
263
Plugins/PluginNowPlaying/taglib/fileref.h
Normal file
263
Plugins/PluginNowPlaying/taglib/fileref.h
Normal file
@@ -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 <i>handle</i> 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
|
||||||
499
Plugins/PluginNowPlaying/taglib/flac/flacfile.cpp
Normal file
499
Plugins/PluginNowPlaying/taglib/flac/flacfile.cpp
Normal file
@@ -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 <tbytevector.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tlist.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tagunion.h>
|
||||||
|
|
||||||
|
#include <id3v2header.h>
|
||||||
|
#include <id3v2tag.h>
|
||||||
|
#include <id3v1tag.h>
|
||||||
|
#include <xiphcomment.h>
|
||||||
|
|
||||||
|
#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<MetadataBlock *> 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<MetadataBlock *> 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<ID3v2::Tag *>(d->tag[ID3v2Index]);
|
||||||
|
|
||||||
|
d->tag.set(ID3v2Index, new ID3v2::Tag);
|
||||||
|
return static_cast<ID3v2::Tag *>(d->tag[ID3v2Index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)
|
||||||
|
{
|
||||||
|
return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ogg::XiphComment *FLAC::File::xiphComment(bool create)
|
||||||
|
{
|
||||||
|
return d->tag.access<Ogg::XiphComment>(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::Picture *> FLAC::File::pictureList()
|
||||||
|
{
|
||||||
|
List<Picture *> pictures;
|
||||||
|
for(uint i = 0; i < d->blocks.size(); i++) {
|
||||||
|
Picture *picture = dynamic_cast<Picture *>(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<MetadataBlock *> newBlocks;
|
||||||
|
for(uint i = 0; i < d->blocks.size(); i++) {
|
||||||
|
Picture *picture = dynamic_cast<Picture *>(d->blocks[i]);
|
||||||
|
if(picture) {
|
||||||
|
delete picture;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newBlocks.append(d->blocks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d->blocks = newBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
222
Plugins/PluginNowPlaying/taglib/flac/flacfile.h
Normal file
222
Plugins/PluginNowPlaying/taglib/flac/flacfile.h
Normal file
@@ -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 <b>is still</b> 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 <b>is still</b> 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 <b>is still</b> 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<Picture *> 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
|
||||||
51
Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.cpp
Normal file
51
Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include "flacmetadatablock.h"
|
||||||
|
|
||||||
|
using namespace TagLib;
|
||||||
|
|
||||||
|
class FLAC::MetadataBlock::MetadataBlockPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MetadataBlockPrivate() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
FLAC::MetadataBlock::MetadataBlock()
|
||||||
|
{
|
||||||
|
d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLAC::MetadataBlock::~MetadataBlock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
75
Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.h
Normal file
75
Plugins/PluginNowPlaying/taglib/flac/flacmetadatablock.h
Normal file
@@ -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
|
||||||
221
Plugins/PluginNowPlaying/taglib/flac/flacpicture.cpp
Normal file
221
Plugins/PluginNowPlaying/taglib/flac/flacpicture.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
208
Plugins/PluginNowPlaying/taglib/flac/flacpicture.h
Normal file
208
Plugins/PluginNowPlaying/taglib/flac/flacpicture.h
Normal file
@@ -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<Picture> PictureList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
158
Plugins/PluginNowPlaying/taglib/flac/flacproperties.cpp
Normal file
158
Plugins/PluginNowPlaying/taglib/flac/flacproperties.cpp
Normal file
@@ -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 <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
98
Plugins/PluginNowPlaying/taglib/flac/flacproperties.h
Normal file
98
Plugins/PluginNowPlaying/taglib/flac/flacproperties.h
Normal file
@@ -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
|
||||||
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
197
Plugins/PluginNowPlaying/taglib/mp4/mp4atom.cpp
Normal file
197
Plugins/PluginNowPlaying/taglib/mp4/mp4atom.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_MP4
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#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
|
||||||
77
Plugins/PluginNowPlaying/taglib/mp4/mp4atom.h
Normal file
77
Plugins/PluginNowPlaying/taglib/mp4/mp4atom.h
Normal file
@@ -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<Atom *> 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
|
||||||
89
Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.cpp
Normal file
89
Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_MP4
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#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
|
||||||
71
Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.h
Normal file
71
Plugins/PluginNowPlaying/taglib/mp4/mp4coverart.h
Normal file
@@ -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<CoverArt> CoverArtList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
145
Plugins/PluginNowPlaying/taglib/mp4/mp4file.cpp
Normal file
145
Plugins/PluginNowPlaying/taglib/mp4/mp4file.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_MP4
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#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
|
||||||
103
Plugins/PluginNowPlaying/taglib/mp4/mp4file.h
Normal file
103
Plugins/PluginNowPlaying/taglib/mp4/mp4file.h
Normal file
@@ -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 <b>is still</b> 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
|
||||||
149
Plugins/PluginNowPlaying/taglib/mp4/mp4item.cpp
Normal file
149
Plugins/PluginNowPlaying/taglib/mp4/mp4item.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_MP4
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#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
|
||||||
72
Plugins/PluginNowPlaying/taglib/mp4/mp4item.h
Normal file
72
Plugins/PluginNowPlaying/taglib/mp4/mp4item.h
Normal file
@@ -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
|
||||||
169
Plugins/PluginNowPlaying/taglib/mp4/mp4properties.cpp
Normal file
169
Plugins/PluginNowPlaying/taglib/mp4/mp4properties.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_MP4
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#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
|
||||||
61
Plugins/PluginNowPlaying/taglib/mp4/mp4properties.h
Normal file
61
Plugins/PluginNowPlaying/taglib/mp4/mp4properties.h
Normal file
@@ -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
|
||||||
636
Plugins/PluginNowPlaying/taglib/mp4/mp4tag.cpp
Normal file
636
Plugins/PluginNowPlaying/taglib/mp4/mp4tag.cpp
Normal file
@@ -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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_MP4
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#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
|
||||||
104
Plugins/PluginNowPlaying/taglib/mp4/mp4tag.h
Normal file
104
Plugins/PluginNowPlaying/taglib/mp4/mp4tag.h
Normal file
@@ -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<String, Item> 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
|
||||||
325
Plugins/PluginNowPlaying/taglib/mpc/mpcfile.cpp
Normal file
325
Plugins/PluginNowPlaying/taglib/mpc/mpcfile.cpp
Normal file
@@ -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 <tbytevector.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tagunion.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
|
||||||
|
#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<ID3v1::Tag>(ID3v1Index, create);
|
||||||
|
}
|
||||||
|
|
||||||
|
APE::Tag *MPC::File::APETag(bool create)
|
||||||
|
{
|
||||||
|
return d->tag.access<APE::Tag>(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;
|
||||||
|
}
|
||||||
175
Plugins/PluginNowPlaying/taglib/mpc/mpcfile.h
Normal file
175
Plugins/PluginNowPlaying/taglib/mpc/mpcfile.h
Normal file
@@ -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 <b>is still</b> 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 <b>is still</b> 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
|
||||||
140
Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.cpp
Normal file
140
Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.cpp
Normal file
@@ -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 <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
85
Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.h
Normal file
85
Plugins/PluginNowPlaying/taglib/mpc/mpcproperties.h
Normal file
@@ -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
|
||||||
219
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.cpp
Normal file
219
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.cpp
Normal file
@@ -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;
|
||||||
|
}
|
||||||
66
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.h
Normal file
66
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1genres.h
Normal file
@@ -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<String, int> 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
|
||||||
248
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.cpp
Normal file
248
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.cpp
Normal file
@@ -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 <tdebug.h>
|
||||||
|
#include <tfile.h>
|
||||||
|
|
||||||
|
#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]);
|
||||||
|
}
|
||||||
181
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.h
Normal file
181
Plugins/PluginNowPlaying/taglib/mpeg/id3v1/id3v1tag.h
Normal file
@@ -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 <b>not</b> 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 <b>not</b> 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
|
||||||
@@ -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 <tstringlist.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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 <tbytevectorlist.h>
|
||||||
|
#include <id3v2tag.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstringlist.h>
|
||||||
|
|
||||||
|
#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<CommentsFrame *>(*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));
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
||||||
|
*
|
||||||
|
* \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
|
||||||
|
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> 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
|
||||||
@@ -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 <tdebug.h>
|
||||||
|
|
||||||
|
#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));
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user