winamp/Src/Plugins/Input/in_cdda/nde_cd.cpp

720 lines
21 KiB
C++
Raw Permalink Normal View History

2024-09-24 12:54:57 +00:00
#include "../nde/nde_c.h"
#include "main.h"
#include <shlwapi.h>
#include "../nu/AutoLock.h"
#include "../nu/AutoWide.h"
#include "cddbinterface.h"
#include "cddb.h"
#include "api__in_cdda.h"
#include <api/service/waservicefactory.h>
#include <atlbase.h>
#include <strsafe.h>
using namespace Nullsoft::Utility;
static nde_database_t discDB=0;
static nde_table_t discTable=0, trackTable=0;
static Nullsoft::Utility::LockGuard dbcs;
static int g_dirty;
enum
{
NDE_CD_SUCCESS=0,
NDE_CD_FAILURE=1,
};
enum
{
DISCTABLE_ID_DISCID = 0,
DISCTABLE_ID_ALBUM=1,
DISCTABLE_ID_ARTIST=2,
DISCTABLE_ID_TUID=3,
DISCTABLE_ID_YEAR=4,
DISCTABLE_ID_GENRE=5,
DISCTABLE_ID_COMMENT=6,
DISCTABLE_ID_DISC=7,
DISCTABLE_ID_COMPOSER=8,
DISCTABLE_ID_PUBLISHER=9,
DISCTABLE_ID_CONDUCTOR=10,
DISCTABLE_ID_REMIXING=10,
};
enum
{
TRACKTABLE_ID_DISCID = 0,
TRACKTABLE_ID_TRACK = 1,
TRACKTABLE_ID_ARTIST=2,
TRACKTABLE_ID_TITLE=3,
TRACKTABLE_ID_TAGID=4,
TRACKTABLE_ID_COMPOSER=5,
TRACKTABLE_ID_CONDUCTOR=6,
TRACKTABLE_ID_EXTENDED_DATA=7,
TRACKTABLE_ID_REMIXING=8,
TRACKTABLE_ID_ISRC=9,
};
static void CreateDiscFields(nde_table_t table)
{
// create defaults
NDE_Table_NewColumnW(table, DISCTABLE_ID_DISCID, L"discid", FIELD_INTEGER);
NDE_Table_NewColumnW(table, DISCTABLE_ID_ALBUM, L"title", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_ARTIST, L"artist", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_TUID, L"tuid", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_YEAR, L"year", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_GENRE, L"genre", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_COMMENT, L"comment", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_DISC, L"disc", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_COMPOSER, L"composer", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_PUBLISHER, L"publisher", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_CONDUCTOR, L"conductor", FIELD_STRING);
NDE_Table_NewColumnW(table, DISCTABLE_ID_REMIXING, L"remixing", FIELD_STRING);
NDE_Table_PostColumns(table);
NDE_Table_AddIndexByIDW(table, DISCTABLE_ID_DISCID, L"discid");
}
static void CreateTrackFields(nde_table_t table)
{
// create defaults
NDE_Table_NewColumnW(table, TRACKTABLE_ID_DISCID, L"discid", FIELD_INTEGER);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_TRACK, L"track", FIELD_INTEGER);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_ARTIST, L"artist", FIELD_STRING);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_TITLE, L"title", FIELD_STRING);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_TAGID, L"tagid", FIELD_STRING);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_COMPOSER, L"composer", FIELD_STRING);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_CONDUCTOR, L"conductor", FIELD_STRING);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_EXTENDED_DATA, L"extendeddata", FIELD_STRING);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_REMIXING, L"remixing", FIELD_STRING);
NDE_Table_NewColumnW(table, TRACKTABLE_ID_ISRC, L"ISRC", FIELD_STRING);
NDE_Table_PostColumns(table);
NDE_Table_AddIndexByIDW(table, TRACKTABLE_ID_DISCID, L"discid");
NDE_Table_AddIndexByIDW(table, TRACKTABLE_ID_TRACK, L"track");
}
static int OpenDiscDatabase()
{
AutoLock lock(dbcs);
if (!discDB)
{
discDB = NDE_CreateDatabase();
}
return NDE_CD_SUCCESS;
}
static int OpenDiscTable()
{
AutoLock lock(dbcs);
int ret = OpenDiscDatabase();
if (ret != NDE_CD_SUCCESS)
{
return ret;
}
if (!discTable)
{
const wchar_t *inidir = WASABI_API_APP->path_getUserSettingsPath();
wchar_t discTablePath[MAX_PATH] = {0}, discIndexPath[MAX_PATH] = {0};
PathCombineW(discTablePath, inidir, L"plugins");
PathAppendW(discTablePath, L"cddiscs.dat");
PathCombineW(discIndexPath, inidir, L"plugins");
PathAppendW(discIndexPath, L"cddiscs.idx");
discTable = NDE_Database_OpenTable(discDB, discTablePath, discIndexPath, NDE_OPEN_ALWAYS, NDE_CACHE);
if (discTable)
{
CreateDiscFields(discTable);
}
}
return (discTable ? NDE_CD_SUCCESS : NDE_CD_FAILURE);
}
static int OpenTrackTable()
{
AutoLock lock(dbcs);
int ret = OpenDiscDatabase();
if (ret != NDE_CD_SUCCESS)
{
return ret;
}
if (!trackTable)
{
const wchar_t *inidir = WASABI_API_APP->path_getUserSettingsPath();
wchar_t trackTablePath[MAX_PATH] = {0}, trackIndexPath[MAX_PATH] = {0};
PathCombineW(trackTablePath, inidir, L"plugins");
PathAppendW(trackTablePath, L"cdtracks.dat");
PathCombineW(trackIndexPath, inidir, L"plugins");
PathAppendW(trackIndexPath, L"cdtracks.idx");
trackTable = NDE_Database_OpenTable(discDB, trackTablePath, trackIndexPath, NDE_OPEN_ALWAYS, NDE_CACHE);
if (trackTable)
{
CreateTrackFields(trackTable);
}
}
return (trackTable ? NDE_CD_SUCCESS : NDE_CD_FAILURE);
}
void CloseTables()
{
if (discTable)
{
if (g_dirty & 1) NDE_Table_Sync(discTable);
NDE_Database_CloseTable(discDB, discTable);
discTable = 0;
}
if (trackTable)
{
if (g_dirty & 2) NDE_Table_Sync(trackTable);
NDE_Database_CloseTable(discDB, trackTable);
trackTable = 0;
}
if (discDB)
{
NDE_DestroyDatabase(discDB);
discDB = 0;
}
g_dirty = 0;
}
static void db_setFieldInt(nde_scanner_t s, unsigned char id, int data)
{
nde_field_t f = NDE_Scanner_GetFieldByID(s, id);
if (!f) f = NDE_Scanner_NewFieldByID(s, id);
NDE_IntegerField_SetValue(f, data);
}
static void db_setFieldString(nde_scanner_t s, unsigned char id, const wchar_t *data)
{
nde_field_t f = NDE_Scanner_GetFieldByID(s, id);
if (!f) f = NDE_Scanner_NewFieldByID(s, id);
NDE_StringField_SetString(f, data);
}
static void db_removeField(nde_scanner_t s, unsigned char id)
{
nde_field_t f = NDE_Scanner_GetFieldByID(s, id);
if (f)
{
NDE_Scanner_DeleteField(s, f);
}
}
static int db_getFieldInt(nde_scanner_t s, unsigned char id, int defaultVal)
{
nde_field_t f = NDE_Scanner_GetFieldByID(s, id);
if (f)
return NDE_IntegerField_GetValue(f);
else
return defaultVal;
}
static wchar_t *db_getFieldString(nde_scanner_t s, unsigned char id)
{
nde_field_t f = NDE_Scanner_GetFieldByID(s, id);
if (f)
return NDE_StringField_GetString(f);
else
return 0;
}
static void SeekToDisc(nde_scanner_t s, unsigned int cddb_id)
{
if (!NDE_Scanner_LocateInteger(s, DISCTABLE_ID_DISCID, FIRST_RECORD, cddb_id))
{
NDE_Scanner_New(s);
db_setFieldInt(s,DISCTABLE_ID_DISCID,cddb_id);
}
}
static void SeekToTrack(nde_scanner_t s, unsigned int cddb_id, int track)
{
nde_field_t f_id = NDE_IntegerField_Create(cddb_id);
NDE_Scanner_AddFilterByID(s, TRACKTABLE_ID_DISCID, f_id, FILTER_EQUALS);
if (!NDE_Scanner_LocateInteger(s, TRACKTABLE_ID_TRACK, FIRST_RECORD, track))
{
NDE_Scanner_New(s);
db_setFieldInt(s,TRACKTABLE_ID_DISCID,cddb_id);
db_setFieldInt(s,TRACKTABLE_ID_TRACK,track);
}
NDE_Scanner_RemoveFilters(s);
}
#ifndef IGNORE_API_GRACENOTE
void StoreDisc(unsigned int cddb_id, ICddbDiscPtr pDisc)
{
AutoLock lock(dbcs);
CComBSTR str, disc_artist, disc_composer, disc_conductor, disc_remixing;
BSTR composerRole=L"3", conductorRole=L"12", remixingRole=L"147";
/*
for (int i=100;i<300;i++)
{
wchar_t id[256] = {0};
_itow(i, id, 10);
ICddbRolePtr role;
pCDDBControl->GetRoleInfo(id, &role);
if (role)
{
BSTR name, description;
role->get_Name(&name);
role->get_Description(&description);
wchar_t str[4096] = {0};
wsprintf(str, L"ID: %s\r\nName: %s\r\nDescription: %s\r\n", id, name, description);
MessageBoxW(NULL, str, L"CDDB Role", MB_OK);
}
}
*/
OpenDiscTable();
nde_scanner_t s = NDE_Table_CreateScanner(discTable);
SeekToDisc(s, cddb_id);
ICddbDisc2Ptr pDisc2;
pDisc->QueryInterface(&pDisc2);
ICddbDisc2_5Ptr pDisc2_5;
pDisc->QueryInterface(&pDisc2_5);
if (GetRole(pDisc, conductorRole, &disc_conductor) && disc_conductor && disc_conductor.m_str[0])
db_setFieldString(s, DISCTABLE_ID_CONDUCTOR, disc_conductor);
else
db_removeField(s, DISCTABLE_ID_CONDUCTOR);
if (GetRole(pDisc, composerRole, &disc_composer) && disc_composer && disc_composer.m_str[0])
db_setFieldString(s, DISCTABLE_ID_COMPOSER, disc_composer);
else
db_removeField(s, DISCTABLE_ID_COMPOSER);
if (GetRole(pDisc, remixingRole, &disc_remixing) && disc_remixing && disc_remixing.m_str[0])
db_setFieldString(s, DISCTABLE_ID_REMIXING, disc_remixing);
else
db_removeField(s, DISCTABLE_ID_REMIXING);
if (SUCCEEDED(pDisc->get_Artist(&disc_artist)) && disc_artist && disc_artist.m_str[0])
db_setFieldString(s, DISCTABLE_ID_ARTIST, disc_artist);
else
db_removeField(s, DISCTABLE_ID_ARTIST);
if (SUCCEEDED(pDisc->get_Year(&str)) && str && str.m_str[0])
db_setFieldString(s, DISCTABLE_ID_YEAR, str);
else
db_removeField(s, DISCTABLE_ID_YEAR);
if (pDisc2_5 == NULL
|| (FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(3, &str))
&& FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(2, &str))
&& FAILED(pDisc2_5->get_V2GenreStringPrimaryByLevel(1, &str))
&& FAILED(pDisc2_5->get_V2GenreStringPrimary(&str)))
)
{
pDisc->get_GenreId(&str);
ICddbGenre *poop = 0;
if (SUCCEEDED(pCDDBControl->GetGenreInfo(str, &poop)) && poop)
{
poop->get_Name(&str);
poop->Release();
}
else
str.Empty();
}
if (str && str.m_str[0])
db_setFieldString(s, DISCTABLE_ID_GENRE, str);
else
db_removeField(s, DISCTABLE_ID_GENRE);
if (SUCCEEDED(pDisc->get_Title(&str)) && str && str.m_str[0])
db_setFieldString(s, DISCTABLE_ID_ALBUM, str);
else
db_removeField(s, DISCTABLE_ID_ALBUM);
if (SUCCEEDED(pDisc->get_TitleUId(&str)) && str && str.m_str[0])
db_setFieldString(s, DISCTABLE_ID_TUID, str);
else
db_removeField(s, DISCTABLE_ID_TUID);
if (SUCCEEDED(pDisc->get_Label(&str)) && str && str.m_str[0])
db_setFieldString(s, DISCTABLE_ID_PUBLISHER, str);
else
db_removeField(s, DISCTABLE_ID_PUBLISHER);
if (SUCCEEDED(pDisc->get_Notes(&str)) && str && str.m_str[0])
db_setFieldString(s, DISCTABLE_ID_COMMENT, str);
else
db_removeField(s, DISCTABLE_ID_COMMENT);
/*
long val;
pDisc->get_Compilation(&val);
ps->compilation = !!val;
*/
int numdiscs = 0;
if (SUCCEEDED(pDisc->get_TotalInSet(&str)) && str && str.m_str[0])
numdiscs = _wtoi(str.m_str);
int discnum =0;
if (SUCCEEDED(pDisc->get_NumberInSet(&str)) && str && str.m_str[0])
discnum = _wtoi(str.m_str);
if (discnum)
{
wchar_t disc_temp[64] = {0};
if (numdiscs)
StringCchPrintfW(disc_temp, 64, L"%d/%d", discnum, numdiscs);
else
StringCchPrintfW(disc_temp, 64, L"%d", discnum);
db_setFieldString(s, DISCTABLE_ID_DISC, disc_temp);
}
else
db_removeField(s, DISCTABLE_ID_DISC);
long tracks=0;
if (FAILED(pDisc->get_NumTracks(&tracks)))
tracks=0;
NDE_Scanner_Post(s);
NDE_Table_DestroyScanner(discTable, s);
OpenTrackTable();
s = NDE_Table_CreateScanner(trackTable);
for (int x = 0; x < tracks; x ++)
{
ICddbTrack *t=0;
ICddbTrack2_5Ptr track2_5;
if (FAILED(pDisc->GetTrack(x + 1, &t)) || !t)
break;
SeekToTrack(s, cddb_id, x+1);
// don't store if it's the same as the disc artist
if (SUCCEEDED(t->get_Artist(&str)) && str && str.m_str[0] && (!disc_artist || !disc_artist.m_str[0] || wcscmp(str.m_str, disc_artist.m_str)))
db_setFieldString(s, TRACKTABLE_ID_ARTIST, str);
else
db_removeField(s, TRACKTABLE_ID_ARTIST);
if (SUCCEEDED(t->get_Title(&str)) && str && str.m_str[0])
db_setFieldString(s, TRACKTABLE_ID_TITLE, str);
else
db_removeField(s, TRACKTABLE_ID_TITLE);
if (SUCCEEDED(t->get_ISRC(&str)) && str && str.m_str[0])
db_setFieldString(s, TRACKTABLE_ID_ISRC, str);
else
db_removeField(s, TRACKTABLE_ID_ISRC);
if (SUCCEEDED(pCDDBControl->GetDiscTagId(pDisc, x + 1, &str)) && str && str.m_str[0])
db_setFieldString(s, TRACKTABLE_ID_TAGID, str);
else
db_removeField(s, TRACKTABLE_ID_TAGID);
// don't store if it's the same as the disc conductor
if (GetRole(t, conductorRole, &str) && str && str.m_str[0] && (!disc_conductor || !disc_conductor.m_str[0] || wcscmp(str.m_str, disc_conductor.m_str)))
db_setFieldString(s, TRACKTABLE_ID_CONDUCTOR, str);
else
db_removeField(s, TRACKTABLE_ID_CONDUCTOR);
// don't store if it's the same as the disc composer
if (GetRole(t, composerRole, &str) && str && str.m_str[0] && (!disc_composer || !disc_composer.m_str[0] || wcscmp(str.m_str, disc_composer.m_str)))
db_setFieldString(s, TRACKTABLE_ID_COMPOSER, str);
else
db_removeField(s, TRACKTABLE_ID_COMPOSER);
// don't store if it's the same as the disc remixer
if (GetRole(t, remixingRole, &str) && str && str.m_str[0] && (!disc_remixing || !disc_remixing.m_str[0] || wcscmp(str.m_str, disc_remixing.m_str)))
db_setFieldString(s, TRACKTABLE_ID_REMIXING, str);
else
db_removeField(s, TRACKTABLE_ID_REMIXING);
t->QueryInterface(&track2_5);
if (track2_5 != NULL && (SUCCEEDED(track2_5->get_ExtDataSerialized(&str)) && str && str.m_str[0]) // try track first
|| (pDisc2_5 != NULL && SUCCEEDED(pDisc2_5->get_ExtDataSerialized(&str)) && str && str.m_str[0])) // then disc
db_setFieldString(s, TRACKTABLE_ID_EXTENDED_DATA, str);
else
db_removeField(s, TRACKTABLE_ID_EXTENDED_DATA);
NDE_Scanner_Post(s);
t->Release();
}
NDE_Table_DestroyScanner(trackTable, s);
NDE_Table_Sync(trackTable);
NDE_Table_Sync(discTable);
}
#endif
static void CDText_Process(unsigned int cddb_id, const char *title, const char *performers, const char *composers, int codepage)
{
AutoLock lock(dbcs);
OpenDiscTable();
nde_scanner_t s = NDE_Table_CreateScanner(discTable);
SeekToDisc(s, cddb_id);
char thisTitle[1024] = {0};
const char *titles = title;
// first, get disc title
thisTitle[0] = 0;
titles = ReadLine(titles, thisTitle, 1024, codepage);
db_setFieldString(s, DISCTABLE_ID_ALBUM, AutoWide(thisTitle, codepage));
// now get track titles
OpenTrackTable();
nde_scanner_t tableScanner = NDE_Table_CreateScanner(trackTable);
int trackNum = 1;
while (titles && *titles)
{
SeekToTrack(tableScanner, cddb_id, trackNum++);
thisTitle[0] = 0;
titles = ReadLine(titles, thisTitle, 1024, codepage);
db_setFieldString(tableScanner, TRACKTABLE_ID_TITLE, AutoWide(thisTitle, codepage));
NDE_Scanner_Post(tableScanner);
}
titles = performers;
// now get disc artist
thisTitle[0] = 0;
titles = ReadLine(titles, thisTitle, 1024, codepage);
db_setFieldString(s, DISCTABLE_ID_ARTIST, AutoWide(thisTitle, codepage));
// now get track artists
trackNum = 1;
while (titles && *titles)
{
SeekToTrack(tableScanner, cddb_id, trackNum++);
thisTitle[0] = 0;
titles = ReadLine(titles, thisTitle, 1024, codepage);
db_setFieldString(tableScanner, TRACKTABLE_ID_ARTIST, AutoWide(thisTitle, codepage));
NDE_Scanner_Post(tableScanner);
}
titles = composers;
// now get disc composer
thisTitle[0] = 0;
titles = ReadLine(titles, thisTitle, 1024, codepage);
db_setFieldString(s, DISCTABLE_ID_COMPOSER, AutoWide(thisTitle, codepage));
// now get track composers
trackNum = 1;
while (titles && *titles)
{
SeekToTrack(tableScanner, cddb_id, trackNum++);
thisTitle[0] = 0;
titles = ReadLine(titles, thisTitle, 1024, codepage);
db_setFieldString(tableScanner, TRACKTABLE_ID_COMPOSER, AutoWide(thisTitle, codepage));
NDE_Scanner_Post(tableScanner);
}
NDE_Table_DestroyScanner(trackTable, tableScanner);
NDE_Scanner_Post(s);
NDE_Table_DestroyScanner(discTable, s);
}
/* returns true if there was CD text */
bool StoreCDText(unsigned int cddb_id, wchar_t device)
{
if (!device)
return false;
#ifndef IGNORE_API_GRACENOTE
if (config_use_veritas)
{
obj_primo *primo=0;
waServiceFactory *sf = line.service->service_getServiceByGuid(obj_primo::getServiceGuid());
if (sf) primo = reinterpret_cast<obj_primo *>(sf->getInterface());
if (primo)
{
DWORD unit = device;
if (primo->DiscInfoEx(&unit, 0, NULL, NULL, NULL, NULL, NULL, NULL) != PRIMOSDK_OK) // CDTextInfoEJ suggest that this needs to be called first
{
sf->releaseInterface(primo);
return false;
}
char titleE[8192] = "", performerE[8192] = "", composerE[8192] = "", titleJ[2000] = "", performerJ[2000] = "", composerJ[2000] = "";
if (primo->CDTextInfoEJ(&unit, (PBYTE)titleE, (PBYTE)performerE, (PBYTE)composerE, (PBYTE)titleJ, (PBYTE)performerJ, (PBYTE)composerJ) == PRIMOSDK_OK)
{
sf->releaseInterface(primo);
// read titles
if (titleE[0])
{
CDText_Process(cddb_id, titleE, performerE, composerE, 28591 /* Latin1 */);
return true;
}
else if (titleJ[0])
{
CDText_Process(cddb_id, titleJ, performerJ, composerJ, 932 /* SHIFT-JIS */);
return true;
}
}
}
}
#endif
return false;
}
void StoreCDNoInfo(unsigned int cddb_id)
{
AutoLock lock(dbcs);
OpenDiscTable();
nde_scanner_t s = NDE_Table_CreateScanner(discTable);
SeekToDisc(s, cddb_id);
NDE_Scanner_Post(s);
NDE_Table_DestroyScanner(discTable, s);
g_dirty |= 1;
}
// sets part and parts to 0 on fail/missing
void ParseIntSlashInt(const wchar_t *string, int *part, int *parts)
{
*part = 0;
*parts = 0;
if (string && string[0])
{
*part = _wtoi(string);
while (string && *string && *string != '/')
{
string++;
}
if (string && *string == '/')
{
string++;
*parts = _wtoi(string);
}
}
}
bool QueryDINFO(unsigned int cddb_id, DINFO *info)
{
info->Reset();
AutoLock lock(dbcs);
if (OpenDiscTable() != NDE_CD_SUCCESS)
return false;
nde_scanner_t s = NDE_Table_CreateScanner(discTable);
if (NDE_Scanner_LocateInteger(s, DISCTABLE_ID_DISCID, FIRST_RECORD, cddb_id))
{
ndestring_retain(info->title = db_getFieldString(s, DISCTABLE_ID_ALBUM));
ndestring_retain(info->artist = db_getFieldString(s, DISCTABLE_ID_ARTIST));
ndestring_retain(info->tuid = db_getFieldString(s, DISCTABLE_ID_TUID));
ndestring_retain(info->year = db_getFieldString(s, DISCTABLE_ID_YEAR));
ndestring_retain(info->genre = db_getFieldString(s, DISCTABLE_ID_GENRE));
ndestring_retain(info->notes = db_getFieldString(s, DISCTABLE_ID_COMMENT));
const wchar_t *disc_str = db_getFieldString(s, DISCTABLE_ID_DISC);
ParseIntSlashInt(disc_str , &info->discnum, &info->numdiscs);
ndestring_retain(info->composer = db_getFieldString(s, DISCTABLE_ID_COMPOSER));
ndestring_retain(info->label = db_getFieldString(s, DISCTABLE_ID_PUBLISHER));
ndestring_retain(info->conductor = db_getFieldString(s, DISCTABLE_ID_CONDUCTOR));
/* Read tracks */
OpenTrackTable();
nde_scanner_t trackScanner = NDE_Table_CreateScanner(trackTable);
nde_field_t f_id = NDE_IntegerField_Create(cddb_id);
NDE_Scanner_AddFilterByID(trackScanner, TRACKTABLE_ID_DISCID, f_id, FILTER_EQUALS);
int trackNum=1;
while (trackNum < 100)
{
TRACKINFO &trackInfo = info->tracks[trackNum-1];
if (!NDE_Scanner_LocateInteger(trackScanner, TRACKTABLE_ID_TRACK, FIRST_RECORD, trackNum))
break;
trackNum++;
ndestring_retain(trackInfo.artist = db_getFieldString(trackScanner, TRACKTABLE_ID_ARTIST));
ndestring_retain(trackInfo.title = db_getFieldString(trackScanner, TRACKTABLE_ID_TITLE));
ndestring_retain(trackInfo.tagID = db_getFieldString(trackScanner, TRACKTABLE_ID_TAGID));
ndestring_retain(trackInfo.composer = db_getFieldString(trackScanner, TRACKTABLE_ID_COMPOSER));
ndestring_retain(trackInfo.conductor = db_getFieldString(trackScanner, TRACKTABLE_ID_CONDUCTOR));
ndestring_retain(trackInfo.extData = db_getFieldString(trackScanner, TRACKTABLE_ID_EXTENDED_DATA));
}
NDE_Table_DestroyScanner(trackTable, trackScanner);
NDE_Table_DestroyScanner(discTable, s);
info->populated = true;
return true;
}
NDE_Table_DestroyScanner(discTable, s);
return false;
}
static void db_add_or_set(nde_scanner_t s, unsigned char id, wchar_t *data)
{
nde_field_t f = NDE_Scanner_GetFieldByID(s, id);
if (data)
{
if (!f) f = NDE_Scanner_NewFieldByID(s, id);
NDE_StringField_SetNDEString(f, data);
}
else if (f)
{
NDE_Scanner_DeleteField(s, f);
}
}
static void db_compare_add_or_set(nde_scanner_t s, unsigned char id, const wchar_t *disc_data, wchar_t *data)
{
if (disc_data && data && !wcscmp(disc_data, data))
db_removeField(s, id);
else
db_add_or_set(s, id, data);
}
//#ifndef IGNORE_API_GRACENOTE
bool StoreDINFO(unsigned cddb_id, DINFO *info)
{
AutoLock lock(dbcs);
if (OpenDiscTable() != NDE_CD_SUCCESS)
return false;
nde_scanner_t s = NDE_Table_CreateScanner(discTable);
SeekToDisc(s, cddb_id);
db_add_or_set(s, DISCTABLE_ID_ALBUM, info->title);
db_add_or_set(s, DISCTABLE_ID_ARTIST, info->artist);
db_add_or_set(s, DISCTABLE_ID_TUID, info->tuid);
db_add_or_set(s, DISCTABLE_ID_YEAR, info->year);
db_add_or_set(s, DISCTABLE_ID_GENRE, info->genre);
db_add_or_set(s, DISCTABLE_ID_PUBLISHER, info->label);
db_add_or_set(s, DISCTABLE_ID_COMMENT, info->notes);
if (info->discnum)
{
wchar_t disc_temp[64] = {0};
if (info->numdiscs)
StringCchPrintfW(disc_temp, 64, L"%d/%d", info->discnum, info->numdiscs);
else
StringCchPrintfW(disc_temp, 64, L"%d", info->discnum);
db_setFieldString(s, DISCTABLE_ID_DISC, disc_temp);
}
else
db_removeField(s, DISCTABLE_ID_DISC);
db_add_or_set(s, DISCTABLE_ID_CONDUCTOR, info->conductor);
db_add_or_set(s, DISCTABLE_ID_COMPOSER, info->composer);
NDE_Scanner_Post(s);
NDE_Table_DestroyScanner(discTable, s);
OpenTrackTable();
s = NDE_Table_CreateScanner(trackTable);
for (int x=0;x<info->ntracks;x++)
{
SeekToTrack(s, cddb_id, x+1);
TRACKINFO &trackInfo = info->tracks[x];
db_compare_add_or_set(s, TRACKTABLE_ID_ARTIST, info->artist, trackInfo.artist);
db_add_or_set(s, TRACKTABLE_ID_TITLE, trackInfo.title);
db_add_or_set(s, TRACKTABLE_ID_TAGID, trackInfo.tagID);
db_compare_add_or_set(s, TRACKTABLE_ID_COMPOSER, info->composer, trackInfo.composer);
db_compare_add_or_set(s, TRACKTABLE_ID_CONDUCTOR, info->conductor, trackInfo.conductor);
db_add_or_set(s, TRACKTABLE_ID_EXTENDED_DATA, trackInfo.extData);
NDE_Scanner_Post(s);
}
NDE_Table_DestroyScanner(trackTable, s);
NDE_Table_Sync(trackTable);
NDE_Table_Sync(discTable);
g_dirty = 0;
return true;
}
//#endif