📄 cuesheet.c
字号:
/* grabbag - Convenience lib for various routines common to several tools * Copyright (C) 2002,2003,2004,2005 Josh Coalson * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "share/grabbag.h"#include "FLAC/assert.h"#include <stdio.h>#include <stdlib.h>#include <string.h>unsigned grabbag__cuesheet_msf_to_frame(unsigned minutes, unsigned seconds, unsigned frames){ return ((minutes * 60) + seconds) * 75 + frames;}void grabbag__cuesheet_frame_to_msf(unsigned frame, unsigned *minutes, unsigned *seconds, unsigned *frames){ *frames = frame % 75; frame /= 75; *seconds = frame % 60; frame /= 60; *minutes = frame;}/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */static int local__parse_int_(const char *s){ int ret = 0; char c; if(*s == '\0') return -1; while('\0' != (c = *s++)) if(c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); else return -1; return ret;}/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */static FLAC__int64 local__parse_int64_(const char *s){ FLAC__int64 ret = 0; char c; if(*s == '\0') return -1; while('\0' != (c = *s++)) if(c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); else return -1; return ret;}/* accept '[0-9]+:[0-9][0-9]?:[0-9][0-9]?', but max second of 59 and max frame of 74, e.g. 0:0:0, 123:45:67 * return sample number or <0 for error */static FLAC__int64 local__parse_msf_(const char *s){ FLAC__int64 ret, field; char c; c = *s++; if(c >= '0' && c <= '9') field = (c - '0'); else return -1; while(':' != (c = *s++)) { if(c >= '0' && c <= '9') field = field * 10 + (c - '0'); else return -1; } ret = field * 60 * 44100; c = *s++; if(c >= '0' && c <= '9') field = (c - '0'); else return -1; if(':' != (c = *s++)) { if(c >= '0' && c <= '9') { field = field * 10 + (c - '0'); c = *s++; if(c != ':') return -1; } else return -1; } if(field >= 60) return -1; ret += field * 44100; c = *s++; if(c >= '0' && c <= '9') field = (c - '0'); else return -1; if('\0' != (c = *s++)) { if(c >= '0' && c <= '9') { field = field * 10 + (c - '0'); c = *s++; } else return -1; } if(c != '\0') return -1; if(field >= 75) return -1; ret += field * (44100 / 75); return ret;}static char *local__get_field_(char **s, FLAC__bool allow_quotes){ FLAC__bool has_quote = false; char *p; FLAC__ASSERT(0 != s); if(0 == *s) return 0; /* skip leading whitespace */ while(**s && 0 != strchr(" \t\r\n", **s)) (*s)++; if(**s == 0) { *s = 0; return 0; } if(allow_quotes && (**s == '"')) { has_quote = true; (*s)++; if(**s == 0) { *s = 0; return 0; } } p = *s; if(has_quote) { *s = strchr(*s, '\"'); /* if there is no matching end quote, it's an error */ if(0 == *s) p = *s = 0; else { **s = '\0'; (*s)++; } } else { while(**s && 0 == strchr(" \t\r\n", **s)) (*s)++; if(**s) { **s = '\0'; (*s)++; } else *s = 0; } return p;}static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__StreamMetadata *cuesheet, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset){#if defined _MSC_VER || defined __MINGW32__#define FLAC__STRCASECMP stricmp#else#define FLAC__STRCASECMP strcasecmp#endif char buffer[4096], *line, *field; unsigned linelen, forced_leadout_track_num = 0; FLAC__uint64 forced_leadout_track_offset = 0; int in_track_num = -1, in_index_num = -1; FLAC__bool disc_has_catalog = false, track_has_flags = false, track_has_isrc = false, has_forced_leadout = false; FLAC__StreamMetadata_CueSheet *cs = &cuesheet->data.cue_sheet; cs->lead_in = is_cdda? 2 * 44100 /* The default lead-in size for CD-DA */ : 0; cs->is_cd = is_cdda; while(0 != fgets(buffer, sizeof(buffer), file)) { (*last_line_read)++; line = buffer; linelen = strlen(line); if(line[linelen-1] != '\n') { *error_message = "line too long"; return false; } if(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) { if(0 == FLAC__STRCASECMP(field, "CATALOG")) { if(disc_has_catalog) { *error_message = "found multiple CATALOG commands"; return false; } if(0 == (field = local__get_field_(&line, /*allow_quotes=*/true))) { *error_message = "CATALOG is missing catalog number"; return false; } if(strlen(field) >= sizeof(cs->media_catalog_number)) { *error_message = "CATALOG number is too long"; return false; } if(is_cdda && (strlen(field) != 13 || strspn(field, "0123456789") != 13)) { *error_message = "CD-DA CATALOG number must be 13 decimal digits"; return false; } strcpy(cs->media_catalog_number, field); disc_has_catalog = true; } else if(0 == FLAC__STRCASECMP(field, "FLAGS")) { if(track_has_flags) { *error_message = "found multiple FLAGS commands"; return false; } if(in_track_num < 0 || in_index_num >= 0) { *error_message = "FLAGS command must come after TRACK but before INDEX"; return false; } while(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) { if(0 == FLAC__STRCASECMP(field, "PRE")) cs->tracks[cs->num_tracks-1].pre_emphasis = 1; } track_has_flags = true; } else if(0 == FLAC__STRCASECMP(field, "INDEX")) { FLAC__int64 xx; FLAC__StreamMetadata_CueSheet_Track *track = &cs->tracks[cs->num_tracks-1]; if(in_track_num < 0) { *error_message = "found INDEX before any TRACK"; return false; } if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { *error_message = "INDEX is missing index number"; return false; } in_index_num = local__parse_int_(field); if(in_index_num < 0) { *error_message = "INDEX has invalid index number"; return false; } FLAC__ASSERT(cs->num_tracks > 0); if(track->num_indices == 0) { /* it's the first index point of the track */ if(in_index_num > 1) { *error_message = "first INDEX number of a TRACK must be 0 or 1"; return false; } } else { if(in_index_num != track->indices[track->num_indices-1].number + 1) { *error_message = "INDEX numbers must be sequential"; return false; } } if(is_cdda && in_index_num > 99) { *error_message = "CD-DA INDEX number must be between 0 and 99, inclusive"; return false; } /*@@@ search for duplicate track number? */ if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { *error_message = "INDEX is missing an offset after the index number"; return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -