annotate src/libsndfile-1.0.27/programs/sndfile-metadata-set.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 1df64224f5ac
children
rev   line source
Chris@40 1 /*
Chris@40 2 ** Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
Chris@40 3 ** Copyright (C) 2008-2010 George Blood Audio
Chris@40 4 **
Chris@40 5 ** All rights reserved.
Chris@40 6 **
Chris@40 7 ** Redistribution and use in source and binary forms, with or without
Chris@40 8 ** modification, are permitted provided that the following conditions are
Chris@40 9 ** met:
Chris@40 10 **
Chris@40 11 ** * Redistributions of source code must retain the above copyright
Chris@40 12 ** notice, this list of conditions and the following disclaimer.
Chris@40 13 ** * Redistributions in binary form must reproduce the above copyright
Chris@40 14 ** notice, this list of conditions and the following disclaimer in
Chris@40 15 ** the documentation and/or other materials provided with the
Chris@40 16 ** distribution.
Chris@40 17 ** * Neither the author nor the names of any contributors may be used
Chris@40 18 ** to endorse or promote products derived from this software without
Chris@40 19 ** specific prior written permission.
Chris@40 20 **
Chris@40 21 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Chris@40 22 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Chris@40 23 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Chris@40 24 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
Chris@40 25 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Chris@40 26 ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Chris@40 27 ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
Chris@40 28 ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Chris@40 29 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
Chris@40 30 ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Chris@40 31 ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Chris@40 32 */
Chris@40 33
Chris@40 34 #include <config.h>
Chris@40 35
Chris@40 36 #include <stdio.h>
Chris@40 37 #include <stdlib.h>
Chris@40 38 #include <string.h>
Chris@40 39 #include <ctype.h>
Chris@40 40 #include <time.h>
Chris@40 41
Chris@40 42 #include <sndfile.h>
Chris@40 43
Chris@40 44 #include "common.h"
Chris@40 45
Chris@40 46 #define BUFFER_LEN (1 << 16)
Chris@40 47
Chris@40 48
Chris@40 49 static void usage_exit (const char *progname, int exit_code) ;
Chris@40 50 static void missing_param (const char * option) ;
Chris@40 51 static void read_localtime (struct tm * timedata) ;
Chris@40 52 static int has_bext_fields_set (const METADATA_INFO * info) ;
Chris@40 53
Chris@40 54 int
Chris@40 55 main (int argc, char *argv [])
Chris@40 56 { METADATA_INFO info ;
Chris@40 57 struct tm timedata ;
Chris@40 58 const char *progname ;
Chris@40 59 const char * filenames [2] = { NULL, NULL } ;
Chris@40 60 char date [128], time [128] ;
Chris@40 61 int k ;
Chris@40 62
Chris@40 63 /* Store the program name. */
Chris@40 64 progname = program_name (argv [0]) ;
Chris@40 65
Chris@40 66 /* Check if we've been asked for help. */
Chris@40 67 if (argc < 3 || strcmp (argv [1], "--help") == 0 || strcmp (argv [1], "-h") == 0)
Chris@40 68 usage_exit (progname, 0) ;
Chris@40 69
Chris@40 70 /* Set all fields of the struct to zero bytes. */
Chris@40 71 memset (&info, 0, sizeof (info)) ;
Chris@40 72
Chris@40 73 /* Get the time in case we need it later. */
Chris@40 74 read_localtime (&timedata) ;
Chris@40 75
Chris@40 76 for (k = 1 ; k < argc ; k++)
Chris@40 77 { if (argv [k][0] != '-')
Chris@40 78 { if (filenames [0] == NULL)
Chris@40 79 filenames [0] = argv [k] ;
Chris@40 80 else if (filenames [1] == NULL)
Chris@40 81 filenames [1] = argv [k] ;
Chris@40 82 else
Chris@40 83 { printf ("Error : Already have two file names on the command line and then found '%s'.\n\n", argv [k]) ;
Chris@40 84 usage_exit (progname, 1) ;
Chris@40 85 } ;
Chris@40 86 continue ;
Chris@40 87 } ;
Chris@40 88
Chris@40 89 #define HANDLE_BEXT_ARG(cmd, field) \
Chris@40 90 if (strcmp (argv [k], cmd) == 0) \
Chris@40 91 { k ++ ; \
Chris@40 92 if (k == argc) missing_param (argv [k - 1]) ; \
Chris@40 93 info.field = argv [k] ; \
Chris@40 94 continue ; \
Chris@40 95 } ;
Chris@40 96
Chris@40 97 HANDLE_BEXT_ARG ("--bext-description", description) ;
Chris@40 98 HANDLE_BEXT_ARG ("--bext-originator", originator) ;
Chris@40 99 HANDLE_BEXT_ARG ("--bext-orig-ref", originator_reference) ;
Chris@40 100 HANDLE_BEXT_ARG ("--bext-umid", umid) ;
Chris@40 101 HANDLE_BEXT_ARG ("--bext-orig-date", origination_date) ;
Chris@40 102 HANDLE_BEXT_ARG ("--bext-orig-time", origination_time) ;
Chris@40 103 HANDLE_BEXT_ARG ("--bext-coding-hist", coding_history) ;
Chris@40 104 HANDLE_BEXT_ARG ("--bext-time-ref", time_ref) ;
Chris@40 105
Chris@40 106 #define HANDLE_STR_ARG(cmd, field) \
Chris@40 107 if (strcmp (argv [k], cmd) == 0) \
Chris@40 108 { k ++ ; \
Chris@40 109 if (k == argc) missing_param (argv [k - 1]) ; \
Chris@40 110 info.field = argv [k] ; \
Chris@40 111 continue ; \
Chris@40 112 } ;
Chris@40 113
Chris@40 114 HANDLE_STR_ARG ("--str-comment", comment) ;
Chris@40 115 HANDLE_STR_ARG ("--str-title", title) ;
Chris@40 116 HANDLE_STR_ARG ("--str-copyright", copyright) ;
Chris@40 117 HANDLE_STR_ARG ("--str-artist", artist) ;
Chris@40 118 HANDLE_STR_ARG ("--str-date", date) ;
Chris@40 119 HANDLE_STR_ARG ("--str-album", album) ;
Chris@40 120 HANDLE_STR_ARG ("--str-license", license) ;
Chris@40 121
Chris@40 122 /* Following options do not take an argument. */
Chris@40 123 if (strcmp (argv [k], "--bext-auto-time-date") == 0)
Chris@40 124 { snprintf (time, sizeof (time), "%02d:%02d:%02d", timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ;
Chris@40 125 info.origination_time = time ;
Chris@40 126
Chris@40 127 snprintf (date, sizeof (date), "%04d-%02d-%02d", timedata.tm_year + 1900, timedata.tm_mon + 1, timedata.tm_mday) ;
Chris@40 128 info.origination_date = date ;
Chris@40 129 continue ;
Chris@40 130 } ;
Chris@40 131
Chris@40 132 if (strcmp (argv [k], "--bext-auto-time") == 0)
Chris@40 133 { snprintf (time, sizeof (time), "%02d:%02d:%02d", timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ;
Chris@40 134 info.origination_time = time ;
Chris@40 135 continue ;
Chris@40 136 } ;
Chris@40 137
Chris@40 138 if (strcmp (argv [k], "--bext-auto-date") == 0)
Chris@40 139 { snprintf (date, sizeof (date), "%04d-%02d-%02d", timedata.tm_year + 1900, timedata.tm_mon + 1, timedata.tm_mday) ;
Chris@40 140 info.origination_date = strdup (date) ;
Chris@40 141 continue ;
Chris@40 142 } ;
Chris@40 143
Chris@40 144 if (strcmp (argv [k], "--str-auto-date") == 0)
Chris@40 145 { snprintf (date, sizeof (date), "%04d-%02d-%02d", timedata.tm_year + 1900, timedata.tm_mon + 1, timedata.tm_mday) ;
Chris@40 146
Chris@40 147 info.date = strdup (date) ;
Chris@40 148 continue ;
Chris@40 149 } ;
Chris@40 150
Chris@40 151 printf ("Error : Don't know what to do with command line arg '%s'.\n\n", argv [k]) ;
Chris@40 152 usage_exit (progname, 1) ;
Chris@40 153 } ;
Chris@40 154
Chris@40 155 /* Find out if any of the 'bext' fields are set. */
Chris@40 156 info.has_bext_fields = has_bext_fields_set (&info) ;
Chris@40 157
Chris@40 158 if (filenames [0] == NULL)
Chris@40 159 { printf ("Error : No input file specificed.\n\n") ;
Chris@40 160 exit (1) ;
Chris@40 161 } ;
Chris@40 162
Chris@40 163 if (filenames [1] != NULL && strcmp (filenames [0], filenames [1]) == 0)
Chris@40 164 { printf ("Error : Input and output files are the same.\n\n") ;
Chris@40 165 exit (1) ;
Chris@40 166 } ;
Chris@40 167
Chris@40 168 if (info.coding_history != NULL && filenames [1] == NULL)
Chris@40 169 { printf ("\n"
Chris@40 170 "Error : Trying to update coding history of an existing file which unfortunately\n"
Chris@40 171 " is not supported. Instead, create a new file using :\n"
Chris@40 172 "\n"
Chris@40 173 " %s --bext-coding-hist \"Coding history\" old_file.wav new_file.wav\n"
Chris@40 174 "\n",
Chris@40 175 progname) ;
Chris@40 176 exit (1) ;
Chris@40 177 } ;
Chris@40 178
Chris@40 179 sfe_apply_metadata_changes (filenames, &info) ;
Chris@40 180
Chris@40 181 return 0 ;
Chris@40 182 } /* main */
Chris@40 183
Chris@40 184 /*==============================================================================
Chris@40 185 ** Print version and usage.
Chris@40 186 */
Chris@40 187
Chris@40 188 static void
Chris@40 189 usage_exit (const char *progname, int exit_code)
Chris@40 190 { printf ("\nUsage :\n\n"
Chris@40 191 " %s [options] <file>\n"
Chris@40 192 " %s [options] <input file> <output file>\n"
Chris@40 193 "\n",
Chris@40 194 progname, progname) ;
Chris@40 195
Chris@40 196 puts (
Chris@40 197 "Where an option is made up of a pair of a field to set (one of\n"
Chris@40 198 "the 'bext' or metadata fields below) and a string. Fields are\n"
Chris@40 199 "as follows :\n"
Chris@40 200 ) ;
Chris@40 201
Chris@40 202 puts (
Chris@40 203 " --bext-description Set the 'bext' description.\n"
Chris@40 204 " --bext-originator Set the 'bext' originator.\n"
Chris@40 205 " --bext-orig-ref Set the 'bext' originator reference.\n"
Chris@40 206 " --bext-umid Set the 'bext' UMID.\n"
Chris@40 207 " --bext-orig-date Set the 'bext' origination date.\n"
Chris@40 208 " --bext-orig-time Set the 'bext' origination time.\n"
Chris@40 209 " --bext-coding-hist Set the 'bext' coding history.\n"
Chris@40 210 " --bext-time-ref Set the 'bext' Time ref.\n"
Chris@40 211 "\n"
Chris@40 212 " --str-comment Set the metadata comment.\n"
Chris@40 213 " --str-title Set the metadata title.\n"
Chris@40 214 " --str-copyright Set the metadata copyright.\n"
Chris@40 215 " --str-artist Set the metadata artist.\n"
Chris@40 216 " --str-date Set the metadata date.\n"
Chris@40 217 " --str-album Set the metadata album.\n"
Chris@40 218 " --str-license Set the metadata license.\n"
Chris@40 219 ) ;
Chris@40 220
Chris@40 221 puts (
Chris@40 222 "There are also the following arguments which do not take a\n"
Chris@40 223 "parameter :\n\n"
Chris@40 224 " --bext-auto-time-date Set the 'bext' time and date to current time/date.\n"
Chris@40 225 " --bext-auto-time Set the 'bext' time to current time.\n"
Chris@40 226 " --bext-auto-date Set the 'bext' date to current date.\n"
Chris@40 227 " --str-auto-date Set the metadata date to current date.\n"
Chris@40 228 ) ;
Chris@40 229
Chris@40 230 puts (
Chris@40 231 "Most of the above operations can be done in-place on an existing\n"
Chris@40 232 "file. If any operation cannot be performed, the application will\n"
Chris@40 233 "exit with an appropriate error message.\n"
Chris@40 234 ) ;
Chris@40 235
Chris@40 236 printf ("Using %s.\n\n", sf_version_string ()) ;
Chris@40 237 exit (exit_code) ;
Chris@40 238 } /* usage_exit */
Chris@40 239
Chris@40 240 static void
Chris@40 241 missing_param (const char * option)
Chris@40 242 {
Chris@40 243 printf ("Error : Option '%s' needs a parameter but doesn't seem to have one.\n\n", option) ;
Chris@40 244 exit (1) ;
Chris@40 245 } /* missing_param */
Chris@40 246
Chris@40 247 /*==============================================================================
Chris@40 248 */
Chris@40 249
Chris@40 250 static int
Chris@40 251 has_bext_fields_set (const METADATA_INFO * info)
Chris@40 252 {
Chris@40 253 if (info->description || info->originator || info->originator_reference)
Chris@40 254 return 1 ;
Chris@40 255
Chris@40 256 if (info->origination_date || info->origination_time || info->umid || info->coding_history || info->time_ref)
Chris@40 257 return 1 ;
Chris@40 258
Chris@40 259 return 0 ;
Chris@40 260 } /* has_bext_fields_set */
Chris@40 261
Chris@40 262 static void
Chris@40 263 read_localtime (struct tm * timedata)
Chris@40 264 { time_t current ;
Chris@40 265
Chris@40 266 time (&current) ;
Chris@40 267 memset (timedata, 0, sizeof (struct tm)) ;
Chris@40 268
Chris@40 269 #if defined (HAVE_LOCALTIME_R)
Chris@40 270 /* If the re-entrant version is available, use it. */
Chris@40 271 localtime_r (&current, timedata) ;
Chris@40 272 #elif defined (HAVE_LOCALTIME)
Chris@40 273 {
Chris@40 274 struct tm *tmptr ;
Chris@40 275 /* Otherwise use the standard one and copy the data to local storage. */
Chris@40 276 if ((tmptr = localtime (&current)) != NULL)
Chris@40 277 memcpy (timedata, tmptr, sizeof (struct tm)) ;
Chris@40 278 }
Chris@40 279 #endif
Chris@40 280
Chris@40 281 return ;
Chris@40 282 } /* read_localtime */
Chris@40 283