diff options
Diffstat (limited to 'Src/external_dependencies/libdiscid-0.6.2/src')
15 files changed, 2883 insertions, 0 deletions
diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/base64.c b/Src/external_dependencies/libdiscid-0.6.2/src/base64.c new file mode 100644 index 00000000..99a13ae6 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/base64.c @@ -0,0 +1,110 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2000 Robert Kaye + + 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 + + $Id$ + +----------------------------------------------------------------------------*/ +/* + * Program: RFC-822 routines (originally from SMTP) + * + * Author: Mark Crispin + * Networks and Distributed Computing + * Computing & Communications + * University of Washington + * Administration Building, AG-44 + * Seattle, WA 98195 + * Internet: MRC@CAC.Washington.EDU + * + * Date: 27 July 1988 + * Last Edited: 10 September 1998 + * + * Sponsorship: The original version of this work was developed in the + * Symbolic Systems Resources Group of the Knowledge Systems + * Laboratory at Stanford University in 1987-88, and was funded + * by the Biomedical Research Technology Program of the National + * Institutes of Health under grant number RR-00785. + * + * Original version Copyright 1988 by The Leland Stanford Junior University + * Copyright 1998 by the University of Washington + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notices appear in all copies and that both the + * above copyright notices and this permission notice appear in supporting + * documentation, and that the name of the University of Washington or The + * Leland Stanford Junior University not be used in advertising or publicity + * pertaining to distribution of the software without specific, written prior + * permission. This software is made available "as is", and + * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY + * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF + * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <ctype.h> +#include <stdio.h> +#include <time.h> +#include <stdlib.h> +#include "base64.h" + +/* NOTE: This is not true RFC822 anymore. The use of the characters + '/', '+', and '=' is no bueno when the ID will be used as part of a URL. + '_', '.', and '-' have been used instead +*/ + +/* Convert binary contents to BASE64 + * Accepts: source + * length of source + * pointer to return destination length + * Returns: destination as BASE64 + */ + +unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len) +{ + unsigned char *ret,*d; + unsigned char *s = (unsigned char *) src; + char *v = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._"; + unsigned long i = ((srcl + 2) / 3) * 4; + *len = i += 2 * ((i / 60) + 1); + d = ret = (unsigned char *) malloc ((size_t) ++i); + for (i = 0; srcl; s += 3) { /* process tuplets */ + *d++ = v[s[0] >> 2]; /* byte 1: high 6 bits (1) */ + /* byte 2: low 2 bits (1), high 4 bits (2) */ + *d++ = v[((s[0] << 4) + (--srcl ? (s[1] >> 4) : 0)) & 0x3f]; + /* byte 3: low 4 bits (2), high 2 bits (3) */ + *d++ = srcl ? v[((s[1] << 2) + (--srcl ? (s[2] >> 6) : 0)) & 0x3f] : '-'; + /* byte 4: low 6 bits (3) */ + *d++ = srcl ? v[s[2] & 0x3f] : '-'; + if (srcl) srcl--; /* count third character if processed */ + if ((++i) == 15) { /* output 60 characters? */ + i = 0; /* restart line break count, insert CRLF */ + *d++ = '\015'; *d++ = '\012'; + } + } + *d = '\0'; /* tie off string */ + + return ret; /* return the resulting string */ +} diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/base64.h b/Src/external_dependencies/libdiscid-0.6.2/src/base64.h new file mode 100644 index 00000000..d22e43e1 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/base64.h @@ -0,0 +1,74 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2000 Robert Kaye + + 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 + + $Id$ + +----------------------------------------------------------------------------*/ +/* + * Program: RFC-822 routines (originally from SMTP) + * + * Author: Mark Crispin + * Networks and Distributed Computing + * Computing & Communications + * University of Washington + * Administration Building, AG-44 + * Seattle, WA 98195 + * Internet: MRC@CAC.Washington.EDU + * + * Date: 27 July 1988 + * Last Edited: 10 September 1998 + * + * Sponsorship: The original version of this work was developed in the + * Symbolic Systems Resources Group of the Knowledge Systems + * Laboratory at Stanford University in 1987-88, and was funded + * by the Biomedical Research Technology Program of the National + * Institutes of Health under grant number RR-00785. + * + * Original version Copyright 1988 by The Leland Stanford Junior University + * Copyright 1998 by the University of Washington + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notices appear in all copies and that both the + * above copyright notices and this permission notice appear in supporting + * documentation, and that the name of the University of Washington or The + * Leland Stanford Junior University not be used in advertising or publicity + * pertaining to distribution of the software without specific, written prior + * permission. This software is made available "as is", and + * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY + * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF + * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef BASE64_H +#define BASE64_H + +#include "discid/discid.h" /* for LIBDISCID_INTERNAL */ + +LIBDISCID_INTERNAL unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len); + +#endif diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/disc.c b/Src/external_dependencies/libdiscid-0.6.2/src/disc.c new file mode 100644 index 00000000..391b7cff --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/disc.c @@ -0,0 +1,508 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2006 Matthias Friedrich + Copyright (C) 2000 Robert Kaye + Copyright (C) 1999 Marc E E van Woerkom + + 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 + +--------------------------------------------------------------------------- */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <string.h> +#include <assert.h> +#include <limits.h> + +#include "sha1.h" +#include "base64.h" + +#include "discid/discid.h" +#include "discid/discid_private.h" + + +#define TRACK_NUM_IS_VALID(disc, i) \ + ( i >= disc->first_track_num && i <= disc->last_track_num ) + + +static void create_disc_id(mb_disc_private *d, char buf[]); +static void create_freedb_disc_id(mb_disc_private *d, char buf[]); +static char *create_toc_string(mb_disc_private *d, char *sep); +static void create_submission_url(mb_disc_private *d, char buf[]); +static void create_webservice_url(mb_disc_private *d, char buf[]); + + +/**************************************************************************** + * + * Implementation of the public interface. + * + ****************************************************************************/ + +DiscId *discid_new() { + /* initializes everything to zero */ + return calloc(1, sizeof(mb_disc_private)); +} + + +void discid_free(DiscId *d) { + free(d); +} + + +char *discid_get_error_msg(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + + return disc->error_msg; +} + + +char *discid_get_id(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return NULL; + + if (strlen(disc->id) == 0) + create_disc_id(disc, disc->id); + + return disc->id; +} + + +char *discid_get_freedb_id(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return NULL; + + if (strlen(disc->freedb_id) == 0) + create_freedb_disc_id(disc, disc->freedb_id); + + return disc->freedb_id; +} + +char *discid_get_toc_string(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert( disc != NULL ); + assert( disc->success ); + + if ( ! disc->success ) + return NULL; + + if ( strlen(disc->toc_string) == 0 ) { + char *toc = create_toc_string(disc, " "); + if (toc) { + memcpy(disc->toc_string, toc, strlen(toc) + 1); + free(toc); + } + } + + return disc->toc_string; +} + +char *discid_get_submission_url(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return NULL; + + if (strlen(disc->submission_url) == 0) + create_submission_url(disc, disc->submission_url); + + return disc->submission_url; +} + +char *discid_get_webservice_url(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return NULL; + + if (strlen(disc->webservice_url) == 0) + create_webservice_url(disc, disc->webservice_url); + + return disc->webservice_url; +} + +int discid_read(DiscId *d, const char *device) { + return discid_read_sparse(d, device, UINT_MAX); +} + +int discid_read_sparse(DiscId *d, const char *device, unsigned int features) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + + if (device == NULL) + device = discid_get_default_device(); + + assert(device != NULL); + + /* Necessary, because the disc handle could have been used before. */ + memset(disc, 0, sizeof(mb_disc_private)); + + /* pre-read the TOC to reduce "not-ready" problems + * See LIB-44 (issues with multi-session discs) + */ + if (!mb_disc_read_unportable(disc, device, DISCID_FEATURE_READ)) { + return 0; + } + memset(disc, 0, sizeof(mb_disc_private)); + + return disc->success = mb_disc_read_unportable(disc, device, features); +} + +int discid_put(DiscId *d, int first, int last, int *offsets) { + int i, disc_length; + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + + /* Necessary, because the disc handle could have been used before. */ + memset(disc, 0, sizeof(mb_disc_private)); + + /* extensive checking of given parameters */ + if (first > last || first < 1 + || first > 99 || last < 1 || last > 99) { + + sprintf(disc->error_msg, "Illegal track limits"); + return 0; + } + if (offsets == NULL) { + sprintf(disc->error_msg, "No offsets given"); + return 0; + } + disc_length = offsets[0]; + if (disc_length > MAX_DISC_LENGTH) { + sprintf(disc->error_msg, "Disc too long"); + return 0; + } + for (i = 0; i <= last; i++) { + if (offsets[i] > disc_length) { + sprintf(disc->error_msg, "Invalid offset"); + return 0; + } + if (i > 1 && offsets[i-1] > offsets[i]) { + sprintf(disc->error_msg, "Invalid order"); + return 0; + } + } + + disc->first_track_num = first; + disc->last_track_num = last; + + memcpy(disc->track_offsets, offsets, sizeof(int) * (last+1)); + + disc->success = 1; + + return 1; +} + + +char *discid_get_default_device(void) { + return mb_disc_get_default_device_unportable(); +} + +int discid_get_first_track_num(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return -1; + else + return disc->first_track_num; +} + + +int discid_get_last_track_num(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return -1; + else + return disc->last_track_num; +} + + +int discid_get_sectors(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return -1; + else + return disc->track_offsets[0]; +} + + +int discid_get_track_offset(DiscId *d, int i) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + assert(TRACK_NUM_IS_VALID(disc, i)); + + if (!disc->success || !TRACK_NUM_IS_VALID(disc, i)) + return -1; + else + return disc->track_offsets[i]; +} + + +int discid_get_track_length(DiscId *d, int i) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + assert(TRACK_NUM_IS_VALID(disc, i)); + + if (!disc->success || !TRACK_NUM_IS_VALID(disc, i)) + return -1; + else if (i < disc->last_track_num) + return disc->track_offsets[i+1] - disc->track_offsets[i]; + else + return disc->track_offsets[0] - disc->track_offsets[i]; +} + +char *discid_get_mcn(DiscId *d) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + + if (!disc->success) + return NULL; + else + return disc->mcn; +} + +char* discid_get_track_isrc(DiscId *d, int i) { + mb_disc_private *disc = (mb_disc_private *) d; + assert(disc != NULL); + assert(disc->success); + assert(TRACK_NUM_IS_VALID(disc, i)); + + if (!disc->success || i == 0 || !TRACK_NUM_IS_VALID(disc, i)) + return NULL; + else + return disc->isrc[i]; +} + +int discid_has_feature(enum discid_feature feature) { + return mb_disc_has_feature_unportable(feature); +} + +void discid_get_feature_list(char *features[DISCID_FEATURE_LENGTH]) { + int i; + + /* for the code, the parameter is actually only a pointer */ + memset(features, 0, sizeof(char *) * DISCID_FEATURE_LENGTH); + i = 0; + + if (discid_has_feature(DISCID_FEATURE_READ)) { + features[i++] = DISCID_FEATURE_STR_READ; + } + if (discid_has_feature(DISCID_FEATURE_MCN)) { + features[i++] = DISCID_FEATURE_STR_MCN; + } + if (discid_has_feature(DISCID_FEATURE_ISRC)) { + features[i++] = DISCID_FEATURE_STR_ISRC; + } + + return; +} + +char *discid_get_version_string(void) { +#ifdef HAVE_CONFIG_H + return PACKAGE_STRING; +#else + return ""; +#endif +} + + + +/**************************************************************************** + * + * Private utilities, not exported. + * + ****************************************************************************/ + +/* + * Create a DiscID based on the TOC data found in the DiscId object. + * The DiscID is placed in the provided string buffer. + */ +static void create_disc_id(mb_disc_private *d, char buf[]) { + SHA_INFO sha; + unsigned char digest[20], *base64; + unsigned long size; + char tmp[17]; /* for 8 hex digits (16 to avoid trouble) */ + int i; + + assert(d != NULL); + assert(d->success); + + sha_init(&sha); + + sprintf(tmp, "%02X", d->first_track_num); + sha_update(&sha, (unsigned char *) tmp, strlen(tmp)); + + sprintf(tmp, "%02X", d->last_track_num); + sha_update(&sha, (unsigned char *) tmp, strlen(tmp)); + + for (i = 0; i < 100; i++) { + sprintf(tmp, "%08X", d->track_offsets[i]); + sha_update(&sha, (unsigned char *) tmp, strlen(tmp)); + } + + sha_final(digest, &sha); + + base64 = rfc822_binary(digest, sizeof(digest), &size); + + memcpy(buf, base64, size); + buf[size] = '\0'; + + free(base64); +} + + +/* + * Create a FreeDB DiscID based on the TOC data found in the DiscId object. + * The DiscID is placed in the provided string buffer. + */ +static void create_freedb_disc_id(mb_disc_private *d, char buf[]) { + int i, n, m, t; + + assert(d != NULL); + assert(d->success); + + n = 0; + for (i = 0; i < d->last_track_num; i++) { + m = d->track_offsets[i + 1] / 75; + while (m > 0) { + n += m % 10; + m /= 10; + } + } + t = d->track_offsets[0] / 75 - d->track_offsets[1] / 75; + sprintf(buf, "%08x", ((n % 0xff) << 24 | t << 8 | d->last_track_num)); +} + +/* + * Create a string based on the TOC data found in the mb_disc_private + * object. The returned string is allocated, caller has to free() it. + * On failure, it returns NULL. + * + * Format is: + * [1st track num][sep][last track num][sep][length in sectors][sep][1st track offset][sep]... + */ +static char *create_toc_string(mb_disc_private *d, char *sep) { + char tmp[16]; + char *toc; + int i, size; + + assert( d != NULL ); + + /* number of tracks */ + size = 1 + d->last_track_num - d->first_track_num; + /* first&last track num and total length */ + size += 3; + /* number + separator */ + size *= (6 + strlen(sep)); + /* nul */ + size++; + + toc = calloc(size, sizeof(char)); + if (!toc) return NULL; + + sprintf(toc, "%d%s%d%s%d", + d->first_track_num, + sep, + d->last_track_num, + sep, + d->track_offsets[0]); + + for (i = d->first_track_num; i <= d->last_track_num; i++) { + sprintf(tmp, "%s%d", sep, d->track_offsets[i]); + strcat(toc, tmp); + } + + return toc; +} + +/* Append &toc=... to buf, calling create_toc_string() */ +static void cat_toc_param(mb_disc_private *d, char *buf) { + char *toc = create_toc_string(d, "+"); + if (toc) { + strcat(buf, "&toc="); + strcat(buf, toc); + free(toc); + } +} + +/* + * Create a submission URL based on the TOC data found in the mb_disc_private + * object. The URL is placed in the provided string buffer. + */ +static void create_submission_url(mb_disc_private *d, char buf[]) { + char tmp[16]; + + assert(d != NULL); + assert(d->success); + + strcpy(buf, MB_SUBMISSION_URL); + + strcat(buf, "?id="); + strcat(buf, discid_get_id((DiscId *) d)); + + sprintf(tmp, "&tracks=%d", d->last_track_num); + strcat(buf, tmp); + + cat_toc_param(d, buf); +} + +/* + * Create a web service URL based on the TOC data found in the mb_disc_private + * object. The URL is placed in the provided string buffer. + */ +static void create_webservice_url(mb_disc_private *d, char buf[]) { + assert(d != NULL); + assert(d->success); + + strcpy(buf, MB_WEBSERVICE_URL); + + strcat(buf, "?type=xml&discid="); + strcat(buf, discid_get_id((DiscId *) d)); + + cat_toc_param(d, buf); +} + +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/disc_bsd.c b/Src/external_dependencies/libdiscid-0.6.2/src/disc_bsd.c new file mode 100644 index 00000000..cc749767 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/disc_bsd.c @@ -0,0 +1,194 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2008 Patrick Hurrelmann + Copyright (C) 2006 Matthias Friedrich + Copyright (C) 2000 Robert Kaye + Copyright (C) 1999 Marc E E van Woerkom + + 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 + +--------------------------------------------------------------------------- */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/cdio.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <unistd.h> + +#if defined(__FreeBSD__) +#include <netinet/in.h> /* for ntohl() */ +#else +#include <util.h> /* for getrawpartition() */ +#endif + +#include "discid/discid_private.h" +#include "unix.h" + +#define MAX_DEV_LEN 15 + +static int get_device(int n, char* device_name, size_t device_name_length) { +#if !defined(__FreeBSD__) /* /dev/rcdNX, where X is the letter for the raw partition */ + snprintf(device_name, device_name_length, "/dev/rcd%d%c", n - 1, 'a' + getrawpartition()); +#else /* on FreeBSD it's just /dev/cdN */ + snprintf(device_name, device_name_length, "/dev/cd%d", n - 1); +#endif + return mb_disc_unix_exists(device_name); +} + +int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) { + struct ioc_toc_header th; + struct cd_toc_entry te[100]; + struct ioc_read_toc_entry rte; + int i; + + memset(&th, 0, sizeof th); + if (ioctl(fd, CDIOREADTOCHEADER, &th) < 0) + return 0; /* error */ + + toc->first_track_num = th.starting_track; + toc->last_track_num = th.ending_track; + + if (toc->last_track_num == 0) + return 1; /* no entries to read */ + + /* Read all the TOC entries in one icotl() call */ + + memset(&te, 0, sizeof te); + memset(&rte, 0, sizeof rte); + rte.address_format = CD_LBA_FORMAT; + rte.data = &te[0]; + rte.data_len = sizeof te; + rte.starting_track = toc->first_track_num; + + if (ioctl(fd, CDIOREADTOCENTRYS, &rte) < 0) + return 0; /* error */ + + for (i = toc->first_track_num; i <= toc->last_track_num; ++i) { + assert(te[i - toc->first_track_num].track == i); +#if defined(__FreeBSD__) /* LBA address is in network byte order */ + toc->tracks[i].address = ntohl(te[i - toc->first_track_num].addr.lba); +#else + toc->tracks[i].address = te[i - toc->first_track_num].addr.lba; +#endif + toc->tracks[i].control = te[i - toc->first_track_num].control; + } + /* leadout - track number 170 (0xAA) */ + assert(te[i - toc->first_track_num].track == 0xAA); +#if defined(__FreeBSD__) /* LBA address is in network byte order */ + toc->tracks[0].address = ntohl(te[i - toc->first_track_num].addr.lba); +#else + toc->tracks[0].address = te[i - toc->first_track_num].addr.lba; +#endif + toc->tracks[0].control = te[i - toc->first_track_num].control; + + return 1; +} + +int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) { + /* All TOC entries were already read by mb_disc_unix_read_toc_header() */ + return 1; +} + +void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) { + struct cd_sub_channel_info sci; + struct ioc_read_subchannel rsc; + + memset(&sci, 0, sizeof sci); + memset(&rsc, 0, sizeof rsc); + rsc.address_format = CD_LBA_FORMAT; /* not technically relevant */ + rsc.data_format = CD_MEDIA_CATALOG; + rsc.data_len = sizeof sci; + rsc.data = &sci; + + if ( ioctl(fd, CDIOCREADSUBCHANNEL, &rsc) < 0 ) + perror ("Warning: Unable to read the disc's media catalog number"); + else { + if (sci.what.media_catalog.mc_valid) + strncpy( disc->mcn, + (const char *) sci.what.media_catalog.mc_number, + MCN_STR_LENGTH ); + else + memset( disc->mcn, 0, MCN_STR_LENGTH ); + } +} + +void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) { + struct cd_sub_channel_info sci; + struct ioc_read_subchannel rsc; + + memset(&sci, 0, sizeof sci); + memset(&rsc, 0, sizeof rsc); + rsc.address_format = CD_LBA_FORMAT; /* not technically relevant */ + rsc.data_format = CD_TRACK_INFO; + rsc.track = track_num; + rsc.data_len = sizeof sci; + rsc.data = &sci; + + if ( ioctl(fd, CDIOCREADSUBCHANNEL, &rsc) < 0 ) + perror ("Warning: Unable to read track info (ISRC)"); + else { + if (sci.what.track_info.ti_valid) + strncpy( disc->isrc[track_num], + (const char *) sci.what.track_info.ti_number, + ISRC_STR_LENGTH ); + else + memset( disc->isrc[track_num], 0, ISRC_STR_LENGTH ); + } +} + +int mb_disc_has_feature_unportable(enum discid_feature feature) { + switch(feature) { + case DISCID_FEATURE_READ: + case DISCID_FEATURE_MCN: + case DISCID_FEATURE_ISRC: + return 1; + default: + return 0; + } +} + +int mb_disc_read_unportable(mb_disc_private *disc, const char *device, + unsigned int features) { + char device_name[MAX_DEV_LEN] = ""; + int device_number; + + device_number = (int) strtol(device, NULL, 10); + + if (device_number > 0) { + if(!get_device(device_number, device_name, MAX_DEV_LEN)) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot find cd device with the number '%d'", + device_number); + return 0; /* error */ + } + device = device_name; + } + + return mb_disc_unix_read(disc, device, features); +} + +char *mb_disc_get_default_device_unportable(void) { + static char result[MAX_DEV_LEN + 1]; + /* No error check here, so we always return the appropriate device for cd0 */ + get_device(1, result, sizeof result); + return result; +} + +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/disc_darwin.c b/Src/external_dependencies/libdiscid-0.6.2/src/disc_darwin.c new file mode 100644 index 00000000..c0cc553a --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/disc_darwin.c @@ -0,0 +1,242 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2013 Johannes Dewender + Copyright (C) 2006 Robert Kaye + Copyright (C) 1999 Marc E E van Woerkom + + 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 + +----------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <paths.h> +#include <sys/ioctl.h> +#include <sys/param.h> + +#include <CoreFoundation/CoreFoundation.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/IOBSD.h> +#include <IOKit/storage/IOCDBlockStorageDevice.h> +#include <IOKit/storage/IOCDMediaBSDClient.h> + +#include "discid/discid.h" +#include "discid/discid_private.h" +#include "unix.h" + +#define MB_DEFAULT_DEVICE "1" /* first disc drive (empty or not) */ +#define TOC_BUFFER_LEN 2048 + + +static int find_cd_block_devices(io_iterator_t *device_iterator) +{ + mach_port_t master_port; + CFMutableDictionaryRef matching_dictionary; + + if (IOMasterPort(MACH_PORT_NULL, &master_port) != KERN_SUCCESS) + return 0; + + matching_dictionary = IOServiceMatching(kIOCDBlockStorageDeviceClass); + + if (IOServiceGetMatchingServices(master_port, matching_dictionary, + device_iterator) != KERN_SUCCESS) + return 0; + else + return 1; +} + +static int get_device_from_entry(io_registry_entry_t entry, + char *device_path, int max_len) +{ + int return_value = 0; + size_t dev_path_len;; + CFStringRef cf_device_name;; + *device_path = '\0'; + + cf_device_name = IORegistryEntrySearchCFProperty(entry, + kIOServicePlane, CFSTR(kIOBSDNameKey), + kCFAllocatorDefault, kIORegistryIterateRecursively); + + if (cf_device_name) { + strcpy(device_path, _PATH_DEV); + /* Add "r" before the device name to use the raw disk node + * without the buffering cache. */ + strcat(device_path, "r"); + dev_path_len = strlen(device_path); + if (CFStringGetCString(cf_device_name, + device_path + dev_path_len, + max_len - dev_path_len - 1, + kCFStringEncodingASCII)) + return_value = 1; + + CFRelease(cf_device_name); + } + return return_value; +} + +static int get_device_from_number(int device_number, + char * buffer, int buffer_len) { + int return_value = 0; + int index = 0; + io_iterator_t device_iterator; + io_object_t device_object = IO_OBJECT_NULL; + + if (!find_cd_block_devices(&device_iterator)) + return 0; + + while (index < device_number + && (device_object = IOIteratorNext(device_iterator))) + index++; + + if (index != device_number) { + return_value = 0; + } else { + return_value = get_device_from_entry(device_object, + buffer, buffer_len); + } + + IOObjectRelease(device_object); + IOObjectRelease(device_iterator); + + return return_value; +} + +void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) +{ + dk_cd_read_mcn_t cd_read_mcn; + bzero(&cd_read_mcn, sizeof(cd_read_mcn)); + + if(ioctl(fd, DKIOCCDREADMCN, &cd_read_mcn) == -1) { + fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n"); + } else { + strncpy( disc->mcn, cd_read_mcn.mcn, MCN_STR_LENGTH ); + } +} + +void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track) +{ + dk_cd_read_isrc_t cd_read_isrc; + bzero(&cd_read_isrc, sizeof(cd_read_isrc)); + cd_read_isrc.track = track; + + if(ioctl(fd, DKIOCCDREADISRC, &cd_read_isrc) == -1) { + fprintf(stderr, "Warning: Unable to read the international standard recording code (ISRC) for track %i\n", track); + return; + } else { + strncpy( disc->isrc[track], cd_read_isrc.isrc, ISRC_STR_LENGTH ); + } +} + +int mb_disc_has_feature_unportable(enum discid_feature feature) { + switch(feature) { + case DISCID_FEATURE_READ: + case DISCID_FEATURE_MCN: + case DISCID_FEATURE_ISRC: + return 1; + default: + return 0; + } +} + +char *mb_disc_get_default_device_unportable(void) +{ + return MB_DEFAULT_DEVICE; +} + +int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *mb_toc) { + dk_cd_read_toc_t toc; + CDTOC *cdToc; + mb_disc_toc_track *track; + int i, numDesc; + int track_num, min_track, max_track; + + memset(&toc, 0, sizeof(toc)); + toc.format = kCDTOCFormatTOC; + toc.formatAsTime = 0; + toc.buffer = (char *)malloc(TOC_BUFFER_LEN); + toc.bufferLength = TOC_BUFFER_LEN; + if (ioctl(fd, DKIOCCDREADTOC, &toc) < 0) { + return 0; + } + if (toc.bufferLength < sizeof(CDTOC)) { + return 0; + } + + cdToc = (CDTOC *)toc.buffer; + numDesc = CDTOCGetDescriptorCount(cdToc); + min_track = -1; + max_track = -1; + for(i = 0; i < numDesc; i++) { + CDTOCDescriptor *desc = &cdToc->descriptors[i]; + track = NULL; + + /* A2 is the code for the lead-out position in the lead-in */ + if (desc->point == 0xA2 && desc->adr == 1) { + track = &mb_toc->tracks[0]; + } + + /* actual track data, (adr 2-3 are for MCN and ISRC data) */ + if (desc->point <= 99 && desc->adr == 1) { + track_num = desc->point; + track = &mb_toc->tracks[track_num]; + if (min_track < 0 || min_track > track_num) { + min_track = track_num; + } + if (max_track < track_num) { + max_track = track_num; + } + } + + if (track) { + track->address = CDConvertMSFToLBA(desc->p); + track->control = desc->control; + } + } + + mb_toc->first_track_num = min_track; + mb_toc->last_track_num = max_track; + + free(toc.buffer); + + return 1; +} + +int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *toc) { + /* On Darwin the tracks are already filled along with the header */ + return 1; +} + +int mb_disc_read_unportable(mb_disc_private *disc, const char *device, + unsigned int features) { + int device_number; + char device_name[MAXPATHLEN] = "\0"; + + device_number = (int) strtol(device, NULL, 10); + if (device_number > 0) { + if (!get_device_from_number(device_number, + device_name, MAXPATHLEN)) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "no disc in drive number: %d", device_number); + return 0; + } else { + return mb_disc_unix_read(disc, device_name, features); + } + } else { + return mb_disc_unix_read(disc, device, features); + } +} diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/disc_generic.c b/Src/external_dependencies/libdiscid-0.6.2/src/disc_generic.c new file mode 100644 index 00000000..58c31673 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/disc_generic.c @@ -0,0 +1,43 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2013 Johannes Dewender + + 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 + +--------------------------------------------------------------------------- */ +#include <stdio.h> + +#include "discid/discid.h" +#include "discid/discid_private.h" + + +char *mb_disc_get_default_device_unportable(void) { + return "/dev/null"; +} + + +int mb_disc_has_feature_unportable(enum discid_feature feature) { + return 0; +} + +int mb_disc_read_unportable(mb_disc_private *disc, const char *device, unsigned int features) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "disc reading not implemented on this platform"); + return 0; +} + +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/disc_linux.c b/Src/external_dependencies/libdiscid-0.6.2/src/disc_linux.c new file mode 100644 index 00000000..2749bc07 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/disc_linux.c @@ -0,0 +1,275 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2013 Johannes Dewender + Copyright (C) 2006 Matthias Friedrich + Copyright (C) 2000 Robert Kaye + Copyright (C) 1999 Marc E E van Woerkom + + 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 + +--------------------------------------------------------------------------- */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <assert.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/cdrom.h> +#include <scsi/sg.h> + + +#include "discid/discid.h" +#include "discid/discid_private.h" +#include "unix.h" + + +/* timeout better shouldn't happen for scsi commands -> device is reset */ +#define DEFAULT_TIMEOUT 30000 /* in ms */ + +#ifndef SG_MAX_SENSE +#define SG_MAX_SENSE 16 +#endif + +#define MB_DEFAULT_DEVICE "/dev/cdrom" +#define MAX_DEV_LEN 50 + +#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) +# define THREAD_LOCAL __thread +#else +# define THREAD_LOCAL +#endif + +static THREAD_LOCAL char default_device[MAX_DEV_LEN] = ""; + + +static int get_device(int number, char *device, int device_len) { + FILE *proc_file; + char *current_device; + char *lineptr = NULL; + char *saveptr = NULL; + size_t bufflen; + int i, count, counter; + int return_value = 0; + + proc_file = fopen("/proc/sys/dev/cdrom/info", "r"); + if (proc_file != NULL) { + /* skip to line containing device names */ + do { + if (getline(&lineptr, &bufflen, proc_file) < 0) { + return 0; + } + } while (strstr(lineptr, "drive name:") == NULL); + + /* count number of devices = number of tabs - 1*/ + count = -1; + for (i = 0; i < strlen(lineptr); i++) { + if (lineptr[i] == '\t') count++; + } + + /* go through devices, they are in reverse order */ + current_device = strtok_r(lineptr, "\t", &saveptr); + /* skip column title */ + current_device = strtok_r(NULL, "\t", &saveptr); + counter = count; + while (current_device != NULL && counter >= number) { + if (counter == number) { + snprintf(device, device_len, + "/dev/%s", current_device); + return_value = 1; + } + /* go to next in list */ + current_device = strtok_r(NULL, "\t", &saveptr); + counter--; + } + + /* trim the trailing \n for the last entry = first device */ + if (return_value && device[strlen(device)-1] == '\n') { + device[strlen(device)-1] = '\0'; + } + free(lineptr); + fclose(proc_file); + } + return return_value; +} + +int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) { + struct cdrom_tochdr th; + + int ret = ioctl(fd, CDROMREADTOCHDR, &th); + + if ( ret < 0 ) + return 0; /* error */ + + toc->first_track_num = th.cdth_trk0; + toc->last_track_num = th.cdth_trk1; + + return 1; +} + + +int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) { + struct cdrom_tocentry te; + int ret; + + te.cdte_track = track_num; + te.cdte_format = CDROM_LBA; + + ret = ioctl(fd, CDROMREADTOCENTRY, &te); + assert( te.cdte_format == CDROM_LBA ); + + if ( ret < 0 ) + return 0; /* error */ + + track->address = te.cdte_addr.lba; + track->control = te.cdte_ctrl; + + return 1; +} + +char *mb_disc_get_default_device_unportable(void) { + /* prefer the default device symlink to the internal names */ + if (mb_disc_unix_exists(MB_DEFAULT_DEVICE)) { + return MB_DEFAULT_DEVICE; + } else { + if (get_device(1, default_device, MAX_DEV_LEN)) { + return default_device; + } else { + return MB_DEFAULT_DEVICE; + } + } +} + +void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) { + struct cdrom_mcn mcn; + memset(&mcn, 0, sizeof mcn); + + if(ioctl(fd, CDROM_GET_MCN, &mcn) == -1) { + fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n"); + } else { + strncpy( disc->mcn, + (const char *)mcn.medium_catalog_number, + MCN_STR_LENGTH ); + } +} + +/* Send a scsi command and receive data. */ +static int scsi_cmd(int fd, unsigned char *cmd, int cmd_len, + unsigned char *data, int data_len) { + unsigned char sense_buffer[SG_MAX_SENSE]; /* for "error situations" */ + sg_io_hdr_t io_hdr; + + memset(&io_hdr, 0, sizeof io_hdr); + + assert(cmd_len <= 16); + + io_hdr.interface_id = 'S'; /* must always be 'S' (SCSI generic) */ + io_hdr.cmd_len = cmd_len; + io_hdr.cmdp = cmd; + io_hdr.timeout = DEFAULT_TIMEOUT; /* timeout in ms */ + io_hdr.sbp = sense_buffer;/* only used when status is CHECK_CONDITION */ + io_hdr.mx_sb_len = sizeof sense_buffer; + io_hdr.flags = SG_FLAG_DIRECT_IO; + + io_hdr.dxferp = (void*)data; + io_hdr.dxfer_len = data_len; + io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; + + if (ioctl(fd, SG_IO, &io_hdr) != 0) { + return errno; + } else { + return io_hdr.status; /* 0 = success */ + } +} + +void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) { + int i; + unsigned char cmd[10]; + unsigned char data[24]; + char buffer[ISRC_STR_LENGTH+1]; + + memset(cmd, 0, sizeof cmd); + memset(data, 0, sizeof data); + memset(buffer, 0, sizeof buffer); + + /* data read from the last appropriate sector encountered + * by a current or previous media access operation. + * The Logical Unit accesses the media when there is/was no access. + * TODO: force access at a specific block? -> no duplicate ISRCs? + */ + cmd[0] = 0x42; /* READ SUB-CHANNEL */ + /* cmd[1] reserved / MSF bit (unused) */ + cmd[2] = 1 << 6; /* 6th bit set (SUBQ) -> get sub-channel data */ + cmd[3] = 0x03; /* get ISRC (ADR 3, Q sub-channel Mode-3) */ + /* 4+5 reserved */ + cmd[6] = track_num; + /* cmd[7] = upper byte of the transfer length */ + cmd[8] = sizeof data; /* transfer length in bytes (4 header, 20 data)*/ + /* cmd[9] = control byte */ + + if (scsi_cmd(fd, cmd, sizeof cmd, data, sizeof data) != 0) { + fprintf(stderr, "Warning: Cannot get ISRC code for track %d\n", + track_num); + return; + } + + /* data[1:4] = sub-q channel data header (audio status, data length) */ + if (data[8] & (1 << 7)) { /* TCVAL is set -> ISRCs valid */ + for (i = 0; i < ISRC_STR_LENGTH; i++) { + buffer[i] = data[9 + i]; + } + buffer[ISRC_STR_LENGTH] = 0; + strncpy(disc->isrc[track_num], buffer, ISRC_STR_LENGTH); + } + /* data[21:23] = zero, AFRAME, reserved */ +} + +int mb_disc_has_feature_unportable(enum discid_feature feature) { + switch(feature) { + case DISCID_FEATURE_READ: + case DISCID_FEATURE_MCN: + case DISCID_FEATURE_ISRC: + return 1; + default: + return 0; + } +} + +int mb_disc_read_unportable(mb_disc_private *disc, const char *device, + unsigned int features) { + char device_name[MAX_DEV_LEN] = ""; + int device_number; + + device_number = (int) strtol(device, NULL, 10); + if (device_number > 0) { + if(!get_device(device_number, device_name, MAX_DEV_LEN)) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot find cd device with the number '%d'", + device_number); + return 0; + } else { + return mb_disc_unix_read(disc, device_name, features); + } + } else { + return mb_disc_unix_read(disc, device, features); + } +} + +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/disc_solaris.c b/Src/external_dependencies/libdiscid-0.6.2/src/disc_solaris.c new file mode 100644 index 00000000..7d74dcdb --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/disc_solaris.c @@ -0,0 +1,108 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2009 Shunsuke Kuroda + Copyright (C) 2006 Matthias Friedrich + Copyright (C) 2000 Robert Kaye + Copyright (C) 1999 Marc E E van Woerkom + + 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 + +--------------------------------------------------------------------------- */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <assert.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/cdio.h> + + +#include "discid/discid.h" +#include "discid/discid_private.h" +#include "unix.h" + +#define NUM_CANDIDATES 2 + +static char *device_candidates[NUM_CANDIDATES] = {"/vol/dev/aliases/cdrom0", + "/volumes/dev/aliases/cdrom0"}; + +int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) { + struct cdrom_tochdr th; + + int ret = ioctl(fd, CDROMREADTOCHDR, &th); + + if ( ret < 0 ) + return ret; /* error */ + + toc->first_track_num = th.cdth_trk0; + toc->last_track_num = th.cdth_trk1; + + return ret; +} + + +int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) { + struct cdrom_tocentry te; + int ret; + + memset(&te, 0, sizeof te); + te.cdte_track = track_num; + te.cdte_format = CDROM_LBA; + + ret = ioctl(fd, CDROMREADTOCENTRY, &te); + + if ( ret < 0 ) + return 0; /* error */ + + assert( te.cdte_format == CDROM_LBA ); + track->address = te.cdte_addr.lba; + track->control = te.cdte_ctrl; + + return 1; +} + +void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) { + return; +} + +void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) { + return; +} + +char *mb_disc_get_default_device_unportable(void) { + return mb_disc_unix_find_device(device_candidates, NUM_CANDIDATES); +} + +int mb_disc_has_feature_unportable(enum discid_feature feature) { + switch(feature) { + case DISCID_FEATURE_READ: + return 1; + default: + return 0; + } +} + +int mb_disc_read_unportable(mb_disc_private *disc, const char *device, + unsigned int features) { + return mb_disc_unix_read(disc, device, features); +} + +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/disc_win32.c b/Src/external_dependencies/libdiscid-0.6.2/src/disc_win32.c new file mode 100644 index 00000000..df9409d6 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/disc_win32.c @@ -0,0 +1,247 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2007-2008 Lukas Lalinsky + + 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 + +----------------------------------------------------------------------------*/ + +#ifdef _MSC_VER + #define _CRT_SECURE_NO_WARNINGS + #if (_MSC_VER < 1900) + #define snprintf _snprintf + #endif +#endif + +#include <windows.h> +#include <string.h> +#include <stdio.h> + +#if defined(__CYGWIN__) +#include <ntddcdrm.h> +#elif defined(__MINGW32__) +#include <ddk/ntddcdrm.h> +#else +#include "ntddcdrm.h" +#endif + +#include "discid/discid.h" +#include "discid/discid_private.h" + + +#define MB_DEFAULT_DEVICE "D:" +#define MAX_DEV_LEN 3 + +#if defined(_MSC_VER) +# define THREAD_LOCAL __declspec(thread) +#elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) +# define THREAD_LOCAL __thread +#else +# define THREAD_LOCAL +#endif + +static THREAD_LOCAL char default_device[MAX_DEV_LEN] = "\0"; + +static int address_to_sectors(UCHAR address[4]) { + return address[1] * 4500 + address[2] * 75 + address[3]; +} + +static HANDLE create_device_handle(mb_disc_private *disc, const char *device) { + HANDLE hDevice; + char filename[128]; + const char* colon; + size_t len; + + strcpy(filename, "\\\\.\\"); + len = strlen(device); + colon = strchr(device, ':'); + if (colon) { + len = colon - device + 1; + } + strncat(filename, device, len > 120 ? 120 : len); + + hDevice = CreateFile(filename, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot open the CD audio device '%s'", device); + return 0; + } + + return hDevice; +} + +static void read_disc_mcn(HANDLE hDevice, mb_disc_private *disc) { + DWORD dwReturned; + BOOL bResult; + CDROM_SUB_Q_DATA_FORMAT format; + SUB_Q_CHANNEL_DATA data; + + format.Track = 0; + format.Format = IOCTL_CDROM_MEDIA_CATALOG; + bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_Q_CHANNEL, + &format, sizeof(format), + &data, sizeof(data), + &dwReturned, NULL); + if (bResult == FALSE) { + fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n"); + } else { + strncpy(disc->mcn, (char *) data.MediaCatalog.MediaCatalog, + MCN_STR_LENGTH); + } +} + +static void read_disc_isrc(HANDLE hDevice, mb_disc_private *disc, int track) { + DWORD dwReturned; + BOOL bResult; + CDROM_SUB_Q_DATA_FORMAT format; + SUB_Q_CHANNEL_DATA data; + + format.Track = track; + format.Format = IOCTL_CDROM_TRACK_ISRC; + bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_Q_CHANNEL, + &format, sizeof(format), + &data, sizeof(data), + &dwReturned, NULL); + if (bResult == FALSE) { + fprintf(stderr, "Warning: Unable to read the international standard recording code (ISRC) for track %i\n", track); + } else { + strncpy(disc->isrc[track], (char *) data.TrackIsrc.TrackIsrc, + ISRC_STR_LENGTH); + } +} + +static int get_nth_device(int number, char* device, int device_length) { + int i, counter = 0; + char tmpDevice[MAX_DEV_LEN]; + DWORD mask = GetLogicalDrives(); + + for (i = 0; i <= 25; i++) { + if (mask >> i & 1) { + snprintf(tmpDevice, MAX_DEV_LEN, "%c:", i + 'A'); + if (GetDriveType(tmpDevice) == DRIVE_CDROM) { + counter++; + if (counter == number) { + strncpy(device, tmpDevice, device_length); + return TRUE; + } + } + } + } + + return FALSE; +} + +char *mb_disc_get_default_device_unportable(void) { + if (!get_nth_device(1, default_device, MAX_DEV_LEN)) { + return MB_DEFAULT_DEVICE; + } + + return default_device; +} + +int mb_disc_has_feature_unportable(enum discid_feature feature) { + switch(feature) { + case DISCID_FEATURE_READ: + case DISCID_FEATURE_MCN: + case DISCID_FEATURE_ISRC: + return 1; + default: + return 0; + } +} + +static int mb_disc_winnt_read_toc(HANDLE device, mb_disc_private *disc, mb_disc_toc *toc) { + DWORD dwReturned; + BOOL bResult; + CDROM_TOC cd; + int i; + + bResult = DeviceIoControl(device, IOCTL_CDROM_READ_TOC, + NULL, 0, + &cd, sizeof(cd), + &dwReturned, NULL); + if (bResult == FALSE) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "error while reading the CD TOC"); + return 0; + } + + toc->first_track_num = cd.FirstTrack; + toc->last_track_num = cd.LastTrack; + + /* Get info about all tracks */ + for (i = toc->first_track_num; i <= toc->last_track_num; i++) { + toc->tracks[i].address = address_to_sectors(cd.TrackData[i - 1].Address) - 150; + toc->tracks[i].control = cd.TrackData[i - 1].Control; + } + + /* Lead-out is stored after the last track */ + toc->tracks[0].address = address_to_sectors(cd.TrackData[toc->last_track_num].Address) - 150; + toc->tracks[0].control = cd.TrackData[toc->last_track_num].Control; + + return 1; +} + +int mb_disc_read_unportable(mb_disc_private *disc, const char *device, + unsigned int features) { + mb_disc_toc toc; + char tmpDevice[MAX_DEV_LEN]; + HANDLE hDevice; + int i, device_number; + + device_number = (int) strtol(device, NULL, 10); + + if (device_number > 0) { + if (!get_nth_device(device_number, tmpDevice, MAX_DEV_LEN)) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot find the CD audio device '%i'", device_number); + return 0; + } + device = tmpDevice; + } + + hDevice = create_device_handle(disc, device); + if (hDevice == 0) + return 0; + + if (!mb_disc_winnt_read_toc(hDevice, disc, &toc)) { + CloseHandle(hDevice); + return 0; + } + + if (!mb_disc_load_toc(disc, &toc)) { + CloseHandle(hDevice); + return 0; + } + + if (features & DISCID_FEATURE_MCN) { + read_disc_mcn(hDevice, disc); + } + + for (i = disc->first_track_num; i <= disc->last_track_num; i++) { + if (features & DISCID_FEATURE_ISRC) { + read_disc_isrc(hDevice, disc, i); + } + } + + CloseHandle(hDevice); + return 1; +} + +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/ntddcdrm.h b/Src/external_dependencies/libdiscid-0.6.2/src/ntddcdrm.h new file mode 100644 index 00000000..defb5bd9 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/ntddcdrm.h @@ -0,0 +1,320 @@ +/* + * ntddcdrm.h + * + * CDROM IOCTL interface. + * + * This file is part of the w32api package. + * + * Contributors: + * Created by Casper S. Hornstrup <chorns@users.sourceforge.net> + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __NTDDCDRM_H +#define __NTDDCDRM_H + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push,4) + +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM + +#define IOCTL_CDROM_CHECK_VERIFY \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_FIND_NEW_DEVICES \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_CONTROL \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_LAST_SESSION \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_VOLUME \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_PAUSE_AUDIO \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_PLAY_AUDIO_MSF \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_RAW_READ \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) + +#define IOCTL_CDROM_READ_Q_CHANNEL \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_READ_TOC \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_READ_TOC_EX \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_RESUME_AUDIO \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_SEEK_AUDIO_MSF \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_SET_VOLUME \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_SIMBAD \ + CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_STOP_AUDIO \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS) + + +#define MAXIMUM_NUMBER_TRACKS 100 +#define MAXIMUM_CDROM_SIZE 804 +#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2 + +typedef struct _TRACK_DATA { + UCHAR Reserved; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TrackNumber; + UCHAR Reserved1; + UCHAR Address[4]; +} TRACK_DATA, *PTRACK_DATA; + +/* CDROM_DISK_DATA.DiskData flags */ +#define CDROM_DISK_AUDIO_TRACK 0x00000001 +#define CDROM_DISK_DATA_TRACK 0x00000002 + +typedef struct _CDROM_DISK_DATA { + ULONG DiskData; +} CDROM_DISK_DATA, *PCDROM_DISK_DATA; + +typedef struct _CDROM_PLAY_AUDIO_MSF { + UCHAR StartingM; + UCHAR StartingS; + UCHAR StartingF; + UCHAR EndingM; + UCHAR EndingS; + UCHAR EndingF; +} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF; + +/* CDROM_READ_TOC_EX.Format constants */ +#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00 +#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01 +#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02 +#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03 +#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04 +#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05 + +typedef struct _CDROM_READ_TOC_EX { + UCHAR Format : 4; + UCHAR Reserved1 : 3; + UCHAR Msf : 1; + UCHAR SessionTrack; + UCHAR Reserved2; + UCHAR Reserved3; +} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX; + +typedef struct _CDROM_SEEK_AUDIO_MSF { + UCHAR M; + UCHAR S; + UCHAR F; +} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; + +/* CDROM_SUB_Q_DATA_FORMAT.Format constants */ +#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 +#define IOCTL_CDROM_CURRENT_POSITION 0x01 +#define IOCTL_CDROM_MEDIA_CATALOG 0x02 +#define IOCTL_CDROM_TRACK_ISRC 0x03 + +typedef struct _CDROM_SUB_Q_DATA_FORMAT { + UCHAR Format; + UCHAR Track; +} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; + +typedef struct _CDROM_TOC { + UCHAR Length[2]; + UCHAR FirstTrack; + UCHAR LastTrack; + TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; +} CDROM_TOC, *PCDROM_TOC; + +#define CDROM_TOC_SIZE sizeof(CDROM_TOC) + +typedef struct _CDROM_TOC_ATIP_DATA_BLOCK { + UCHAR CdrwReferenceSpeed : 3; + UCHAR Reserved3 : 1; + UCHAR WritePower : 3; + UCHAR True1 : 1; + UCHAR Reserved4 : 6; + UCHAR UnrestrictedUse : 1; + UCHAR Reserved5 : 1; + UCHAR A3Valid : 1; + UCHAR A2Valid : 1; + UCHAR A1Valid : 1; + UCHAR Reserved6 : 3; + UCHAR IsCdrw : 1; + UCHAR True2 : 1; + UCHAR Reserved7; + UCHAR LeadInMsf[3]; + UCHAR Reserved8; + UCHAR LeadOutMsf[3]; + UCHAR Reserved9; + UCHAR A1Values[3]; + UCHAR Reserved10; + UCHAR A2Values[3]; + UCHAR Reserved11; + UCHAR A3Values[3]; + UCHAR Reserved12; +} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK; + +/* CDROM_TOC_CD_TEXT_DATA_BLOCK.PackType constants */ +#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80 +#define CDROM_CD_TEXT_PACK_PERFORMER 0x81 +#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82 +#define CDROM_CD_TEXT_PACK_COMPOSER 0x83 +#define CDROM_CD_TEXT_PACK_ARRANGER 0x84 +#define CDROM_CD_TEXT_PACK_MESSAGES 0x85 +#define CDROM_CD_TEXT_PACK_DISC_ID 0x86 +#define CDROM_CD_TEXT_PACK_GENRE 0x87 +#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88 +#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89 +#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e +#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f + +typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK { + UCHAR PackType; + UCHAR TrackNumber : 7; + UCHAR ExtensionFlag : 1; + UCHAR SequenceNumber; + UCHAR CharacterPosition : 4; + UCHAR BlockNumber : 3; + UCHAR Unicode : 1; + union { + UCHAR Text[12]; + WCHAR WText[6]; + }; + UCHAR CRC[2]; +} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK; + +/* CDROM_TOC_FULL_TOC_DATA_BLOCK.Adr constants */ +#define ADR_NO_MODE_INFORMATION 0x0 +#define ADR_ENCODES_CURRENT_POSITION 0x1 +#define ADR_ENCODES_MEDIA_CATALOG 0x2 +#define ADR_ENCODES_ISRC 0x3 + +typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK { + UCHAR SessionNumber; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR Reserved1; + UCHAR Point; + UCHAR MsfExtra[3]; + UCHAR Zero; + UCHAR Msf[3]; +} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK; + +/* SUB_Q_HEADER.AudioStatus constants */ +#define AUDIO_STATUS_NOT_SUPPORTED 0x00 +#define AUDIO_STATUS_IN_PROGRESS 0x11 +#define AUDIO_STATUS_PAUSED 0x12 +#define AUDIO_STATUS_PLAY_COMPLETE 0x13 +#define AUDIO_STATUS_PLAY_ERROR 0x14 +#define AUDIO_STATUS_NO_STATUS 0x15 + +typedef struct _SUB_Q_HEADER { + UCHAR Reserved; + UCHAR AudioStatus; + UCHAR DataLength[2]; +} SUB_Q_HEADER, *PSUB_Q_HEADER; + +typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved[3]; + UCHAR Reserved1 : 7; + UCHAR Mcval :1; + UCHAR MediaCatalog[15]; +} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; + +typedef struct _SUB_Q_TRACK_ISRC { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved0; + UCHAR Track; + UCHAR Reserved1; + UCHAR Reserved2 : 7; + UCHAR Tcval : 1; + UCHAR TrackIsrc[15]; +} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; + +typedef struct _SUB_Q_CURRENT_POSITION { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Control : 4; + UCHAR ADR : 4; + UCHAR TrackNumber; + UCHAR IndexNumber; + UCHAR AbsoluteAddress[4]; + UCHAR TrackRelativeAddress[4]; +} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; + +typedef union _SUB_Q_CHANNEL_DATA { + SUB_Q_CURRENT_POSITION CurrentPosition; + SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; + SUB_Q_TRACK_ISRC TrackIsrc; +} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; + +/* CDROM_AUDIO_CONTROL.LbaFormat constants */ +#define AUDIO_WITH_PREEMPHASIS 0x1 +#define DIGITAL_COPY_PERMITTED 0x2 +#define AUDIO_DATA_TRACK 0x4 +#define TWO_FOUR_CHANNEL_AUDIO 0x8 + +typedef struct _CDROM_AUDIO_CONTROL { + UCHAR LbaFormat; + USHORT LogicalBlocksPerSecond; +} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL; + +typedef struct _VOLUME_CONTROL { + UCHAR PortVolume[4]; +} VOLUME_CONTROL, *PVOLUME_CONTROL; + +typedef enum _TRACK_MODE_TYPE { + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct __RAW_READ_INFO { + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif /* __NTDDCDRM_H */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/sha1.c b/Src/external_dependencies/libdiscid-0.6.2/src/sha1.c new file mode 100644 index 00000000..7e154f8e --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/sha1.c @@ -0,0 +1,329 @@ +/* (PD) 2001 The Bitzi Corporation + * Please see file COPYING or http://bitzi.com/publicdomain + * for more info. + * + * NIST Secure Hash Algorithm + * heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> + * from Peter C. Gutmann's implementation as found in + * Applied Cryptography by Bruce Schneier + * Further modifications to include the "UNRAVEL" stuff, below + * + * This code is in the public domain + * + * $Id$ + */ + +#include <string.h> +#include "sha1.h" + +/* UNRAVEL should be fastest & biggest */ +/* UNROLL_LOOPS should be just as big, but slightly slower */ +/* both undefined should be smallest and slowest */ + +#define UNRAVEL +/* #define UNROLL_LOOPS */ + +/* SHA f()-functions */ + +#define f1(x,y,z) ((x & y) | (~x & z)) +#define f2(x,y,z) (x ^ y ^ z) +#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) +#define f4(x,y,z) (x ^ y ^ z) + +/* SHA constants */ + +#define CONST1 0x5a827999L +#define CONST2 0x6ed9eba1L +#define CONST3 0x8f1bbcdcL +#define CONST4 0xca62c1d6L + +/* truncate to 32 bits -- should be a null op on 32-bit machines */ + +#define T32(x) ((x) & 0xffffffffL) + +/* 32-bit rotate */ + +#define R32(x,n) T32(((x << n) | (x >> (32 - n)))) + +/* the generic case, for when the overall rotation is not unraveled */ + +#define FG(n) \ + T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \ + E = D; D = C; C = R32(B,30); B = A; A = T + +/* specific cases, for when the overall rotation is unraveled */ + +#define FA(n) \ + T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30) + +#define FB(n) \ + E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30) + +#define FC(n) \ + D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30) + +#define FD(n) \ + C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30) + +#define FE(n) \ + B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30) + +#define FT(n) \ + A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30) + +/* do SHA transformation */ + +static void sha_transform(SHA_INFO *sha_info) +{ + int i; + SHA_BYTE *dp; + SHA_LONG T, A, B, C, D, E, W[80], *WP; + + dp = sha_info->data; + +/* +the following makes sure that at least one code block below is +traversed or an error is reported, without the necessity for nested +preprocessor if/else/endif blocks, which are a great pain in the +nether regions of the anatomy... +*/ +#undef SWAP_DONE + +#if (SHA_BYTE_ORDER == 1234) +#define SWAP_DONE + for (i = 0; i < 16; ++i) { + T = *((SHA_LONG *) dp); + dp += 4; + W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | + ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); + } +#endif /* SHA_BYTE_ORDER == 1234 */ + +#if (SHA_BYTE_ORDER == 4321) +#define SWAP_DONE + for (i = 0; i < 16; ++i) { + T = *((SHA_LONG *) dp); + dp += 4; + W[i] = T32(T); + } +#endif /* SHA_BYTE_ORDER == 4321 */ + +#if (SHA_BYTE_ORDER == 12345678) +#define SWAP_DONE + for (i = 0; i < 16; i += 2) { + T = *((SHA_LONG *) dp); + dp += 8; + W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | + ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); + T >>= 32; + W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | + ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); + } +#endif /* SHA_BYTE_ORDER == 12345678 */ + +#if (SHA_BYTE_ORDER == 87654321) +#define SWAP_DONE + for (i = 0; i < 16; i += 2) { + T = *((SHA_LONG *) dp); + dp += 8; + W[i] = T32(T >> 32); + W[i+1] = T32(T); + } +#endif /* SHA_BYTE_ORDER == 87654321 */ + +#ifndef SWAP_DONE +#error Unknown byte order -- you need to add code here +#endif /* SWAP_DONE */ + + for (i = 16; i < 80; ++i) { + W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; +#if (SHA_VERSION == 1) + W[i] = R32(W[i], 1); +#endif /* SHA_VERSION */ + } + A = sha_info->digest[0]; + B = sha_info->digest[1]; + C = sha_info->digest[2]; + D = sha_info->digest[3]; + E = sha_info->digest[4]; + WP = W; +#ifdef UNRAVEL + FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); + FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); + FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); + FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); + FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); + FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); + FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); + FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); + sha_info->digest[0] = T32(sha_info->digest[0] + E); + sha_info->digest[1] = T32(sha_info->digest[1] + T); + sha_info->digest[2] = T32(sha_info->digest[2] + A); + sha_info->digest[3] = T32(sha_info->digest[3] + B); + sha_info->digest[4] = T32(sha_info->digest[4] + C); +#else /* !UNRAVEL */ +#ifdef UNROLL_LOOPS + FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); + FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); + FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); + FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); + FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); + FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); + FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); + FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); +#else /* !UNROLL_LOOPS */ + for (i = 0; i < 20; ++i) { FG(1); } + for (i = 20; i < 40; ++i) { FG(2); } + for (i = 40; i < 60; ++i) { FG(3); } + for (i = 60; i < 80; ++i) { FG(4); } +#endif /* !UNROLL_LOOPS */ + sha_info->digest[0] = T32(sha_info->digest[0] + A); + sha_info->digest[1] = T32(sha_info->digest[1] + B); + sha_info->digest[2] = T32(sha_info->digest[2] + C); + sha_info->digest[3] = T32(sha_info->digest[3] + D); + sha_info->digest[4] = T32(sha_info->digest[4] + E); +#endif /* !UNRAVEL */ +} + +/* initialize the SHA digest */ + +void sha_init(SHA_INFO *sha_info) +{ + sha_info->digest[0] = 0x67452301L; + sha_info->digest[1] = 0xefcdab89L; + sha_info->digest[2] = 0x98badcfeL; + sha_info->digest[3] = 0x10325476L; + sha_info->digest[4] = 0xc3d2e1f0L; + sha_info->count_lo = 0L; + sha_info->count_hi = 0L; + sha_info->local = 0; +} + +/* update the SHA digest */ + +void sha_update(SHA_INFO *sha_info, SHA_BYTE *buffer, size_t count) +{ + size_t i; + SHA_LONG clo; + + clo = T32(sha_info->count_lo + ((SHA_LONG) count << 3)); + if (clo < sha_info->count_lo) { + ++sha_info->count_hi; + } + sha_info->count_lo = clo; + sha_info->count_hi += (SHA_LONG) count >> 29; + if (sha_info->local) { + i = SHA_BLOCKSIZE - sha_info->local; + if (i > count) { + i = count; + } + memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i); + count -= i; + buffer += i; + sha_info->local += i; + if (sha_info->local == SHA_BLOCKSIZE) { + sha_transform(sha_info); + } else { + return; + } + } + while (count >= SHA_BLOCKSIZE) { + memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); + buffer += SHA_BLOCKSIZE; + count -= SHA_BLOCKSIZE; + sha_transform(sha_info); + } + memcpy(sha_info->data, buffer, count); + sha_info->local = count; +} + +/* finish computing the SHA digest */ + +void sha_final(unsigned char digest[20], SHA_INFO *sha_info) +{ + int count; + SHA_LONG lo_bit_count, hi_bit_count; + + lo_bit_count = sha_info->count_lo; + hi_bit_count = sha_info->count_hi; + count = (int) ((lo_bit_count >> 3) & 0x3f); + ((SHA_BYTE *) sha_info->data)[count++] = 0x80; + if (count > SHA_BLOCKSIZE - 8) { + memset(((SHA_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count); + sha_transform(sha_info); + memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8); + } else { + memset(((SHA_BYTE *) sha_info->data) + count, 0, + SHA_BLOCKSIZE - 8 - count); + } + sha_info->data[56] = (unsigned char) ((hi_bit_count >> 24) & 0xff); + sha_info->data[57] = (unsigned char) ((hi_bit_count >> 16) & 0xff); + sha_info->data[58] = (unsigned char) ((hi_bit_count >> 8) & 0xff); + sha_info->data[59] = (unsigned char) ((hi_bit_count >> 0) & 0xff); + sha_info->data[60] = (unsigned char) ((lo_bit_count >> 24) & 0xff); + sha_info->data[61] = (unsigned char) ((lo_bit_count >> 16) & 0xff); + sha_info->data[62] = (unsigned char) ((lo_bit_count >> 8) & 0xff); + sha_info->data[63] = (unsigned char) ((lo_bit_count >> 0) & 0xff); + sha_transform(sha_info); + digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff); + digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff); + digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff); + digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff); + digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff); + digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff); + digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff); + digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff); + digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff); + digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff); + digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff); + digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff); + digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff); + digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff); + digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff); + digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff); + digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff); + digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff); + digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff); + digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff); +} + +/* compute the SHA digest of a FILE stream */ + +#define BLOCK_SIZE 8192 + +void sha_stream(unsigned char digest[20], SHA_INFO *sha_info, FILE *fin) +{ + size_t i; + SHA_BYTE data[BLOCK_SIZE]; + + sha_init(sha_info); + while ((i = fread(data, 1, BLOCK_SIZE, fin)) > 0) { + sha_update(sha_info, data, i); + } + sha_final(digest, sha_info); +} + +/* print a SHA digest */ + +void sha_print(unsigned char digest[20]) +{ + int i, j; + + for (j = 0; j < 5; ++j) { + for (i = 0; i < 4; ++i) { + printf("%02x", *digest++); + } + printf("%c", (j < 4) ? ' ' : '\n'); + } +} + +char *sha_version(void) +{ +#if (SHA_VERSION == 1) + static char *version = "SHA-1"; +#else + static char *version = "SHA"; +#endif + return(version); +} + diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/sha1.h b/Src/external_dependencies/libdiscid-0.6.2/src/sha1.h new file mode 100644 index 00000000..16e563b3 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/sha1.h @@ -0,0 +1,63 @@ +/* NIST Secure Hash Algorithm */ +/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */ +/* from Peter C. Gutmann's implementation as found in */ +/* Applied Cryptography by Bruce Schneier */ +/* This code is in the public domain */ +/* $Id$ */ + +#ifndef SHA_H +#define SHA_H + +#include <stdlib.h> +#include <stdio.h> +#include "discid/discid.h" /* for LIBDISCID_INTERNAL */ + +/* Useful defines & typedefs */ +typedef unsigned char SHA_BYTE; /* 8-bit quantity */ +typedef unsigned long SHA_LONG; /* 32-or-more-bit quantity */ + +#define SHA_BLOCKSIZE 64 +#define SHA_DIGESTSIZE 20 + +typedef struct { + SHA_LONG digest[5]; /* message digest */ + SHA_LONG count_lo, count_hi; /* 64-bit bit count */ + SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */ + size_t local; /* unprocessed amount in data */ +} SHA_INFO; + +LIBDISCID_INTERNAL void sha_init(SHA_INFO *); +LIBDISCID_INTERNAL void sha_update(SHA_INFO *, SHA_BYTE *, size_t); +LIBDISCID_INTERNAL void sha_final(unsigned char [20], SHA_INFO *); + +LIBDISCID_INTERNAL void sha_stream(unsigned char [20], SHA_INFO *, FILE *); +LIBDISCID_INTERNAL void sha_print(unsigned char [20]); +LIBDISCID_INTERNAL char *sha_version(void); + +#define SHA_VERSION 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" + + +#ifdef WORDS_BIGENDIAN +# if SIZEOF_LONG == 4 +# define SHA_BYTE_ORDER 4321 +# elif SIZEOF_LONG == 8 +# define SHA_BYTE_ORDER 87654321 +# endif +#else +# if SIZEOF_LONG == 4 +# define SHA_BYTE_ORDER 1234 +# elif SIZEOF_LONG == 8 +# define SHA_BYTE_ORDER 12345678 +# endif +#endif + +#else + +#define SHA_BYTE_ORDER 1234 + +#endif + +#endif /* SHA_H */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/toc.c b/Src/external_dependencies/libdiscid-0.6.2/src/toc.c new file mode 100644 index 00000000..b1ec59f2 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/toc.c @@ -0,0 +1,116 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2006 Lukas Lalinsky + + 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 + +--------------------------------------------------------------------------- */ + +#ifdef _MSC_VER + #define _CRT_SECURE_NO_WARNINGS + #if (_MSC_VER < 1900) + #define snprintf _snprintf + #endif +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "discid/discid_private.h" + +#define XA_INTERVAL ((60 + 90 + 2) * 75) +#define DATA_TRACK 0x04 + + +int mb_disc_load_toc(mb_disc_private *disc, mb_disc_toc *toc) { + int first_audio_track, last_audio_track, i; + mb_disc_toc_track *track; + + if (toc->first_track_num < 1) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "invalid CD TOC - first track number must be 1 or higher"); + return 0; + } + + if (toc->last_track_num < 1) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "invalid CD TOC - last track number must be 99 or lower"); + return 0; + } + + /* we can't just skip data tracks at the front + * releases are always expected to start with track 1 by MusicBrainz + */ + first_audio_track = toc->first_track_num; + last_audio_track = -1; + /* scan the TOC for audio tracks */ + for (i = toc->first_track_num; i <= toc->last_track_num; i++) { + track = &toc->tracks[i]; + if ( !(track->control & DATA_TRACK) ) { + last_audio_track = i; + } + } + + if (last_audio_track < 0) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "no actual audio tracks on disc: CDROM or DVD?"); + return 0; + } + + disc->first_track_num = first_audio_track; + disc->last_track_num = last_audio_track; + + /* get offsets for all found data tracks */ + for (i = first_audio_track; i <= last_audio_track; i++) { + track = &toc->tracks[i]; + if (track->address > 0) { + disc->track_offsets[i] = track->address + 150; + } else { + /* this seems to happen on "copy-protected" discs */ + disc->track_offsets[i] = 150; + } + } + + /* if the last audio track is not the last track on the CD, + * use the offset of the next data track as the "lead-out" offset */ + if (last_audio_track < toc->last_track_num) { + track = &toc->tracks[last_audio_track + 1]; + disc->track_offsets[0] = track->address - XA_INTERVAL + 150; + } else { + /* use the regular lead-out track */ + track = &toc->tracks[0]; + disc->track_offsets[0] = track->address + 150; + } + + /* as long as the lead-out isn't actually bigger than + * the position of the last track, the last track is invalid. + * This happens on "copy-protected"/invalid discs. + * The track is then neither a valid audio track, nor data track. + */ + while (disc->track_offsets[0] < disc->track_offsets[last_audio_track]) { + disc->last_track_num = --last_audio_track; + disc->track_offsets[last_audio_track + 1] = 0; + track = &toc->tracks[last_audio_track + 1]; + disc->track_offsets[0] = track->address - XA_INTERVAL + 150; + } + + return 1; +} + +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/unix.c b/Src/external_dependencies/libdiscid-0.6.2/src/unix.c new file mode 100644 index 00000000..a91c8e58 --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/unix.c @@ -0,0 +1,151 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2006 Matthias Friedrich + Copyright (C) 2000 Robert Kaye + Copyright (C) 1999 Marc E E van Woerkom + + 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 + +--------------------------------------------------------------------------- */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <assert.h> +#include <errno.h> + +#include "discid/discid_private.h" +#include "unix.h" + + +int mb_disc_unix_exists(const char *device) { + int fd; + fd = open(device, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + /* we only check for existance, access should fail later on */ + if (errno == ENOENT) { + return 0; + } else { + return 1; + } + } else { + close(fd); + return 1; + } +} + +char *mb_disc_unix_find_device(char *candidates[], int num_candidates) { + int i; + + for (i = 0; i < num_candidates; i++) { + if (mb_disc_unix_exists(candidates[i])) { + return candidates[i]; + } + } + /* use the first name for the error message later on */ + return candidates[0]; +} + +int mb_disc_unix_open(mb_disc_private *disc, const char *device) { + int fd; + + fd = open(device, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot open device `%s'", device); + } + /* fd < 0 check needs to be made by caller */ + return fd; +} + +int mb_disc_unix_read_toc(int fd, mb_disc_private *disc, mb_disc_toc *toc) { + int i; + + /* Find the numbers of the first track (usually 1) and the last track. */ + if ( !mb_disc_unix_read_toc_header(fd, toc) ) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot read table of contents"); + return 0; + } + + /* basic error checking */ + if ( toc->last_track_num == 0 ) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "this disc has no tracks"); + return 0; + } + + /* + * Read the TOC entry for every track. + */ + for (i = toc->first_track_num; i <= toc->last_track_num; i++) { + if ( !mb_disc_unix_read_toc_entry(fd, i, &toc->tracks[i]) ) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot read TOC entry for track %d", i); + return 0; + } + } + if ( !mb_disc_unix_read_toc_entry(fd, 0xAA, &toc->tracks[0]) ) { + snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH, + "cannot read TOC entry for lead-out"); + return 0; + } + + return 1; +} + +int mb_disc_unix_read(mb_disc_private *disc, const char *device, + unsigned int features) { + mb_disc_toc toc; + int fd; + int i; + + fd = mb_disc_unix_open(disc, device); + if (fd < 0) + return 0; + + + if ( !mb_disc_unix_read_toc(fd, disc, &toc) ) { + close(fd); + return 0; + } + + if ( !mb_disc_load_toc(disc, &toc) ) { + close(fd); + return 0; + } + + /* Read in the media catalog number */ + if (features & DISCID_FEATURE_MCN + && mb_disc_has_feature_unportable(DISCID_FEATURE_MCN)) { + mb_disc_unix_read_mcn(fd, disc); + } + + /* Read the ISRC for the track */ + if (features & DISCID_FEATURE_ISRC + && mb_disc_has_feature_unportable(DISCID_FEATURE_ISRC)) { + for (i = disc->first_track_num; i <= disc->last_track_num; i++) { + mb_disc_unix_read_isrc(fd, disc, i); + } + } + + close(fd); + + return 1; +} +/* EOF */ diff --git a/Src/external_dependencies/libdiscid-0.6.2/src/unix.h b/Src/external_dependencies/libdiscid-0.6.2/src/unix.h new file mode 100644 index 00000000..b6a059fc --- /dev/null +++ b/Src/external_dependencies/libdiscid-0.6.2/src/unix.h @@ -0,0 +1,103 @@ +/* -------------------------------------------------------------------------- + + MusicBrainz -- The Internet music metadatabase + + Copyright (C) 2013 Johannes Dewender + + 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 + +--------------------------------------------------------------------------- */ + +#include "discid/discid_private.h" + + +/* + * required functions + * ------------------ + */ + +/* + * Read the TOC header from disc + * + * THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM + */ +LIBDISCID_INTERNAL int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc); + +/* + * Read a TOC entry for a certain track from disc + * + * THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM + */ +LIBDISCID_INTERNAL int mb_disc_unix_read_toc_entry(int fd, int track_num, + mb_disc_toc_track *track); + +/* + * Read the MCN from the disc + * + * THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM + */ +LIBDISCID_INTERNAL void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc); + +/* + * Read the ISRC for a certain track from disc + * + * THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM + */ +LIBDISCID_INTERNAL void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, + int track_num); + + +/* + * provided functions + * ------------------ + */ + +/* + * This function is implemented in unix.c and can be used + * for most platforms to implement mb_disc_read_unportable + * after the above functions are implemented on the platform. + * Returns 1 on success and 0 on failure. + */ +LIBDISCID_INTERNAL int mb_disc_unix_read(mb_disc_private *disc, + const char *device, unsigned int features); + +/* + * This function is implemented in unix.c and can be used + * after the above functions are implemented on the platform. + * This uses mb_disc_unix_read_toc_* and adds some error checking. + * Returns 1 on success and 0 on failure. + */ +LIBDISCID_INTERNAL int mb_disc_unix_read_toc(int fd, mb_disc_private *disc, + mb_disc_toc *toc); + +/* + * utility function to find an existing device from a candidate list + */ +LIBDISCID_INTERNAL int mb_disc_unix_exists(const char *device); + +/* + * utility function to find an existing device from a candidate list + */ +LIBDISCID_INTERNAL char *mb_disc_unix_find_device(char *candidates[], + int num_candidates); + +/* + * utility function to try opening the device with open() + * returns a non-negative file descriptor on success. + * On failure a negative integer is returned and error_msg filled + * with an appropriate string. + */ +LIBDISCID_INTERNAL int mb_disc_unix_open(mb_disc_private *disc, + const char *device); |