discid

These are the bindings for libdiscid from MusicBrainz.
Libdiscid is a C library for calculating DiscIDs (MusicBrainz and freedb) for Audio CDs. Additionally the library can extract the MCN/UPC/EAN and the ISRCs from a disc.
The idea is to have an easy to use library without any dependencies that can be used from scripting languages.
This is an example of the most basic usage:
auto disc = discid_new();
scope(exit) discid_free(disc);

if(discid_read_sparse(disc, "/dev/cdrom", 0) == 0)
{
    stderr.writefln("Error: %s", discid_get_error_msg(disc).fromStringz());
    return 1;
}

writefln("DiscID     : %s", discid_get_id(disc));
writefln("Submit via : %s", discid_get_submission_url(disc));
enum int DISCID_VERSION_MAJOR;
enum int DISCID_VERSION_MINOR;
enum int DISCID_VERSION_PATCH;
enum int DISCID_VERSION_NUM;
alias DiscId = void*;
A transparent handle for an Audio CD.
This is returned by discid_new and has to be passed as the first parameter to all discid_*() functions.
nothrow @nogc @trusted DiscId* discid_new();
Return a handle for a new DiscId object.
If no memory could be allocated, null is returned. Don't use the created DiscId object before calling discid_read or discid_put.
Returns: a DiscId object, or null.
nothrow @nogc @trusted void discid_free(scope DiscId* d);
Release the memory allocated for the DiscId object.
Parameters:
DiscId* d a DiscId object created by discid_new
nothrow @nogc @trusted int discid_read(scope DiscId* d, scope const char* device);
Read all supported features of the disc in the given CD-ROM/DVD-ROM drive.
This function reads the disc in the drive specified by the given device identifier. If the device is null, the default drive, as returned by discid_get_default_device is used.
If you do not require all features provided by libdiscid, such as MCN or ISRC reading, you should consider using discid_read_sparse instead of discid_read for performance reasons.
On error, this function returns false and sets the error message which you can access using discid_get_error_msg. In this case, the other functions won't return meaningful values and should not be used.
This function may be used multiple times with the same DiscId object.
Parameters:
DiscId* d a DiscId object created by discid_new
char* device an operating system dependent device identifier, or null
Returns: true successful, or false on error.
nothrow @nogc @trusted int discid_read_sparse(scope DiscId* d, scope const char* device, uint features);
Read the disc in the given CD-ROM/DVD-ROM drive extracting only the TOC and additionally specified features.
This function will always read the TOC, but additional features like DISCID_FEATURE_MCN and DISCID_FEATURE_ISRC can be set using the features parameter. Multiple features can be set using bitwise OR.
If you only want to generate a disc ID, you only need the TOC, so set features to 0:
discid_read_sparse(disc, device, 0)
This is a bit more verbose, but equivalent since DISCID_FEATURE_READ is always implied:
discid_read_sparse(disc, device, DISCID_FEATURE_READ)
If you want to read all features available, you can use discid_read.
On error, this function returns false and sets the error message which you can access using discid_get_error_msg. In this case, the other functions won't return meaningful values and should not be used.
This function may be used multiple times with the same DiscId object.
Parameters:
DiscId* d a DiscId object created by discid_new
char* device an operating system dependent device identifier, or null
uint features a list of bit flags from the DISCID_FEATURE_* enums.
Returns: true if successful, or false on error.
pure nothrow @nogc @trusted int discid_put(scope DiscId* d, int first, int last, scope int* offsets);
Provides the TOC of a known CD.
This function may be used if the TOC has been read earlier and you want to calculate the disc ID afterwards, without accessing the disc drive. It replaces the discid_read function in this case.
On error, this function returns false and sets the error message which you can access using discid_get_error_msg. In this case, the other functions won't return meaningful values and should not be used.
The offsets parameter points to a C array containing the track offsets for each track. It must contain 100 elements. Rather than a track offset, offsets[0] contains the length of the sectors on the disc (see discid_get_sectors) and offsets[1 .. numTracks + 1] contains the actual track offsets. Unfortunately, the C documentation does not state what the remaining offsets should be, but having them be 0 seems sensible and has worked in all of the cases tested (it's also what naturally happens if int[100] or new int[100] is used for the offsets).
For discs with additional data tracks, the trailing data tracks should be ignored. offsets[0] should therefore be the last sector of the last audio track.
Make sure the length of the last audio track as returned by libdiscid after a put is the same as the length of your last audio track. Depending on your tools you might need to substract 11400 (2:32 min.).
Parameters:
DiscId* d a DiscID object created by discid_new
int first the number of the first audio track on disc (usually one)
int last the number of the last audio track on the disc
int* offsets a pointer to a C array of 100 track offsets
Returns: true if the given data was valid, and false on error
Examples:
import std.string : fromStringz;
import std.stdio : writefln;

int firstTrack;
int lastTrack;
int sectors;
int[] trackOffsets;

{
    auto disc = discid_new();
    scope(exit) discid_free(disc);

    if(discid_read_sparse(disc, null, 0) == 0)
    {
        writefln("Failed to read disc: %s", discid_get_error_msg(disc).fromStringz());
        return;
    }

    firstTrack = discid_get_first_track_num(disc);
    lastTrack = discid_get_last_track_num(disc);
    sectors = discid_get_sectors(disc);

    foreach(track; firstTrack .. lastTrack + 1)
        trackOffsets ~= discid_get_track_offset(disc, track);
}

auto disc = discid_new();
scope(exit) discid_free(disc);

int[100] offsets;
offsets[0] = sectors;
offsets[1 .. trackOffsets.length + 1] = trackOffsets[];

if(discid_put(disc, firstTrack, lastTrack, &offsets[0]) == 0)
{
    writefln("discid_put failed: %s", discid_get_error_msg(disc).fromStringz());
    return;
}

writefln("Disc ID: %s", discid_get_id(disc).fromStringz());
nothrow @nogc @trusted char* discid_get_error_msg(scope DiscId* d);
Return a human-readable error message.
This function may only be used if discid_read failed. The returned error message is only valid as long as the DiscId object exists.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: a string describing the error that occurred
pure nothrow @nogc @trusted char* discid_get_id(scope DiscId* d);
Return a MusicBrainz DiscID.
The returned string is only valid as long as the DiscId object exists.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: a C-string containing a MusicBrainz DiscID
pure nothrow @nogc @trusted char* discid_get_freedb_id(scope DiscId* d);
Return a FreeDB DiscID.
The returned string is only valid as long as the DiscId object exists.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: a C-string containing a FreeDB DiscID
pure nothrow @nogc @trusted char* discid_get_toc_string(scope DiscId* d);
Return a string representing CD Table Of Contents (TOC).
The string has following values separated by space:
  • first track number
  • last track number
  • total length in sectors
  • offset of 1st track
  • offset of 2nd track
Example: "1 7 164900 150 22460 50197 80614 100828 133318 144712"
The returned string is only valid as long as the DiscId object exists.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: a C-string containing TOC information
nothrow @nogc @trusted char* discid_get_submission_url(scope DiscId* d);
Return a URL for submitting the DiscID to MusicBrainz.
The URL leads to an interactive disc submission wizard that guides the user through the process of associating this disc's DiscID with a release in the MusicBrainz database.
The returned string is only valid as long as the DiscId object exists.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: a C-string containing a URL
nothrow @nogc @trusted char* discid_get_default_device();
Return the name of the default disc drive for this machine. This isn't constant but possibly depends on the drives currently attached, depending on the platform. For this reason, you should call this once and save it when you want to make sure to use the same drive for multiple operations.
The returned string is thread local and owned by libdiscid internally.
Returns: a C-string containing an operating system dependent device identifier
pure nothrow @nogc @trusted int discid_get_first_track_num(scope DiscId* d);
Return the number of the first track on this disc.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: the number of the first track
pure nothrow @nogc @trusted int discid_get_last_track_num(scope DiscId* d);
Return the number of the last audio track on this disc.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: the number of the last track
pure nothrow @nogc @trusted int discid_get_sectors(scope DiscId* d);
Return the length of the disc in sectors.
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: the length of the disc in sectors
pure nothrow @nogc @trusted int discid_get_track_offset(scope DiscId* d, int track_num);
Return the sector offset of a track.
Only track numbers between (and including) discid_get_first_track_num and discid_get_last_track_num may be used.
Parameters:
DiscId* d a DiscId object created by discid_new
int track_num the number of a track
Returns: the sector offset of the specified track
pure nothrow @nogc @trusted int discid_get_track_length(scope DiscId* d, int track_num);
Return the length of a track in sectors.
Only track numbers between (and including) discid_get_first_track_num and discid_get_last_track_num may be used.
Parameters:
DiscId* d a DiscId object created by discid_new
int track_num the number of a track
Returns: the length of the specified track
pure nothrow @nogc @trusted char* discid_get_mcn(scope DiscId* d);
Return the Media Catalogue Number (MCN) for the disc.
This is essentially an EAN (= UPC with 0 prefix).
Parameters:
DiscId* d a DiscId object created by discid_new
Returns: a C-string containing the Media Catalogue Number of the disc
pure nothrow @nogc @trusted char* discid_get_track_isrc(scope DiscId* d, int track_num);
Return the ISRC for a track.
Only track numbers between (and including) discid_get_first_track_num and discid_get_last_track_num may be used.
Parameters:
DiscId* d a DiscId object created by discid_new
int track_num the number of a track
Returns: a C-string containing an ISRC for the specified track
enum uint DISCID_FEATURE_READ;
enum uint DISCID_FEATURE_MCN;
enum uint DISCID_FEATURE_ISRC;
PLATFORM-DEPENDENT FEATURES
The platform dependent features are currently:
"read" read TOC from disc
"mcn" read MCN from disc
"isrc" ead ISRC from disc
A table in the MusicBrainz Documentation specifies which features are available on which platform in what version.
In the code you can use discid_get_feature_list or discid_has_feature below to get the features for your platform in this version.
pure nothrow @nogc @trusted int discid_has_feature(uint feature);
Check if a certain feature is implemented on the current platform.
This only works for single features, not bit masks with multiple features.
Parameters:
uint feature One of the DISCID_* enums
Returns: 1 if the feature is implemented and 0 if not.
enum string DISCID_FEATURE_STR_READ;
enum string DISCID_FEATURE_STR_MCN;
enum string DISCID_FEATURE_STR_ISRC;
enum int DISCID_FEATURE_LENGTH;
pure nothrow @nogc @trusted void discid_get_feature_list(ref scope char*[DISCID_FEATURE_LENGTH] features);
Return a list of features supported by the current platform. The array of length DISCID_FEATURE_LENGTH should be allocated by the user. After the call each element of the array is either null or a pointer to a static string.
Parameters:
char*[DISCID_FEATURE_LENGTH] features a static string array of length DISCID_FEATURE_LENGTH
pure nothrow @nogc @trusted char* discid_get_version_string();
Return the full version string of this library, including the name. This can be used for debug output. Don't use this to test for features, see discid_has_feature.
Returns: a C-string containing the version of libdiscid.