1 /* Implements the public API for libSoX general functions
2  * All public functions & data are prefixed with sox_ .
3  *
4  * (c) 2006-8 Chris Bagwell and SoX contributors
5  *
6  * This library is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or (at
9  * your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "sox_i.h"
22 #include <string.h>
23 
sox_version(void)24 const char *sox_version(void)
25 {
26   static char versionstr[20];
27 
28   sprintf(versionstr, "%d.%d.%d",
29           (SOX_LIB_VERSION_CODE & 0xff0000) >> 16,
30           (SOX_LIB_VERSION_CODE & 0x00ff00) >> 8,
31           (SOX_LIB_VERSION_CODE & 0x0000ff));
32   return(versionstr);
33 }
34 
sox_version_info(void)35 sox_version_info_t const * sox_version_info(void)
36 {
37 #define STRINGIZE1(x) #x
38 #define STRINGIZE(x) STRINGIZE1(x)
39     static char arch[30];
40     static sox_version_info_t info = {
41         /* size */
42         sizeof(sox_version_info_t),
43         /* flags */
44         (sox_version_flags_t)(
45 #if HAVE_POPEN
46         sox_version_have_popen +
47 #endif
48 #if  HAVE_MAGIC
49         sox_version_have_magic +
50 #endif
51 #if HAVE_OPENMP
52         sox_version_have_threads +
53 #endif
54 #ifdef HAVE_FMEMOPEN
55         sox_version_have_memopen +
56 #endif
57         sox_version_none),
58         /* version_code */
59         SOX_LIB_VERSION_CODE,
60         /* version */
61         NULL,
62         /* sox_version_extra */
63 #ifdef PACKAGE_EXTRA
64         PACKAGE_EXTRA,
65 #else
66         NULL,
67 #endif
68         /* sox_time */
69         __DATE__ " " __TIME__,
70         /* sox_distro */
71 #ifdef DISTRO
72         DISTRO,
73 #else
74         NULL,
75 #endif
76         /* sox_compiler */
77 #if defined __GNUC__
78         "gcc " __VERSION__,
79 #elif defined _MSC_VER
80         "msvc " STRINGIZE(_MSC_FULL_VER),
81 #elif defined __SUNPRO_C
82     fprintf(file, "sun c " STRINGIZE(__SUNPRO_C),
83 #else
84         NULL,
85 #endif
86         /* sox_arch */
87         NULL
88     };
89 
90     if (!info.version)
91     {
92         info.version = sox_version();
93     }
94 
95     if (!info.arch)
96     {
97         snprintf(arch, sizeof(arch),
98             "%" PRIuPTR "%" PRIuPTR "%" PRIuPTR "%" PRIuPTR
99             " %" PRIuPTR "%" PRIuPTR " %" PRIuPTR "%" PRIuPTR " %c %s",
100             sizeof(char), sizeof(short), sizeof(long), sizeof(off_t),
101             sizeof(float), sizeof(double), sizeof(int *), sizeof(int (*)(void)),
102             MACHINE_IS_BIGENDIAN ? 'B' : 'L',
103             (info.flags & sox_version_have_threads) ? "OMP" : "");
104         arch[sizeof(arch) - 1] = 0;
105         info.arch = arch;
106     }
107 
108     return &info;
109 }
110 
111 /* Default routine to output messages; can be overridden */
output_message(unsigned level,const char * filename,const char * fmt,va_list ap)112 static void output_message(
113     unsigned level, const char *filename, const char *fmt, va_list ap)
114 {
115   if (sox_globals.verbosity >= level) {
116     char base_name[128];
117     sox_basename(base_name, sizeof(base_name), filename);
118     fprintf(stderr, "%s: ", base_name);
119     vfprintf(stderr, fmt, ap);
120     fprintf(stderr, "\n");
121   }
122 }
123 
124 static sox_globals_t s_sox_globals = {
125   2,               /* unsigned     verbosity */
126   output_message,  /* sox_output_message_handler */
127   sox_false,       /* sox_bool     repeatable */
128   8192,            /* size_t       bufsiz */
129   0,               /* size_t       input_bufsiz */
130   0,               /* int32_t      ranqd1 */
131   NULL,            /* char const * stdin_in_use_by */
132   NULL,            /* char const * stdout_in_use_by */
133   NULL,            /* char const * subsystem */
134   NULL,            /* char       * tmp_path */
135   sox_false,       /* sox_bool     use_magic */
136   sox_false,       /* sox_bool     use_threads */
137   10               /* size_t       log2_dft_min_size */
138 };
139 
sox_get_globals(void)140 sox_globals_t * sox_get_globals(void)
141 {
142     return &s_sox_globals;
143 }
144 
145 /* FIXME: Not thread safe using globals */
146 static sox_effects_globals_t s_sox_effects_globals =
147     {sox_plot_off, &s_sox_globals};
148 
149 sox_effects_globals_t *
sox_get_effects_globals(void)150 sox_get_effects_globals(void)
151 {
152     return &s_sox_effects_globals;
153 }
154 
sox_strerror(int sox_errno)155 char const * sox_strerror(int sox_errno)
156 {
157   static char const * const errors[] = {
158     "Invalid Audio Header",
159     "Unsupported data format",
160     "Can't allocate memory",
161     "Operation not permitted",
162     "Operation not supported",
163     "Invalid argument",
164   };
165   if (sox_errno < SOX_EHDR)
166     return strerror(sox_errno);
167   sox_errno -= SOX_EHDR;
168   if (sox_errno < 0 || (size_t)sox_errno >= array_length(errors))
169     return "Unknown error";
170   return errors[sox_errno];
171 }
172 
sox_basename(char * base_buffer,size_t base_buffer_len,const char * filename)173 size_t sox_basename(char * base_buffer, size_t base_buffer_len, const char * filename)
174 {
175   if (!base_buffer || !base_buffer_len)
176   {
177     return 0;
178   }
179   else
180   {
181     char const * slash_pos = LAST_SLASH(filename);
182     char const * base_name = slash_pos ? slash_pos + 1 : filename;
183     char const * dot_pos   = strrchr(base_name, '.');
184     size_t i, len;
185     dot_pos = dot_pos ? dot_pos : base_name + strlen(base_name);
186     len = dot_pos - base_name;
187     len = min(len, base_buffer_len - 1);
188     for (i = 0; i < len; i++)
189     {
190       base_buffer[i] = base_name[i];
191     }
192     base_buffer[i] = 0;
193     return i;
194   }
195 }
196 
197 #define SOX_MESSAGE_FUNCTION(name,level) \
198 void name(char const * fmt, ...) { \
199   va_list ap; \
200   va_start(ap, fmt); \
201   if (sox_globals.output_message_handler) \
202     (*sox_globals.output_message_handler)(level,sox_globals.subsystem,fmt,ap); \
203   va_end(ap); \
204 }
205 
206 SOX_MESSAGE_FUNCTION(lsx_fail_impl  , 1)
207 SOX_MESSAGE_FUNCTION(lsx_warn_impl  , 2)
208 SOX_MESSAGE_FUNCTION(lsx_report_impl, 3)
209 SOX_MESSAGE_FUNCTION(lsx_debug_impl , 4)
210 SOX_MESSAGE_FUNCTION(lsx_debug_more_impl , 5)
211 SOX_MESSAGE_FUNCTION(lsx_debug_most_impl , 6)
212 
213 #undef SOX_MESSAGE_FUNCTION
214 
sox_init(void)215 int sox_init(void)
216 {
217   return lsx_effects_init();
218 }
219 
sox_quit(void)220 int sox_quit(void)
221 {
222   sox_format_quit();
223   return lsx_effects_quit();
224 }
225