cddb_lookup: Added options, allow dump/verbose output.
* Added option to dump the track info, and optionally not write the data back. * Added option to use an alternative server. * Added option to dump verbose track info. * Added ability to query the CDDB without actual CD in the drive by providing category and CDDB ID. * Added help text.
This commit is contained in:
parent
768544f677
commit
df53a4bf21
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -30,11 +31,17 @@ public:
|
|||||||
CDDBLookup();
|
CDDBLookup();
|
||||||
virtual ~CDDBLookup();
|
virtual ~CDDBLookup();
|
||||||
|
|
||||||
void LookupAll();
|
void LookupAll(CDDBServer& server, bool dumpOnly,
|
||||||
status_t Lookup(const dev_t device);
|
bool verbose);
|
||||||
|
status_t Lookup(CDDBServer& server, const char* path,
|
||||||
|
bool dumpOnly, bool verbose);
|
||||||
|
status_t Lookup(CDDBServer& server, const dev_t device,
|
||||||
|
bool dumpOnly, bool verbose);
|
||||||
|
status_t Dump(CDDBServer& server, const char* category,
|
||||||
|
const char* cddbID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _CanLookup(const dev_t device, uint32* cddbId,
|
bool _ReadTOC(const dev_t device, uint32* cddbID,
|
||||||
scsi_toc_toc* toc) const;
|
scsi_toc_toc* toc) const;
|
||||||
const QueryResponseData*
|
const QueryResponseData*
|
||||||
_SelectResult(
|
_SelectResult(
|
||||||
@ -42,12 +49,24 @@ private:
|
|||||||
status_t _WriteCDData(dev_t device,
|
status_t _WriteCDData(dev_t device,
|
||||||
const QueryResponseData& diskData,
|
const QueryResponseData& diskData,
|
||||||
const ReadResponseData& readResponse);
|
const ReadResponseData& readResponse);
|
||||||
|
void _Dump(const ReadResponseData& readResponse)
|
||||||
|
const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct option const kLongOptions[] = {
|
||||||
|
{"info", required_argument, 0, 'i'},
|
||||||
|
{"dump", no_argument, 0, 'd'},
|
||||||
|
{"verbose", no_argument, 0, 'v'},
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern const char *__progname;
|
extern const char *__progname;
|
||||||
static const char *kProgramName = __progname;
|
static const char *kProgramName = __progname;
|
||||||
|
|
||||||
|
static const char* kDefaultServerAddress = "freedb.freedb.org:80";
|
||||||
static const char* kCddaFsName = "cdda";
|
static const char* kCddaFsName = "cdda";
|
||||||
static const int kMaxTocSize = 1024;
|
static const int kMaxTocSize = 1024;
|
||||||
|
|
||||||
@ -65,36 +84,54 @@ CDDBLookup::~CDDBLookup()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CDDBLookup::LookupAll()
|
CDDBLookup::LookupAll(CDDBServer& server, bool dumpOnly, bool verbose)
|
||||||
{
|
{
|
||||||
BVolumeRoster roster;
|
BVolumeRoster roster;
|
||||||
BVolume volume;
|
BVolume volume;
|
||||||
while (roster.GetNextVolume(&volume) == B_OK) {
|
while (roster.GetNextVolume(&volume) == B_OK) {
|
||||||
Lookup(volume.Device());
|
Lookup(server, volume.Device(), dumpOnly, verbose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
CDDBLookup::Lookup(const dev_t device)
|
CDDBLookup::Lookup(CDDBServer& server, const char* path, bool dumpOnly,
|
||||||
|
bool verbose)
|
||||||
|
{
|
||||||
|
BVolumeRoster roster;
|
||||||
|
BVolume volume;
|
||||||
|
while (roster.GetNextVolume(&volume) == B_OK) {
|
||||||
|
fs_info info;
|
||||||
|
if (fs_stat_dev(volume.Device(), &info) != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(path, info.device_name) == 0)
|
||||||
|
return Lookup(server, volume.Device(), dumpOnly, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CDDBLookup::Lookup(CDDBServer& server, const dev_t device, bool dumpOnly,
|
||||||
|
bool verbose)
|
||||||
{
|
{
|
||||||
scsi_toc_toc* toc = (scsi_toc_toc*)malloc(kMaxTocSize);
|
scsi_toc_toc* toc = (scsi_toc_toc*)malloc(kMaxTocSize);
|
||||||
if (toc == NULL)
|
if (toc == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
uint32 cddbId;
|
uint32 cddbID;
|
||||||
if (!_CanLookup(device, &cddbId, toc)) {
|
if (!_ReadTOC(device, &cddbID, toc)) {
|
||||||
free(toc);
|
free(toc);
|
||||||
fprintf(stderr, "Skipping device with id %" B_PRId32 ".\n", device);
|
fprintf(stderr, "Skipping device with id %" B_PRId32 ".\n", device);
|
||||||
return B_BAD_TYPE;
|
return B_BAD_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Looking up CD with CDDB Id %08" B_PRIx32 ".\n", cddbId);
|
printf("Looking up CD with CDDB Id %08" B_PRIx32 ".\n", cddbID);
|
||||||
|
|
||||||
CDDBServer cddbServer("freedb.freedb.org:80");
|
|
||||||
|
|
||||||
BObjectList<QueryResponseData> queryResponses(10, true);
|
BObjectList<QueryResponseData> queryResponses(10, true);
|
||||||
status_t result = cddbServer.Query(cddbId, toc, queryResponses);
|
status_t result = server.Query(cddbID, toc, queryResponses);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
fprintf(stderr, "Error when querying CD: %s\n", strerror(result));
|
fprintf(stderr, "Error when querying CD: %s\n", strerror(result));
|
||||||
free(toc);
|
free(toc);
|
||||||
@ -110,28 +147,48 @@ CDDBLookup::Lookup(const dev_t device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReadResponseData readResponse;
|
ReadResponseData readResponse;
|
||||||
result = cddbServer.Read(*diskData, readResponse);
|
result = server.Read(*diskData, readResponse);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
fprintf(stderr, "Could not read detailed CD entry from server: %s\n",
|
fprintf(stderr, "Could not read detailed CD entry from server: %s\n",
|
||||||
strerror(result));
|
strerror(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = _WriteCDData(device, *diskData, readResponse);
|
if (verbose || dumpOnly)
|
||||||
if (result == B_OK)
|
_Dump(readResponse);
|
||||||
printf("CD data saved.\n");
|
|
||||||
else
|
|
||||||
fprintf(stderr, "Error writing CD data: %s\n", strerror(result));
|
|
||||||
|
|
||||||
|
if (!dumpOnly) {
|
||||||
|
result = _WriteCDData(device, *diskData, readResponse);
|
||||||
|
if (result == B_OK)
|
||||||
|
printf("CD data saved.\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Error writing CD data: %s\n", strerror(result));
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CDDBLookup::Dump(CDDBServer& server, const char* category, const char* cddbID)
|
||||||
|
{
|
||||||
|
ReadResponseData readResponse;
|
||||||
|
status_t status = server.Read(category, cddbID, "", readResponse);
|
||||||
|
if (status != B_OK) {
|
||||||
|
fprintf(stderr, "Could not read detailed CD entry from server: %s\n",
|
||||||
|
strerror(status));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Dump(readResponse);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CDDBLookup::_CanLookup(const dev_t device, uint32* cddbId,
|
CDDBLookup::_ReadTOC(const dev_t device, uint32* cddbID,
|
||||||
scsi_toc_toc* toc) const
|
scsi_toc_toc* toc) const
|
||||||
{
|
{
|
||||||
if (cddbId == NULL || toc == NULL)
|
if (cddbID == NULL || toc == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Is it an Audio disk?
|
// Is it an Audio disk?
|
||||||
@ -147,17 +204,17 @@ CDDBLookup::_CanLookup(const dev_t device, uint32* cddbId,
|
|||||||
|
|
||||||
bool doLookup;
|
bool doLookup;
|
||||||
if (directory.ReadAttr("CD:do_lookup", B_BOOL_TYPE, 0, (void *)&doLookup,
|
if (directory.ReadAttr("CD:do_lookup", B_BOOL_TYPE, 0, (void *)&doLookup,
|
||||||
sizeof(bool)) < B_OK || !doLookup)
|
sizeof(bool)) < B_OK || !doLookup)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Does it have the CD:cddbid attribute?
|
// Does it have the CD:cddbid attribute?
|
||||||
if (directory.ReadAttr("CD:cddbid", B_UINT32_TYPE, 0, (void *)cddbId,
|
if (directory.ReadAttr("CD:cddbid", B_UINT32_TYPE, 0, (void *)cddbID,
|
||||||
sizeof(uint32)) < B_OK)
|
sizeof(uint32)) < B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Does it have the CD:toc attribute?
|
// Does it have the CD:toc attribute?
|
||||||
if (directory.ReadAttr("CD:toc", B_RAW_TYPE, 0, (void *)toc,
|
if (directory.ReadAttr("CD:toc", B_RAW_TYPE, 0, (void *)toc,
|
||||||
kMaxTocSize) < B_OK)
|
kMaxTocSize) < B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -178,7 +235,7 @@ CDDBLookup::_SelectResult(const QueryResponseList& responses) const
|
|||||||
|
|
||||||
for (int32 i = 0; i < numItems; i++) {
|
for (int32 i = 0; i < numItems; i++) {
|
||||||
QueryResponseData* data = responses.ItemAt(i);
|
QueryResponseData* data = responses.ItemAt(i);
|
||||||
printf("* %s : %s - %s (%s)\n", data->cddbId.String(),
|
printf("* %s : %s - %s (%s)\n", data->cddbID.String(),
|
||||||
data->artist.String(), data->title.String(),
|
data->artist.String(), data->title.String(),
|
||||||
data->category.String());
|
data->category.String());
|
||||||
}
|
}
|
||||||
@ -258,15 +315,120 @@ CDDBLookup::_WriteCDData(dev_t device, const QueryResponseData& diskData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CDDBLookup::_Dump(const ReadResponseData& readResponse) const
|
||||||
|
{
|
||||||
|
printf("Artist: %s\n", readResponse.artist.String());
|
||||||
|
printf("Title: %s\n", readResponse.title.String());
|
||||||
|
printf("Genre: %s\n", readResponse.genre.String());
|
||||||
|
printf("Year: %" B_PRIu32 "\n", readResponse.year);
|
||||||
|
puts("Tracks:");
|
||||||
|
for (int32 i = 0; i < readResponse.tracks.CountItems(); i++) {
|
||||||
|
TrackData* track = readResponse.tracks.ItemAt(i);
|
||||||
|
if (track->artist.IsEmpty()) {
|
||||||
|
printf(" %2" B_PRIu32 ". %s\n", track->trackNumber + 1,
|
||||||
|
track->title.String());
|
||||||
|
} else {
|
||||||
|
printf(" %2" B_PRIu32 ". %s - %s\n", track->trackNumber + 1,
|
||||||
|
track->artist.String(), track->title.String());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
int
|
static void
|
||||||
main(void)
|
usage(int exitCode)
|
||||||
{
|
{
|
||||||
// TODO: support arguments to specify a device
|
fprintf(exitCode == EXIT_SUCCESS ? stdout : stderr,
|
||||||
|
"Usage: %s [-vdh] [-s <server>] [-i <category> <cddb-id>|<device>]\n"
|
||||||
|
"\nYou can specify the device either as path on the device, or using "
|
||||||
|
"the\ndevice name directly. If you do not specify a device, and are\n"
|
||||||
|
"using the -i option, all volumes will be scanned for CD info.\n\n"
|
||||||
|
" -s, --server\tUse alternative server. Default is %s.\n"
|
||||||
|
" -v, --verbose\tVerbose output.\n"
|
||||||
|
" -d, --dump\tDo not write attributes, only dump info to terminal.\n"
|
||||||
|
" -h, --help\tThis help text.\n"
|
||||||
|
" -i\t\tDump info for the specified category/cddb ID pair.\n",
|
||||||
|
kProgramName, kDefaultServerAddress);
|
||||||
|
exit(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char* const* argv)
|
||||||
|
{
|
||||||
|
const char* serverAddress = kDefaultServerAddress;
|
||||||
|
const char* category = NULL;
|
||||||
|
bool verbose = false;
|
||||||
|
bool dump = false;
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = getopt_long(argc, argv, "i:s:vdh", kLongOptions, NULL)) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
category = optarg;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
serverAddress = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose = true;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
dump = true;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CDDBServer server(serverAddress);
|
||||||
CDDBLookup cddb;
|
CDDBLookup cddb;
|
||||||
cddb.LookupAll();
|
int left = argc - optind;
|
||||||
|
|
||||||
|
if (category != NULL) {
|
||||||
|
if (left != 1) {
|
||||||
|
fprintf(stderr, "CDDB disc ID expected!\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cddbID = argv[optind];
|
||||||
|
cddb.Dump(server, category, cddbID);
|
||||||
|
} else {
|
||||||
|
// Lookup via actual CD
|
||||||
|
if (left > 0) {
|
||||||
|
for (int i = optind; i < argc; i++) {
|
||||||
|
// Allow to specify a device
|
||||||
|
const char* path = argv[i];
|
||||||
|
status_t status;
|
||||||
|
if (strncmp(path, "/dev/", 5) == 0) {
|
||||||
|
status = cddb.Lookup(server, path, dump, verbose);
|
||||||
|
} else {
|
||||||
|
dev_t device = dev_for_path(path);
|
||||||
|
if (device >= 0)
|
||||||
|
status = cddb.Lookup(server, device, dump, verbose);
|
||||||
|
else
|
||||||
|
status = (status_t)device;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != B_OK) {
|
||||||
|
fprintf(stderr, "Invalid path \"%s\": %s\n", path,
|
||||||
|
strerror(status));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
cddb.LookupAll(server, dump, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ CDDBServer::CDDBServer(const BString& cddbServer)
|
|||||||
fInitialized(false),
|
fInitialized(false),
|
||||||
fConnected(false)
|
fConnected(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Set up local host name.
|
// Set up local host name.
|
||||||
char localHostName[MAXHOSTNAMELEN + 1];
|
char localHostName[MAXHOSTNAMELEN + 1];
|
||||||
if (gethostname(localHostName, MAXHOSTNAMELEN + 1) == 0) {
|
if (gethostname(localHostName, MAXHOSTNAMELEN + 1) == 0) {
|
||||||
@ -50,7 +49,7 @@ CDDBServer::CDDBServer(const BString& cddbServer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
CDDBServer::Query(uint32 cddbId, const scsi_toc_toc* toc,
|
CDDBServer::Query(uint32 cddbID, const scsi_toc_toc* toc,
|
||||||
QueryResponseList& queryResponses)
|
QueryResponseList& queryResponses)
|
||||||
{
|
{
|
||||||
if (_OpenConnection() != B_OK)
|
if (_OpenConnection() != B_OK)
|
||||||
@ -58,7 +57,7 @@ CDDBServer::Query(uint32 cddbId, const scsi_toc_toc* toc,
|
|||||||
|
|
||||||
// Convert CDDB id to hexadecimal format.
|
// Convert CDDB id to hexadecimal format.
|
||||||
char hexCddbId[9];
|
char hexCddbId[9];
|
||||||
sprintf(hexCddbId, "%08" B_PRIx32, cddbId);
|
sprintf(hexCddbId, "%08" B_PRIx32, cddbID);
|
||||||
|
|
||||||
// Assemble the Query command.
|
// Assemble the Query command.
|
||||||
int32 numTracks = toc->last_track + 1 - toc->first_track;
|
int32 numTracks = toc->last_track + 1 - toc->first_track;
|
||||||
@ -127,7 +126,7 @@ CDDBServer::Query(uint32 cddbId, const scsi_toc_toc* toc,
|
|||||||
output.MoveInto(responseData->category, 0, output.FindFirst(" "));
|
output.MoveInto(responseData->category, 0, output.FindFirst(" "));
|
||||||
output.Remove(0, 1);
|
output.Remove(0, 1);
|
||||||
|
|
||||||
output.MoveInto(responseData->cddbId, 0, output.FindFirst(" "));
|
output.MoveInto(responseData->cddbID, 0, output.FindFirst(" "));
|
||||||
output.Remove(0, 1);
|
output.Remove(0, 1);
|
||||||
|
|
||||||
output.MoveInto(responseData->artist, 0, output.FindFirst(" / "));
|
output.MoveInto(responseData->artist, 0, output.FindFirst(" / "));
|
||||||
@ -155,13 +154,22 @@ CDDBServer::Query(uint32 cddbId, const scsi_toc_toc* toc,
|
|||||||
status_t
|
status_t
|
||||||
CDDBServer::Read(const QueryResponseData& diskData,
|
CDDBServer::Read(const QueryResponseData& diskData,
|
||||||
ReadResponseData& readResponse)
|
ReadResponseData& readResponse)
|
||||||
|
{
|
||||||
|
return Read(diskData.category, diskData.cddbID, diskData.artist,
|
||||||
|
readResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CDDBServer::Read(const BString& category, const BString& cddbID,
|
||||||
|
const BString& artist, ReadResponseData& readResponse)
|
||||||
{
|
{
|
||||||
if (_OpenConnection() != B_OK)
|
if (_OpenConnection() != B_OK)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
// Assemble the Read command.
|
// Assemble the Read command.
|
||||||
BString cddbCommand("cddb read ");
|
BString cddbCommand("cddb read ");
|
||||||
cddbCommand << diskData.category << " " << diskData.cddbId;
|
cddbCommand << category << " " << cddbID;
|
||||||
|
|
||||||
BString output;
|
BString output;
|
||||||
status_t result = _SendCommand(cddbCommand, output);
|
status_t result = _SendCommand(cddbCommand, output);
|
||||||
@ -256,17 +264,15 @@ CDDBServer::Read(const QueryResponseData& diskData,
|
|||||||
trackData->trackNumber = track;
|
trackData->trackNumber = track;
|
||||||
|
|
||||||
int32 pos = line.FindFirst(" / ");
|
int32 pos = line.FindFirst(" / ");
|
||||||
if (pos >= 0 && diskData.artist.ICompare("Various") == 0) {
|
if (pos >= 0 && artist.ICompare("Various") == 0) {
|
||||||
// Disk is set to have a compilation artist and
|
// Disk is set to have a compilation artist and
|
||||||
// we have track specific artist information.
|
// we have track specific artist information.
|
||||||
BString artist;
|
line.MoveInto(trackData->artist, 0, pos);
|
||||||
line.MoveInto(artist, 0, pos);
|
|
||||||
// Move artist information from line to artist.
|
// Move artist information from line to artist.
|
||||||
line.Remove(0, 3);
|
line.Remove(0, 3);
|
||||||
// Remove " / " from line.
|
// Remove " / " from line.
|
||||||
trackData->artist = artist;
|
|
||||||
} else {
|
} else {
|
||||||
trackData->artist = diskData.artist;
|
trackData->artist = artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackData->title = line;
|
trackData->title = line;
|
||||||
|
@ -28,7 +28,7 @@ struct TrackData {
|
|||||||
// Query command response.
|
// Query command response.
|
||||||
struct QueryResponseData {
|
struct QueryResponseData {
|
||||||
BString category;
|
BString category;
|
||||||
BString cddbId;
|
BString cddbID;
|
||||||
BString artist;
|
BString artist;
|
||||||
BString title;
|
BString title;
|
||||||
};
|
};
|
||||||
@ -58,10 +58,14 @@ public:
|
|||||||
CDDBServer(const BString& cddbServer);
|
CDDBServer(const BString& cddbServer);
|
||||||
|
|
||||||
// CDDB commands interface.
|
// CDDB commands interface.
|
||||||
status_t Query(uint32 cddbId, const scsi_toc_toc* toc,
|
status_t Query(uint32 cddbID, const scsi_toc_toc* toc,
|
||||||
QueryResponseList& queryResponses);
|
QueryResponseList& queryResponses);
|
||||||
status_t Read(const QueryResponseData& diskData,
|
status_t Read(const QueryResponseData& diskData,
|
||||||
ReadResponseData& readResponse);
|
ReadResponseData& readResponse);
|
||||||
|
status_t Read(const BString& category,
|
||||||
|
const BString& cddbID,
|
||||||
|
const BString& artist,
|
||||||
|
ReadResponseData& readResponse);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _ParseAddress(const BString& cddbServer);
|
status_t _ParseAddress(const BString& cddbServer);
|
||||||
|
Loading…
Reference in New Issue
Block a user