annotate src/flac-1.2.1/src/metaflac/utils.c @ 86:98c1576536ae

Bring in flac, ogg, vorbis
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 19 Mar 2013 17:37:49 +0000
parents
children
rev   line source
cannam@86 1 /* metaflac - Command-line FLAC metadata editor
cannam@86 2 * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson
cannam@86 3 *
cannam@86 4 * This program is free software; you can redistribute it and/or
cannam@86 5 * modify it under the terms of the GNU General Public License
cannam@86 6 * as published by the Free Software Foundation; either version 2
cannam@86 7 * of the License, or (at your option) any later version.
cannam@86 8 *
cannam@86 9 * This program is distributed in the hope that it will be useful,
cannam@86 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
cannam@86 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
cannam@86 12 * GNU General Public License for more details.
cannam@86 13 *
cannam@86 14 * You should have received a copy of the GNU General Public License
cannam@86 15 * along with this program; if not, write to the Free Software
cannam@86 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
cannam@86 17 */
cannam@86 18
cannam@86 19 #if HAVE_CONFIG_H
cannam@86 20 # include <config.h>
cannam@86 21 #endif
cannam@86 22
cannam@86 23 #include "utils.h"
cannam@86 24 #include "FLAC/assert.h"
cannam@86 25 #include "share/alloc.h"
cannam@86 26 #include "share/utf8.h"
cannam@86 27 #include <ctype.h>
cannam@86 28 #include <stdarg.h>
cannam@86 29 #include <stdio.h>
cannam@86 30 #include <stdlib.h>
cannam@86 31 #include <string.h>
cannam@86 32
cannam@86 33 void die(const char *message)
cannam@86 34 {
cannam@86 35 FLAC__ASSERT(0 != message);
cannam@86 36 fprintf(stderr, "ERROR: %s\n", message);
cannam@86 37 exit(1);
cannam@86 38 }
cannam@86 39
cannam@86 40 #ifdef FLAC__VALGRIND_TESTING
cannam@86 41 size_t local_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
cannam@86 42 {
cannam@86 43 size_t ret = fwrite(ptr, size, nmemb, stream);
cannam@86 44 if(!ferror(stream))
cannam@86 45 fflush(stream);
cannam@86 46 return ret;
cannam@86 47 }
cannam@86 48 #endif
cannam@86 49
cannam@86 50 char *local_strdup(const char *source)
cannam@86 51 {
cannam@86 52 char *ret;
cannam@86 53 FLAC__ASSERT(0 != source);
cannam@86 54 if(0 == (ret = strdup(source)))
cannam@86 55 die("out of memory during strdup()");
cannam@86 56 return ret;
cannam@86 57 }
cannam@86 58
cannam@86 59 void local_strcat(char **dest, const char *source)
cannam@86 60 {
cannam@86 61 size_t ndest, nsource;
cannam@86 62
cannam@86 63 FLAC__ASSERT(0 != dest);
cannam@86 64 FLAC__ASSERT(0 != source);
cannam@86 65
cannam@86 66 ndest = *dest? strlen(*dest) : 0;
cannam@86 67 nsource = strlen(source);
cannam@86 68
cannam@86 69 if(nsource == 0)
cannam@86 70 return;
cannam@86 71
cannam@86 72 *dest = (char*)safe_realloc_add_3op_(*dest, ndest, /*+*/nsource, /*+*/1);
cannam@86 73 if(0 == *dest)
cannam@86 74 die("out of memory growing string");
cannam@86 75 strcpy((*dest)+ndest, source);
cannam@86 76 }
cannam@86 77
cannam@86 78 void hexdump(const char *filename, const FLAC__byte *buf, unsigned bytes, const char *indent)
cannam@86 79 {
cannam@86 80 unsigned i, left = bytes;
cannam@86 81 const FLAC__byte *b = buf;
cannam@86 82
cannam@86 83 for(i = 0; i < bytes; i += 16) {
cannam@86 84 printf("%s%s%s%08X: "
cannam@86 85 "%02X %02X %02X %02X %02X %02X %02X %02X "
cannam@86 86 "%02X %02X %02X %02X %02X %02X %02X %02X "
cannam@86 87 "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
cannam@86 88 filename? filename:"", filename? ":":"",
cannam@86 89 indent, i,
cannam@86 90 left > 0? (unsigned char)b[ 0] : 0,
cannam@86 91 left > 1? (unsigned char)b[ 1] : 0,
cannam@86 92 left > 2? (unsigned char)b[ 2] : 0,
cannam@86 93 left > 3? (unsigned char)b[ 3] : 0,
cannam@86 94 left > 4? (unsigned char)b[ 4] : 0,
cannam@86 95 left > 5? (unsigned char)b[ 5] : 0,
cannam@86 96 left > 6? (unsigned char)b[ 6] : 0,
cannam@86 97 left > 7? (unsigned char)b[ 7] : 0,
cannam@86 98 left > 8? (unsigned char)b[ 8] : 0,
cannam@86 99 left > 9? (unsigned char)b[ 9] : 0,
cannam@86 100 left > 10? (unsigned char)b[10] : 0,
cannam@86 101 left > 11? (unsigned char)b[11] : 0,
cannam@86 102 left > 12? (unsigned char)b[12] : 0,
cannam@86 103 left > 13? (unsigned char)b[13] : 0,
cannam@86 104 left > 14? (unsigned char)b[14] : 0,
cannam@86 105 left > 15? (unsigned char)b[15] : 0,
cannam@86 106 (left > 0) ? (isprint(b[ 0]) ? b[ 0] : '.') : ' ',
cannam@86 107 (left > 1) ? (isprint(b[ 1]) ? b[ 1] : '.') : ' ',
cannam@86 108 (left > 2) ? (isprint(b[ 2]) ? b[ 2] : '.') : ' ',
cannam@86 109 (left > 3) ? (isprint(b[ 3]) ? b[ 3] : '.') : ' ',
cannam@86 110 (left > 4) ? (isprint(b[ 4]) ? b[ 4] : '.') : ' ',
cannam@86 111 (left > 5) ? (isprint(b[ 5]) ? b[ 5] : '.') : ' ',
cannam@86 112 (left > 6) ? (isprint(b[ 6]) ? b[ 6] : '.') : ' ',
cannam@86 113 (left > 7) ? (isprint(b[ 7]) ? b[ 7] : '.') : ' ',
cannam@86 114 (left > 8) ? (isprint(b[ 8]) ? b[ 8] : '.') : ' ',
cannam@86 115 (left > 9) ? (isprint(b[ 9]) ? b[ 9] : '.') : ' ',
cannam@86 116 (left > 10) ? (isprint(b[10]) ? b[10] : '.') : ' ',
cannam@86 117 (left > 11) ? (isprint(b[11]) ? b[11] : '.') : ' ',
cannam@86 118 (left > 12) ? (isprint(b[12]) ? b[12] : '.') : ' ',
cannam@86 119 (left > 13) ? (isprint(b[13]) ? b[13] : '.') : ' ',
cannam@86 120 (left > 14) ? (isprint(b[14]) ? b[14] : '.') : ' ',
cannam@86 121 (left > 15) ? (isprint(b[15]) ? b[15] : '.') : ' '
cannam@86 122 );
cannam@86 123 left -= 16;
cannam@86 124 b += 16;
cannam@86 125 }
cannam@86 126 }
cannam@86 127
cannam@86 128 void print_error_with_chain_status(FLAC__Metadata_Chain *chain, const char *format, ...)
cannam@86 129 {
cannam@86 130 const FLAC__Metadata_ChainStatus status = FLAC__metadata_chain_status(chain);
cannam@86 131 va_list args;
cannam@86 132
cannam@86 133 FLAC__ASSERT(0 != format);
cannam@86 134
cannam@86 135 va_start(args, format);
cannam@86 136
cannam@86 137 (void) vfprintf(stderr, format, args);
cannam@86 138
cannam@86 139 va_end(args);
cannam@86 140
cannam@86 141 fprintf(stderr, ", status = \"%s\"\n", FLAC__Metadata_ChainStatusString[status]);
cannam@86 142
cannam@86 143 if(status == FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE) {
cannam@86 144 fprintf(stderr, "\n"
cannam@86 145 "The FLAC file could not be opened. Most likely the file does not exist\n"
cannam@86 146 "or is not readable.\n"
cannam@86 147 );
cannam@86 148 }
cannam@86 149 else if(status == FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE) {
cannam@86 150 fprintf(stderr, "\n"
cannam@86 151 "The file does not appear to be a FLAC file.\n"
cannam@86 152 );
cannam@86 153 }
cannam@86 154 else if(status == FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE) {
cannam@86 155 fprintf(stderr, "\n"
cannam@86 156 "The FLAC file does not have write permissions.\n"
cannam@86 157 );
cannam@86 158 }
cannam@86 159 else if(status == FLAC__METADATA_CHAIN_STATUS_BAD_METADATA) {
cannam@86 160 fprintf(stderr, "\n"
cannam@86 161 "The metadata to be writted does not conform to the FLAC metadata\n"
cannam@86 162 "specifications.\n"
cannam@86 163 );
cannam@86 164 }
cannam@86 165 else if(status == FLAC__METADATA_CHAIN_STATUS_READ_ERROR) {
cannam@86 166 fprintf(stderr, "\n"
cannam@86 167 "There was an error while reading the FLAC file.\n"
cannam@86 168 );
cannam@86 169 }
cannam@86 170 else if(status == FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR) {
cannam@86 171 fprintf(stderr, "\n"
cannam@86 172 "There was an error while writing FLAC file; most probably the disk is\n"
cannam@86 173 "full.\n"
cannam@86 174 );
cannam@86 175 }
cannam@86 176 else if(status == FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR) {
cannam@86 177 fprintf(stderr, "\n"
cannam@86 178 "There was an error removing the temporary FLAC file.\n"
cannam@86 179 );
cannam@86 180 }
cannam@86 181 }
cannam@86 182
cannam@86 183 FLAC__bool parse_vorbis_comment_field(const char *field_ref, char **field, char **name, char **value, unsigned *length, const char **violation)
cannam@86 184 {
cannam@86 185 static const char * const violations[] = {
cannam@86 186 "field name contains invalid character",
cannam@86 187 "field contains no '=' character"
cannam@86 188 };
cannam@86 189
cannam@86 190 char *p, *q, *s;
cannam@86 191
cannam@86 192 if(0 != field)
cannam@86 193 *field = local_strdup(field_ref);
cannam@86 194
cannam@86 195 s = local_strdup(field_ref);
cannam@86 196
cannam@86 197 if(0 == (p = strchr(s, '='))) {
cannam@86 198 free(s);
cannam@86 199 *violation = violations[1];
cannam@86 200 return false;
cannam@86 201 }
cannam@86 202 *p++ = '\0';
cannam@86 203
cannam@86 204 for(q = s; *q; q++) {
cannam@86 205 if(*q < 0x20 || *q > 0x7d || *q == 0x3d) {
cannam@86 206 free(s);
cannam@86 207 *violation = violations[0];
cannam@86 208 return false;
cannam@86 209 }
cannam@86 210 }
cannam@86 211
cannam@86 212 *name = local_strdup(s);
cannam@86 213 *value = local_strdup(p);
cannam@86 214 *length = strlen(p);
cannam@86 215
cannam@86 216 free(s);
cannam@86 217 return true;
cannam@86 218 }
cannam@86 219
cannam@86 220 void write_vc_field(const char *filename, const FLAC__StreamMetadata_VorbisComment_Entry *entry, FLAC__bool raw, FILE *f)
cannam@86 221 {
cannam@86 222 if(0 != entry->entry) {
cannam@86 223 if(filename)
cannam@86 224 fprintf(f, "%s:", filename);
cannam@86 225
cannam@86 226 if(!raw) {
cannam@86 227 /*
cannam@86 228 * WATCHOUT: comments that contain an embedded null will
cannam@86 229 * be truncated by utf_decode().
cannam@86 230 */
cannam@86 231 char *converted;
cannam@86 232
cannam@86 233 if(utf8_decode((const char *)entry->entry, &converted) >= 0) {
cannam@86 234 (void) local_fwrite(converted, 1, strlen(converted), f);
cannam@86 235 free(converted);
cannam@86 236 }
cannam@86 237 else {
cannam@86 238 (void) local_fwrite(entry->entry, 1, entry->length, f);
cannam@86 239 }
cannam@86 240 }
cannam@86 241 else {
cannam@86 242 (void) local_fwrite(entry->entry, 1, entry->length, f);
cannam@86 243 }
cannam@86 244 }
cannam@86 245
cannam@86 246 putc('\n', f);
cannam@86 247 }
cannam@86 248
cannam@86 249 void write_vc_fields(const char *filename, const char *field_name, const FLAC__StreamMetadata_VorbisComment_Entry entry[], unsigned num_entries, FLAC__bool raw, FILE *f)
cannam@86 250 {
cannam@86 251 unsigned i;
cannam@86 252 const unsigned field_name_length = (0 != field_name)? strlen(field_name) : 0;
cannam@86 253
cannam@86 254 for(i = 0; i < num_entries; i++) {
cannam@86 255 if(0 == field_name || FLAC__metadata_object_vorbiscomment_entry_matches(entry[i], field_name, field_name_length))
cannam@86 256 write_vc_field(filename, entry + i, raw, f);
cannam@86 257 }
cannam@86 258 }