472 lines
15 KiB
C++
472 lines
15 KiB
C++
|
#include "GracenoteApi.h"
|
|||
|
#include "api.h"
|
|||
|
#include "../winamp/api_decodefile.h"
|
|||
|
#include <bfc/error.h>
|
|||
|
#include <limits.h>
|
|||
|
#include <shlwapi.h>
|
|||
|
#include <strsafe.h>
|
|||
|
|
|||
|
GracenoteApi::GracenoteApi()
|
|||
|
{
|
|||
|
cddbInitialized = false;
|
|||
|
playlistInitialized = false;
|
|||
|
pCDDBControl=0;
|
|||
|
}
|
|||
|
|
|||
|
GracenoteApi::~GracenoteApi()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
void GracenoteApi::Close()
|
|||
|
{
|
|||
|
if (pCDDBControl)
|
|||
|
{
|
|||
|
pCDDBControl->Shutdown();
|
|||
|
pCDDBControl->Release();
|
|||
|
pCDDBControl=0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void SetProxy(const wchar_t *proxy, ICddbOptions *options)
|
|||
|
{
|
|||
|
wchar_t user[1024]=L"";
|
|||
|
wchar_t pass[1024]=L"";
|
|||
|
wchar_t server[1024]=L"";
|
|||
|
int port=80;
|
|||
|
if (!_wcsnicmp(proxy,L"https:",6))
|
|||
|
port = 443;
|
|||
|
|
|||
|
const wchar_t *skip = wcsstr(proxy, L"://");
|
|||
|
if (skip)
|
|||
|
proxy = skip+3;
|
|||
|
|
|||
|
skip = wcsstr(proxy, L"@");
|
|||
|
if (skip)
|
|||
|
{
|
|||
|
const wchar_t *delimiter = wcsstr(proxy, L":");
|
|||
|
if (delimiter < skip) // make sure there's really a password (and we didn't end up finding the port number)
|
|||
|
{
|
|||
|
StringCchCopyNW(user, 1024, proxy, delimiter-proxy);
|
|||
|
StringCchCopyNW(pass, 1024, delimiter+1, skip-(delimiter+1));
|
|||
|
proxy=skip+1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
StringCchCopyNW(user, 1024, proxy, skip-proxy);
|
|||
|
proxy=skip+1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
skip = wcsstr(proxy, L":"); // look for port
|
|||
|
if (skip)
|
|||
|
{
|
|||
|
StringCchCopyNW(server, 1024, proxy, skip-proxy);
|
|||
|
port = _wtoi(skip+1);
|
|||
|
}
|
|||
|
else
|
|||
|
StringCchCopyW(server, 1024, proxy);
|
|||
|
|
|||
|
if (server[0])
|
|||
|
options->put_ProxyServer(server);
|
|||
|
if (port)
|
|||
|
options->put_ProxyServerPort(port);
|
|||
|
if (user[0])
|
|||
|
options->put_ProxyUserName(user);
|
|||
|
if (pass[0])
|
|||
|
options->put_ProxyPassword(pass);
|
|||
|
}
|
|||
|
|
|||
|
// {C0A565DC-0CFE-405a-A27C-468B0C8A3A5C}
|
|||
|
static const GUID internetConfigGroupGUID =
|
|||
|
{ 0xc0a565dc, 0xcfe, 0x405a, { 0xa2, 0x7c, 0x46, 0x8b, 0xc, 0x8a, 0x3a, 0x5c } };
|
|||
|
|
|||
|
ICDDBControl2 *GracenoteApi::GetCDDB()
|
|||
|
{
|
|||
|
Nullsoft::Utility::AutoLock lock(cddbGuard);
|
|||
|
if (!cddbInitialized)
|
|||
|
{
|
|||
|
CoCreateInstance(__uuidof(CDDBNSWinampControl), 0, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pCDDBControl);
|
|||
|
if (pCDDBControl == NULL)
|
|||
|
return 0;
|
|||
|
|
|||
|
#if 1 // TODO: benski> put back in once we can match winamp lang pack to a gracenote language ID
|
|||
|
// translate if necessary
|
|||
|
if (WASABI_API_LNG)
|
|||
|
{
|
|||
|
const wchar_t *langFolder = WASABI_API_LNG->GetLanguageFolder();
|
|||
|
if (langFolder)
|
|||
|
{
|
|||
|
WIN32_FIND_DATAW find;
|
|||
|
wchar_t mask[MAX_PATH] = {0}, maskLoc[16] = {0};
|
|||
|
|
|||
|
// attempt to get the language code to help better guess the CDDB dll needed
|
|||
|
if(WASABI_API_LNG->GetLanguageIdentifier(LANG_IDENT_STR))
|
|||
|
StringCchPrintfW(maskLoc, 16, L"CddbLang%s.dll", WASABI_API_LNG->GetLanguageIdentifier(LANG_LANG_CODE));
|
|||
|
|
|||
|
PathCombineW(mask, langFolder, maskLoc);
|
|||
|
HANDLE hFind = FindFirstFileW(mask, &find);
|
|||
|
|
|||
|
// if the the guess provides nothing then scan for any valid dll (not ideal)
|
|||
|
if (hFind == INVALID_HANDLE_VALUE)
|
|||
|
{
|
|||
|
PathCombineW(mask, langFolder, L"CddbLang*.dll");
|
|||
|
hFind = FindFirstFileW(mask, &find);
|
|||
|
}
|
|||
|
|
|||
|
if (hFind != INVALID_HANDLE_VALUE)
|
|||
|
{
|
|||
|
ICddbUIPtr ui;
|
|||
|
ui.CreateInstance(__uuidof(CddbNSWinampUI));
|
|||
|
if (ui)
|
|||
|
{
|
|||
|
long val = 0;
|
|||
|
wchar_t cddb_lang_fn[MAX_PATH] = {0};
|
|||
|
PathCombineW(cddb_lang_fn, langFolder, find.cFileName);
|
|||
|
// TODO: benski> gracenote wants a "language ID" but we don't have a good way of knowing it :(
|
|||
|
ui->SetUILanguage(0, cddb_lang_fn, &val);
|
|||
|
// TODO: benski> also need to set ICddbOptions language ID
|
|||
|
}
|
|||
|
}
|
|||
|
FindClose(hFind);
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
// winamp browser id
|
|||
|
//HRESULT hr = pCDDBControl->SetClientInfo(L"7944448", L"F8DE207FBA826F136FF2C7EFE0AAB181", L"1", L"regstring");
|
|||
|
//wa5's id
|
|||
|
|
|||
|
const wchar_t *appVersion = WASABI_API_APP->main_getVersionNumString();
|
|||
|
|
|||
|
/* development client ID */
|
|||
|
//HRESULT hr = pCDDBControl->SetClientInfo(L"3714048", L"B49286AE14F73CCD73C23B371A56DB00", const_cast<BSTR>(appVersion), L"regstring");
|
|||
|
|
|||
|
/* Beta Client ID */
|
|||
|
//HRESULT hr = pCDDBControl->SetClientInfo(L"8337664", L"A222F2FA8B3E047291DFDBF465FD3C95", const_cast<BSTR>(appVersion), L"regstring");
|
|||
|
|
|||
|
/* Production Client ID */
|
|||
|
BSTR appVersionBSTR = SysAllocString(appVersion);
|
|||
|
HRESULT hr = pCDDBControl->SetClientInfo(L"4896768", L"C1519CAE91489E405BCA93531837F2BE", appVersionBSTR, L"regstring");
|
|||
|
SysFreeString(appVersionBSTR);
|
|||
|
|
|||
|
if (FAILED(hr))
|
|||
|
return 0;
|
|||
|
|
|||
|
long flags = CACHE_UPDATE_FUZZY | CACHE_DONT_WRITE_ANY | CACHE_NO_LOOKUP_MEDIA; //CACHE_SUBMIT_ALL | CACHE_SUBMIT_OFFLINE | CACHE_SUBMIT_NEW | CACHE_NO_LOOKUP_MEDIA;
|
|||
|
|
|||
|
// set cache path for cddb control
|
|||
|
ICddbOptionsPtr pOptions;
|
|||
|
hr = pCDDBControl->GetOptions(&pOptions);
|
|||
|
if (SUCCEEDED(hr))
|
|||
|
{
|
|||
|
wchar_t dataPath[MAX_PATH] = {0};
|
|||
|
PathCombineW(dataPath, WASABI_API_APP->path_getUserSettingsPath(), L"Plugins");
|
|||
|
CreateDirectoryW(dataPath, 0);
|
|||
|
PathAppendW(dataPath, L"Gracenote");
|
|||
|
CreateDirectoryW(dataPath, 0);
|
|||
|
|
|||
|
hr = pOptions->put_LocalCachePath(dataPath);
|
|||
|
|
|||
|
// initial cache flags
|
|||
|
|
|||
|
//BOOL bOnline = SendMessage(line.hMainWindow, WM_USER, 0, 242);
|
|||
|
//if (!bOnline)
|
|||
|
//flags |= CACHE_DONT_CONNECT;
|
|||
|
|
|||
|
// other needed settings
|
|||
|
hr = pOptions->put_ProgressEvents(FALSE);
|
|||
|
//hr = pOptions->put_LocalCacheFlags(CACHE_DONT_CREATE | CACHE_UPDATE_FUZZY | CACHE_SUBMIT_ALL);
|
|||
|
hr = pOptions->put_LocalCacheFlags(flags);
|
|||
|
hr = pOptions->put_LocalCacheSize(128 * 1024); // 128 megabyte limit on local cache size
|
|||
|
hr = pOptions->put_LocalCacheTimeout(5 * 365); // 5 years (e.g. when Gracenote contract runs out)
|
|||
|
hr = pOptions->put_TestSubmitMode(FALSE);
|
|||
|
//hr = pOptions->put_TestSubmitMode(TRUE); //CT> for BETA cycle...
|
|||
|
|
|||
|
// this is supposed to turn off the spinning logo in the upper-left-hand corner
|
|||
|
hr = pOptions->put_ResourceModule(-1);
|
|||
|
|
|||
|
// get n set proxy settings
|
|||
|
const wchar_t *proxy = AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", L"");
|
|||
|
if (proxy && proxy[0])
|
|||
|
SetProxy(proxy, pOptions);
|
|||
|
|
|||
|
// save settings
|
|||
|
hr = pCDDBControl->SetOptions(pOptions);
|
|||
|
}
|
|||
|
|
|||
|
hr = pCDDBControl->Initialize(0/*(long)line.hMainWindow*/, (CDDBCacheFlags)flags);
|
|||
|
|
|||
|
// checks for user registration
|
|||
|
long pVal=0;
|
|||
|
|
|||
|
// this must be called when control is first initialized
|
|||
|
// this will load existing registration into control
|
|||
|
hr = pCDDBControl->IsRegistered(FALSE, &pVal);
|
|||
|
|
|||
|
// if not reg'd, bring up reg UI (param1 = TRUE)
|
|||
|
if (!pVal)
|
|||
|
{
|
|||
|
// do headless registration
|
|||
|
ICddbUserInfoPtr pUser;
|
|||
|
|
|||
|
hr = pCDDBControl->GetUserInfo(&pUser);
|
|||
|
if (pUser != NULL)
|
|||
|
{
|
|||
|
do
|
|||
|
{
|
|||
|
wchar_t strdata[129] = {0};
|
|||
|
size_t size = sizeof(strdata)/sizeof(*strdata);
|
|||
|
wchar_t *str = strdata;
|
|||
|
|
|||
|
GUID uid = GUID_NULL;
|
|||
|
int x;
|
|||
|
unsigned char *p;
|
|||
|
CoCreateGuid(&uid);
|
|||
|
p = (unsigned char *) & uid;
|
|||
|
//lstrcpynW(str, L"WA2_", 129);
|
|||
|
StringCchCopyExW(str, size, L"WA5_", &str, &size, 0);
|
|||
|
for (x = 0; x < sizeof(uid); x ++)
|
|||
|
{
|
|||
|
StringCchPrintfExW(str, size, &str, &size, 0, L"%02X", p[x]);
|
|||
|
//wsprintfW(str + wcslen(str), L"%02X", p[x]);
|
|||
|
}
|
|||
|
|
|||
|
// user name will have to be unique per install
|
|||
|
hr = pUser->put_UserHandle(strdata);
|
|||
|
hr = pUser->put_Password(strdata);
|
|||
|
|
|||
|
hr = pCDDBControl->SetUserInfo(pUser);
|
|||
|
}
|
|||
|
while (hr == CDDBSVCHandleUsed);
|
|||
|
}
|
|||
|
|
|||
|
// this is just to check again that the user is now registered
|
|||
|
hr = pCDDBControl->IsRegistered(FALSE, &pVal);
|
|||
|
}
|
|||
|
|
|||
|
cddbInitialized = true;
|
|||
|
}
|
|||
|
|
|||
|
if (pCDDBControl)
|
|||
|
pCDDBControl->AddRef();
|
|||
|
|
|||
|
return pCDDBControl;
|
|||
|
}
|
|||
|
|
|||
|
#if 0
|
|||
|
/// This is the deprecated version of GetPlaylistManager that is no longer used without the MLDB manager
|
|||
|
ICddbPlaylist25Mgr *GracenoteApi::GetPlaylistManager()
|
|||
|
{
|
|||
|
ICddbPlaylist25Mgr *playlistMgr;
|
|||
|
|
|||
|
ICDDBControl2 *cddb = GetCDDB();
|
|||
|
if (!cddb)
|
|||
|
return 0;
|
|||
|
|
|||
|
CoCreateInstance(__uuidof(CddbNSWinampPlaylist2Mgr), 0, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&playlistMgr);
|
|||
|
if (playlistMgr)
|
|||
|
{
|
|||
|
playlistMgr->AddRef();
|
|||
|
wchar_t dataPath[MAX_PATH] = {0};
|
|||
|
PathCombineW(dataPath, WASABI_API_APP->path_getUserSettingsPath(), L"Plugins");
|
|||
|
CreateDirectoryW(dataPath, 0);
|
|||
|
PathAppendW(dataPath, L"Gracenote");
|
|||
|
CreateDirectoryW(dataPath, 0);
|
|||
|
|
|||
|
if (SUCCEEDED(playlistMgr->Initialize(cddb, dataPath)))
|
|||
|
{
|
|||
|
playlistMgr->DownloadCorrelates(0);
|
|||
|
playlistInitialized = true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
playlistMgr->Release();
|
|||
|
playlistMgr=0;
|
|||
|
}
|
|||
|
}
|
|||
|
cddb->Release();
|
|||
|
return playlistMgr;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
/// Caller is responsible for freeing the returned BSTR !!!
|
|||
|
BSTR SetAndCreatePath(const wchar_t *node)
|
|||
|
{
|
|||
|
wchar_t path_to_create[MAX_PATH] = {0};
|
|||
|
|
|||
|
BSTR bPath = 0;
|
|||
|
|
|||
|
PathCombineW(path_to_create, WASABI_API_APP->path_getUserSettingsPath(), L"Plugins");
|
|||
|
CreateDirectoryW(path_to_create, 0);
|
|||
|
PathAppendW(path_to_create, node);
|
|||
|
CreateDirectoryW(path_to_create, 0);
|
|||
|
|
|||
|
bPath = SysAllocString(path_to_create);
|
|||
|
// modified path as return value
|
|||
|
return bPath;
|
|||
|
}
|
|||
|
|
|||
|
/// This has superceded the old GetPlaylistManager
|
|||
|
/// Returns both a playlist manager in 'playlistMgr' and an mldb manager in 'mldbMgr'
|
|||
|
//int GracenoteApi::GetPlaylistManagerWithMLDBManager(ICddbPlaylist25Mgr **playlistMgr, ICddbMLDBManager **mldbMgr)
|
|||
|
int GracenoteApi::GetPlaylistManager(ICddbPlaylist25Mgr **playlistMgr, ICddbMLDBManager **mldbMgr)
|
|||
|
{
|
|||
|
ICddbPlaylist25Mgr *playlistMgrCreated;
|
|||
|
ICddbMLDBManager *mldbMgrCreated;
|
|||
|
|
|||
|
ICDDBControl2 *cddb = GetCDDB();
|
|||
|
if (!cddb)
|
|||
|
return 0;
|
|||
|
|
|||
|
// Create the mldb manager
|
|||
|
CoCreateInstance(__uuidof(CddbMLDBManager), 0, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&mldbMgrCreated);
|
|||
|
if (mldbMgrCreated)
|
|||
|
{
|
|||
|
//PL_MLDB_FLAGS_ZERO 0x00000000 Used for initialization.
|
|||
|
//PL_MLDB_CHECK_BASE 0x00000001 Causes CheckDB to verify the consistency of the MLDB data file.
|
|||
|
//PL_MLDB_CHECK_INDEX 0x00000002 Causes CheckDB to verify the consistency of the MLDB index file.
|
|||
|
//PL_MLDB_CHECK_DEEP 0x00000004 Causes CheckDB to perform a thorough check of the MLDB file(s).
|
|||
|
//PL_MLDB_CHECK_DEFAULT 0x00000007 Default operation of CheckDB.
|
|||
|
//PL_MLDB_CLEAR_INIT_FLAG 0x00000010 Causes ModifyInitFlag to remove the file indicating Playlist is initialized.
|
|||
|
//PL_MLDB_SET_INIT_FLAG 0x00000020 Causes ModifyInitFlag to create the file indicating Playlist is initialized.
|
|||
|
//PL_MLDB_BACKUP_BASE 0x00000100 Causes BackupDB to create a backup copy of the MLDB data file.
|
|||
|
//PL_MLDB_BACKUP_INDEX 0x00000200 Causes BackupDB to create a backup copy of the MLDB index file.
|
|||
|
//PL_MLDB_RESTORE_BASE 0x00000400 Causes RestoreDB to restore the MLDB data file from the backup copy.
|
|||
|
//PL_MLDB_RESTORE_INDEX 0x00000800 Causes RestoreDB to restore the MLDB index file from the backup copy.
|
|||
|
//PL_MLDB_DELETE_INDEX 0x00001000 Causes DeleteDBFiles to remove the MLDB index file.
|
|||
|
//PL_MLDB_DELETE_BASE 0x00002000 Causes DeleteDBFiles to remove the MLDB data file.
|
|||
|
//PL_MLDB_DELETE_BACKUPS 0x00004000 Causes DeleteDBFiles to remove the MLDBbackup files.
|
|||
|
//PL_MLDB_DELETE_OTHER 0x00008000 Causes DeleteDBFiles to remove the other (non-MLDB) files used by Playlist.
|
|||
|
//PL_MLDB_AUTO_REINDEX 0x00010000 When specified in SetOptions, will cause theindex file to be automatically rebuilt atinitialization if it is corrupt.
|
|||
|
//PL_MLDB_AUTO_BACKUP 0x00020000 When specified in SetOptions, will cause the MLDB files to be automatically backed up at shutdown (if they have been modified). PL_MLDB_AUTO_MANAGE_INIT_FLAG 0x00040000 When specified in SetOptions, will cause the <20>init file<6C> to be managed automatically (created at initialization, deleted at shut down).
|
|||
|
//PL_MLDB_AUTO_CHECK_IF_INIT_SET 0x00080000 When specified in SetOptions, will cause the MLDB files to be check at initialization if the <20>init file<6C> exists (meaning shut down wasn<73>t called).
|
|||
|
//PL_MLDB_AUTO_CHECK_AT_INIT 0x00100000 When specified in SetOptions, will cause the MLDB files to be checked always at initialization.
|
|||
|
//PL_MLDB_AUTO_DEFAULT 0x000C0000 The default automatic behavior if no flags are specified with SetOptions.
|
|||
|
//PL_MLDB_DEVICE_MLDB_42 0x01000000 Enable Gracenote Device SDK 4.2 compatibility for MLDB, list, and correlates files
|
|||
|
|
|||
|
//long autoFlags = PL_MLDB_AUTO_DEFAULT;
|
|||
|
//long autoFlags = PL_MLDB_AUTO_REINDEX | PL_MLDB_AUTO_BACKUP | PL_MLDB_AUTO_MANAGE_INIT_FLAG | PL_MLDB_AUTO_CHECK_IF_INIT_SET | PL_MLDB_AUTO_CHECK_AT_INIT;
|
|||
|
long autoFlags = PL_MLDB_AUTO_REINDEX | PL_MLDB_AUTO_BACKUP | PL_MLDB_AUTO_MANAGE_INIT_FLAG | PL_MLDB_AUTO_CHECK_IF_INIT_SET;
|
|||
|
BSTR bDataPath = SetAndCreatePath(L"Gracenote");
|
|||
|
BSTR bBackupPath = SetAndCreatePath(L"Gracenote/Backup");
|
|||
|
|
|||
|
mldbMgrCreated->AddRef();
|
|||
|
mldbMgrCreated->SetOptions(autoFlags, bBackupPath);
|
|||
|
|
|||
|
|
|||
|
CoCreateInstance(__uuidof(CddbNSWinampPlaylist2Mgr), 0, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&playlistMgrCreated);
|
|||
|
if (playlistMgrCreated)
|
|||
|
{
|
|||
|
playlistMgrCreated->AddRef();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
mldbMgrCreated->Attach(playlistMgrCreated); // Attach the MLDB manager to the playlistMgr
|
|||
|
|
|||
|
if (SUCCEEDED(playlistMgrCreated->Initialize(cddb, bDataPath)))
|
|||
|
{
|
|||
|
playlistMgrCreated->DownloadCorrelates(0);
|
|||
|
playlistInitialized = true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
playlistMgrCreated->Release();
|
|||
|
playlistMgrCreated=0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SysFreeString(bDataPath);
|
|||
|
SysFreeString(bBackupPath);
|
|||
|
}
|
|||
|
cddb->Release();
|
|||
|
|
|||
|
*mldbMgr = mldbMgrCreated;
|
|||
|
*playlistMgr = playlistMgrCreated;
|
|||
|
|
|||
|
if (mldbMgr && playlistMgr)
|
|||
|
return NErr_Success;
|
|||
|
else
|
|||
|
return NErr_FailedCreate;
|
|||
|
}
|
|||
|
|
|||
|
/// Dont really have to use this, get the MLDB manager when creating the playlist manager
|
|||
|
ICddbMLDBManager *GracenoteApi::GetMLDBManager()
|
|||
|
{
|
|||
|
ICddbMLDBManager *mldbMgr;
|
|||
|
|
|||
|
ICDDBControl2 *cddb = GetCDDB();
|
|||
|
if (!cddb)
|
|||
|
return 0;
|
|||
|
|
|||
|
CoCreateInstance(__uuidof(CddbMLDBManager), 0, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&mldbMgr);
|
|||
|
if (mldbMgr)
|
|||
|
{
|
|||
|
mldbMgr->AddRef();
|
|||
|
}
|
|||
|
cddb->Release();
|
|||
|
return mldbMgr;
|
|||
|
}
|
|||
|
|
|||
|
HRESULT GracenoteApi::CreateFingerprint(ICDDBMusicIDManager *musicID, api_decodefile *decodeApi, ICddbFileInfo *info, const wchar_t *filename, long *killswitch)
|
|||
|
{
|
|||
|
if (!musicID || !decodeApi)
|
|||
|
return E_FAIL;
|
|||
|
|
|||
|
ICddbMusicIDFingerprinterPtr fingerprinter;
|
|||
|
musicID->CreateFingerprinter(NULL, &fingerprinter);
|
|||
|
|
|||
|
AudioParameters parameters;
|
|||
|
parameters.bitsPerSample = 16;
|
|||
|
parameters.channels = 2;
|
|||
|
parameters.sampleRate = 44100;
|
|||
|
ifc_audiostream *decoder = decodeApi->OpenAudioBackground(filename, ¶meters);
|
|||
|
if (decoder)
|
|||
|
{
|
|||
|
HRESULT hr = fingerprinter->BeginAudioStream((long)parameters.sampleRate, (long)parameters.bitsPerSample, (long)parameters.channels);
|
|||
|
char data[65536] = {0};
|
|||
|
size_t decodeSize;
|
|||
|
int decode_killswitch=0, decode_error;
|
|||
|
while (decodeSize = decoder->ReadAudio((void *)data, sizeof(data), &decode_killswitch, &decode_error))
|
|||
|
{
|
|||
|
if (decodeSize > LONG_MAX) // I _really_ doubt this is going to happen, but just in case, since we cast down to a long
|
|||
|
break;
|
|||
|
|
|||
|
if (*killswitch)
|
|||
|
break;
|
|||
|
hr = fingerprinter->WriteAudioData(data, (long)decodeSize);
|
|||
|
if (hr == CDDBMusicID_FPAcquired)
|
|||
|
break;
|
|||
|
}
|
|||
|
ICddbMusicIDFingerprintPtr fingerprint;
|
|||
|
fingerprinter->EndAudioStream(&fingerprint);
|
|||
|
decodeApi->CloseAudio(decoder);
|
|||
|
|
|||
|
hr=info->put_Fingerprint(fingerprint);
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
return E_FAIL;
|
|||
|
}
|
|||
|
|
|||
|
ICDDBMusicIDManager3 *GracenoteApi::GetMusicID()
|
|||
|
{
|
|||
|
ICDDBControl2 *cddb = GetCDDB();
|
|||
|
if (!cddb)
|
|||
|
return 0;
|
|||
|
ICDDBMusicIDManager3 *musicID;
|
|||
|
CoCreateInstance(__uuidof(CDDBNSWinampMusicIDManager), 0, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&musicID);
|
|||
|
if (musicID)
|
|||
|
musicID->Initialize(cddb);
|
|||
|
cddb->Release();
|
|||
|
return musicID;
|
|||
|
}
|
|||
|
|
|||
|
#define CBCLASS GracenoteApi
|
|||
|
START_DISPATCH;
|
|||
|
CB(API_GRACENOTE_GETCDDB, GetCDDB)
|
|||
|
CB(API_GRACENOTE_GETMUSICID, GetMusicID)
|
|||
|
CB(API_GRACENOTE_GETPLAYLISTMGR, GetPlaylistManager)
|
|||
|
//CB(API_GRACENOTE_GETPLAYLISTMGRWITHMLDBMGR, GetPlaylistManagerWithMLDBManager)
|
|||
|
CB(API_GRACENOTE_GETMLDBMGR, GetMLDBManager)
|
|||
|
CB(API_GRACENOTE_CREATEFINGERPRINT, CreateFingerprint)
|
|||
|
END_DISPATCH;
|
|||
|
#undef CBCLASS
|