OSDN Git Service

Updated OggDec binaries to v1.10.1 using libvorbis v1.3.5 (2015-03-19), compiled...
[lamexp/LameXP.git] / etc / Patches / OggDec-v1.10.1-Win32-UnicodeSupport+FlushFix.diff
1  audio.c           |   3 +-
2  oggdec.c          | 312 ++++++++++++++++++++++++++++++------------------------
3  unicode_support.c | 197 ++++++++++++++++++++++++++++++++++
4  unicode_support.h |  49 +++++++++
5  wave_out.h        |   2 +-
6  5 files changed, 422 insertions(+), 141 deletions(-)
7
8 diff --git a/audio.c b/audio.c
9 index 88d6b21..e3a303c 100644
10 --- a/audio.c
11 +++ b/audio.c
12 @@ -31,6 +31,7 @@
13  #include <math.h>
14  #include "audio.h"
15  
16 +#include "unicode_support.h"
17  
18  audio_file *open_output_audio_file(char *infile, int samplerate, int channels,
19                              int outputFormat, int fileType, unsigned int knownlength)
20 @@ -76,7 +77,7 @@ audio_file *open_output_audio_file(char *infile, int samplerate, int channels,
21                 aufile->sndfile = stdout;
22         }
23         else
24 -               aufile->sndfile = fopen(infile, "wb");
25 +               aufile->sndfile = fopen_utf8(infile, "wb");
26  
27         if (aufile->sndfile == NULL){
28                 if (aufile)
29 diff --git a/oggdec.c b/oggdec.c
30 index f73095e..2064370 100644
31 --- a/oggdec.c
32 +++ b/oggdec.c
33 @@ -54,6 +54,8 @@
34  
35  #define ROUND64(x)   ( doubletmp = (x) + Dither.Add + (ogg_int64_t)0x001FFFFD80000000L, *(ogg_int64_t*)(&doubletmp) - (ogg_int64_t)0x433FFFFD80000000L )
36  
37 +#include "unicode_support.h"
38 +
39  typedef struct file_list
40  {
41         char *file_name;
42 @@ -64,8 +66,8 @@ typedef struct file_list
43  static void usage(void);
44  void file_error(const char *message, const char *filename);
45  void free_file_list(FILE_LIST *list, int free_names);
46 -char **glob(char *files[], int *count, int shuffle);
47 -void free_glob(char *file_names[]);
48 +//char **glob(char *files[], int *count, int shuffle);
49 +//void free_glob(char *file_names[]);
50  static int tag_compare(const char *s1, const char *s2, int n);
51  double get_scale(const char *filename, int album, int title);
52  
53 @@ -91,7 +93,7 @@ struct option long_options[] = {
54   * for the error in GetLastError(), in that order, as printf arguments for 
55   * the message body.
56   */
57 -void file_error(const char *message, const char *filename)
58 +static void file_error(const char *message, const char *filename)
59  {
60         LPVOID error;
61      
62 @@ -107,7 +109,7 @@ void file_error(const char *message, const char *filename)
63  /* Free a FILE_LIST list. If free_names is true, free the name 
64   * in each list entry as well.
65   */
66 -void free_file_list(FILE_LIST *list, int free_names)
67 +static void free_file_list(FILE_LIST *list, int free_names)
68  {
69         FILE_LIST *next;
70      
71 @@ -125,7 +127,6 @@ void free_file_list(FILE_LIST *list, int free_names)
72         }
73  }
74  
75 -
76  /* Expand any wildcards in the files array (with count entries). The 
77   * returned array is null terminated, and count is set to the number 
78   * of entries, excluding the null. If NULL is returned, an error has 
79 @@ -133,123 +134,124 @@ void free_file_list(FILE_LIST *list, int free_names)
80   *
81   * Call free_glob to free the memory allocated by this function.
82   */
83 -char **glob(char *files[], int *count, int shuffle)
84 -{
85 -       FILE_LIST         *first = NULL,
86 -                         *current,
87 -                         *previous = NULL;
88 -       WIN32_FIND_DATA   find_data;
89 -       HANDLE            *find_handle;
90 -       char              **file_names,
91 -                         *tmp;
92 -       int               file_count = 0,
93 -                         path_length = 0,
94 -                         i,
95 -                         j;
96 -    
97 -       for (i = 0; i < *count; ++i)
98 -       {
99 -               for (j = 0; j < strlen(files[i]); j++)
100 -               {
101 -                       if (files[i][j] == '\\')
102 -                       {
103 -                               path_length = j + 1;
104 -                       }
105 -               }
106 -        
107 -               find_handle = FindFirstFile(files[i], &find_data);
108 -        
109 -               if (INVALID_HANDLE_VALUE == find_handle)
110 -               {
111 -                       file_error(" Could not find '%s': %s", files[i]);
112 -                       files[i] = NULL;
113 -                       continue;
114 -               }
115 -        
116 -               do
117 -               {
118 -                       current = (struct file_list *) calloc(1, sizeof(struct file_list));
119 -                       current->file_name = calloc(path_length + strlen(find_data.cFileName) + 1, 1);
120 -            
121 -                       if (path_length)
122 -                       {
123 -                               strncpy(current->file_name, files[i], path_length);
124 -                               strcat(current->file_name, find_data.cFileName);
125 -                       }
126 -                       else
127 -                       {
128 -                               strcpy(current->file_name, find_data.cFileName);
129 -                       }
130 -            
131 -                       if (previous != NULL)
132 -                       {
133 -                               previous->next_file = current;
134 -                       }
135 -            
136 -                       if (first == NULL)
137 -                       {
138 -                               first = current;
139 -                       }
140 -            
141 -                       previous = current;
142 -                       file_count++;
143 -               } while (FindNextFile(find_handle, &find_data));
144 -        
145 -               if (GetLastError() != ERROR_NO_MORE_FILES)
146 -               {
147 -                       file_error(" Couldn't get more files for '%s': %s\n", files[i]);
148 -                       free_file_list(first, 1);
149 -                       files[i] = NULL;
150 -               }
151 -        
152 -               /* Can return error, but do we need to bother? */
153 -               FindClose(find_handle);
154 -       }
155 -    
156 -       file_names = (char **) calloc(file_count + 1, sizeof(char *));
157 -    
158 -       for (i = 0, current = first; current; current = current->next_file, i++)
159 -       {
160 -               file_names[i] = current->file_name;
161 -       }
162 -    
163 -       /* set up playlist */
164 -
165 -       if (shuffle)
166 -       {
167 -               srand(time(0));
168 -               /* initial shuffle */
169 -               for (i = 0; i < file_count; ++i)
170 -               {
171 -                       j = rand() % file_count;
172 -
173 -                       tmp = file_names[i];
174 -                       file_names[i] = file_names[j];
175 -                       file_names[j] = tmp;
176 -               }
177 -       }
178 -       free_file_list(first, 0);
179 -       *count = file_count;
180 -       return file_names;
181 -}
182 -
183 -
184 -/* Free memory allocated by glob. */
185 -void free_glob(char *file_names[])
186 -{
187 -       char **current;
188 -       int i = 0;
189 -
190 -       for (current = file_names; *current; current++)
191 -       {
192 -               free(*current);
193 -       }
194 -    
195 -       free(file_names);
196 -}
197 +//static char **glob(char *files[], int *count, int shuffle)
198 +//{
199 +//     FILE_LIST         *first = NULL,
200 +//                       *current,
201 +//                       *previous = NULL;
202 +//     WIN32_FIND_DATAW  find_data;
203 +//     HANDLE            *find_handle;
204 +//     char              **file_names,
205 +//                       *tmp;
206 +//     int               file_count = 0,
207 +//                       path_length = 0,
208 +//                       i,
209 +//                       j;
210 +//    
211 +//     for (i = 0; i < *count; ++i)
212 +//     {
213 +//             for (j = 0; j < strlen(files[i]); j++)
214 +//             {
215 +//                     if (files[i][j] == '\\')
216 +//                     {
217 +//                             path_length = j + 1;
218 +//                     }
219 +//             }
220 +//        
221 +//             find_handle = FindFirstFileUTF8(files[i], &find_data);
222 +//        
223 +//             if (INVALID_HANDLE_VALUE == find_handle)
224 +//             {
225 +//                     file_error(" Could not find '%s': %s", files[i]);
226 +//                     files[i] = NULL;
227 +//                     continue;
228 +//             }
229 +//        
230 +//             do
231 +//             {
232 +//                     current = (struct file_list *) calloc(1, sizeof(struct file_list));
233 +//                     current->file_name = calloc(path_length + strlen(find_data.cFileName) + 1, 1);
234 +//            
235 +//                     if (path_length)
236 +//                     {
237 +//                             strncpy(current->file_name, files[i], path_length);
238 +//                             strcat(current->file_name, find_data.cFileName);
239 +//                     }
240 +//                     else
241 +//                     {
242 +//                             strcpy(current->file_name, find_data.cFileName);
243 +//                     }
244 +//            
245 +//                     if (previous != NULL)
246 +//                     {
247 +//                             previous->next_file = current;
248 +//                     }
249 +//            
250 +//                     if (first == NULL)
251 +//                     {
252 +//                             first = current;
253 +//                     }
254 +//            
255 +//                     previous = current;
256 +//                     file_count++;
257 +//             }
258 +//             while (FindNextFile(find_handle, &find_data));
259 +//        
260 +//             if (GetLastError() != ERROR_NO_MORE_FILES)
261 +//             {
262 +//                     file_error(" Couldn't get more files for '%s': %s\n", files[i]);
263 +//                     free_file_list(first, 1);
264 +//                     files[i] = NULL;
265 +//             }
266 +//        
267 +//             /* Can return error, but do we need to bother? */
268 +//             FindClose(find_handle);
269 +//     }
270 +//    
271 +//     file_names = (char **) calloc(file_count + 1, sizeof(char *));
272 +//    
273 +//     for (i = 0, current = first; current; current = current->next_file, i++)
274 +//     {
275 +//             file_names[i] = current->file_name;
276 +//     }
277 +//    
278 +//     /* set up playlist */
279 +//
280 +//     if (shuffle)
281 +//     {
282 +//             srand(time(0));
283 +//             /* initial shuffle */
284 +//             for (i = 0; i < file_count; ++i)
285 +//             {
286 +//                     j = rand() % file_count;
287 +//
288 +//                     tmp = file_names[i];
289 +//                     file_names[i] = file_names[j];
290 +//                     file_names[j] = tmp;
291 +//             }
292 +//     }
293 +//     free_file_list(first, 0);
294 +//     *count = file_count;
295 +//     return file_names;
296 +//}
297 +//
298 +//
299 +///* Free memory allocated by glob. */
300 +//static void free_glob(char *file_names[])
301 +//{
302 +//     char **current;
303 +//     int i = 0;
304 +//
305 +//     for (current = file_names; *current; current++)
306 +//     {
307 +//             free(*current);
308 +//     }
309 +//    
310 +//     free(file_names);
311 +//}
312  
313  /* Dither output */
314 -ogg_int64_t dither_output(int dithering, int shapingtype, long i, double Sum, int k)
315 +static ogg_int64_t dither_output(int dithering, int shapingtype, long i, double Sum, int k)
316  {
317         double Sum2;
318         ogg_int64_t val;
319 @@ -280,7 +282,7 @@ ogg_int64_t dither_output(int dithering, int shapingtype, long i, double Sum, in
320  
321  /* This downmixes multi-channel vorbis to stereo
322   */
323 -void downmix_2_stereo(int channels, float **pcm, long samples)
324 +static void downmix_2_stereo(int channels, float **pcm, long samples)
325  {
326         /* Channels are in vorbis order NOT WAVEFORMATEXTENSIBLE */
327  
328 @@ -349,7 +351,7 @@ static int tag_compare(const char *s1, const char *s2, int n)
329   * the tags are found, it returns the scale value calculated from the
330   * tag, otherwise, it returns a scale value of 1.0.
331   */
332 -double get_scale(const char *filename, int album, int title)
333 +static double get_scale(const char *filename, int album, int title)
334  {
335         vcedit_state    *state = NULL;
336         vorbis_comment  *vc;
337 @@ -373,7 +375,7 @@ double get_scale(const char *filename, int album, int title)
338                 goto exit;
339         }
340  
341 -       file = fopen(filename, "rb");
342 +       file = fopen_utf8(filename, "rb");
343  
344         if (file == NULL)
345         {
346 @@ -517,7 +519,7 @@ exit:
347  
348  static void usage(void)
349  {
350 -       fprintf(stderr, " "VERSION_STRING"\n");
351 +       fprintf(stderr, " "VERSION_STRING"\n", vorbis_version_string());
352         fprintf(stderr, " Copyright (c) 2002-2014 John Edwards\n\n");
353         fprintf(stderr, " Usage: oggdec [options] input.ogg [...]\n\n");
354         fprintf(stderr, " OPTIONS\n");
355 @@ -557,7 +559,7 @@ static void usage(void)
356  }
357  
358  
359 -int main(int argc, char** argv)
360 +static int oggdec_main(int argc, char** argv)
361  {
362         OggVorbis_File     vf;
363         int                current_section;
364 @@ -743,7 +745,7 @@ int main(int argc, char** argv)
365  
366         if(optind >= argc)
367         {
368 -               fprintf(stderr, "ERROR: No input files specified, exiting.\n");
369 +               fprintf(stderr, "ERROR: No input files specified, exiting.\n\n");
370                 usage();
371                 exit(1);
372         }
373 @@ -753,10 +755,10 @@ int main(int argc, char** argv)
374                 file_count = argc - optind;
375         }
376  
377 -       file_names = glob(file_names, &file_count, shuffle);
378 +       //file_names = glob(file_names, &file_count, shuffle);
379  
380         if(out_file && file_count > 1) {
381 -               fprintf(stderr,"ERROR: Named output file only valid for single input file.\n");
382 +               fprintf(stderr,"ERROR: Named output file only valid for single input file.\n\n");
383                 usage();
384                 exit(1);
385         }
386 @@ -769,8 +771,7 @@ int main(int argc, char** argv)
387                 audio_file    *wav_out;
388  
389                 void          *sample_buffer;
390 -               char          *fileName,
391 -                             percents[64];
392 +               char          *fileName;
393                 int           eof = 0,
394                               infile = 1,
395                               outfile = 1,
396 @@ -783,6 +784,7 @@ int main(int argc, char** argv)
397                 double        samples_done = 0,
398                               file_size;
399                 ogg_int64_t   length;
400 +               clock_t       last_update = -1L;
401  
402                 if (file_names[i][0] == '\0')
403                 {
404 @@ -793,7 +795,7 @@ int main(int argc, char** argv)
405                  * ReplayGain tags, which tags are being used. 
406                  */
407                 if(!send_to_stdout)
408 -                       fprintf(stderr, "\n\n"VERSION_STRING"\n");
409 +                       fprintf(stderr, "\n\n"VERSION_STRING"\n", vorbis_version_string());
410  
411                 if(!send_to_stdout && (audiophile || radio))
412                 {
413 @@ -807,7 +809,7 @@ int main(int argc, char** argv)
414                 else
415                         scale = 1.0;
416  
417 -               if((ov_input = fopen(file_names[i], "rb")) == NULL)
418 +               if((ov_input = fopen_utf8(file_names[i], "rb")) == NULL)
419                 {
420                         fprintf(stderr, "\n ERROR: cannot open %s\n", file_names[i]);
421                         continue;
422 @@ -840,7 +842,7 @@ int main(int argc, char** argv)
423                         {
424                                 if ( Set_WIN_Params (INVALID_FILEDESC, vi->rate, SAMPLE_SIZE, channels, play_priority) < 0 )
425                                 {
426 -                                       fprintf (stderr, "\n"VERSION_STRING": Can't access %s\n", "WAVE OUT");
427 +                                       fprintf (stderr, "\n"VERSION_STRING": Can't access %s\n", vorbis_version_string(), "WAVE OUT");
428                                         ov_clear(&vf);
429                                         continue;
430                                 }
431 @@ -924,15 +926,26 @@ int main(int argc, char** argv)
432                                         samples_done += ret;
433                                         if(play_files)
434                                         {
435 -                                               length_secs = samples_done / vi->rate;  // time played in secs.
436 -                                               length_mins = length_secs / 60;
437 -                                               length_secs -= length_mins * 60;
438 -                                               fprintf(stderr," Played %d:%02d mins.\r", length_mins, length_secs);
439 +                                               const clock_t current_time = clock();
440 +                                               if ((current_time < 0) || (last_update < 0) || (current_time > last_update))
441 +                                               {
442 +                                                       length_secs = samples_done / vi->rate;  // time played in secs.
443 +                                                       length_mins = length_secs / 60;
444 +                                                       length_secs -= length_mins * 60;
445 +                                                       fprintf(stderr, "\r Played %d:%02d mins.", length_mins, length_secs);
446 +                                                       fflush(stderr);
447 +                                                       last_update = current_time + (CLOCKS_PER_SEC / 8L);
448 +                                               }
449                                         }
450                                         else if(!quiet)
451                                         {
452 -                                               sprintf(percents, "%4.0lf%% decoded.", (samples_done/file_size)*100);
453 -                                               fprintf(stderr, " %s\r", percents);
454 +                                               const clock_t current_time = clock();
455 +                                               if ((current_time < 0) || (last_update < 0) || (current_time > last_update))
456 +                                               {
457 +                                                       fprintf(stderr, "\r %5.1lf%% decoded.", (samples_done / file_size) * 100.0);
458 +                                                       fflush(stderr);
459 +                                                       last_update = current_time + (CLOCKS_PER_SEC / 8L);
460 +                                               }
461                                         }
462  
463                                         if (ret == 0) 
464 @@ -1012,6 +1025,11 @@ int main(int argc, char** argv)
465                                 }
466                         }
467                         /* Finished with this file, so cleanup. */
468 +                       if ((!play_files) && (!quiet))
469 +                       {
470 +                               fprintf(stderr, "\r %5.1lf%% decoded.", 100.0);
471 +                               fflush(stderr);
472 +                       }
473                         if(play_files)
474                                 WIN_Audio_close();
475                         else
476 @@ -1025,4 +1043,20 @@ int main(int argc, char** argv)
477         return(0);
478  }
479  
480 +int main(int argc, char **argv)
481 +{
482 +       int argc_utf8, exit_code;
483 +       char **argv_utf8;
484 +
485 +       init_console_utf8();
486 +       init_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
487 +
488 +       exit_code = oggdec_main(argc_utf8, argv_utf8);
489 +
490 +       free_commandline_arguments_utf8(&argc_utf8, &argv_utf8);
491 +       uninit_console_utf8();
492 +
493 +       return exit_code;
494 +}
495 +
496  /* **************************************** end of oggdec.c ******************************************* */
497 diff --git a/unicode_support.c b/unicode_support.c
498 new file mode 100644
499 index 0000000..cf8a1e1
500 --- /dev/null
501 +++ b/unicode_support.c
502 @@ -0,0 +1,197 @@
503 +/* Copyright (c) 2004-2012 LoRd_MuldeR <mulder2@gmx.de>
504 +   File: unicode_support.c
505 +
506 +   This file was originally part of a patch included with LameXP,
507 +   released under the same license as the original audio tools.
508 +
509 +   Redistribution and use in source and binary forms, with or without
510 +   modification, are permitted provided that the following conditions
511 +   are met:
512 +
513 +   - Redistributions of source code must retain the above copyright
514 +   notice, this list of conditions and the following disclaimer.
515 +
516 +   - Redistributions in binary form must reproduce the above copyright
517 +   notice, this list of conditions and the following disclaimer in the
518 +   documentation and/or other materials provided with the distribution.
519 +
520 +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
521 +   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
522 +   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
523 +   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
524 +   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
525 +   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
526 +   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
527 +   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
528 +   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
529 +   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
530 +   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
531 +*/
532 +#if defined WIN32 || defined _WIN32
533 +
534 +# include "unicode_support.h"
535 +
536 +# include <windows.h>
537 +# include <io.h>
538 +
539 +static UINT g_old_output_cp = ((UINT)-1);
540 +
541 +char *utf16_to_utf8(const wchar_t *input)
542 +{
543 +       char *Buffer;
544 +       int BuffSize = 0, Result = 0;
545 +
546 +       BuffSize = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL);
547 +       Buffer = (char*) malloc(sizeof(char) * BuffSize);
548 +       if(Buffer)
549 +       {
550 +               Result = WideCharToMultiByte(CP_UTF8, 0, input, -1, Buffer, BuffSize, NULL, NULL);
551 +       }
552 +
553 +       return ((Result > 0) && (Result <= BuffSize)) ? Buffer : NULL;
554 +}
555 +
556 +char *utf16_to_ansi(const wchar_t *input)
557 +{
558 +       char *Buffer;
559 +       int BuffSize = 0, Result = 0;
560 +
561 +       BuffSize = WideCharToMultiByte(CP_ACP, 0, input, -1, NULL, 0, NULL, NULL);
562 +       Buffer = (char*) malloc(sizeof(char) * BuffSize);
563 +       if(Buffer)
564 +       {
565 +               Result = WideCharToMultiByte(CP_ACP, 0, input, -1, Buffer, BuffSize, NULL, NULL);
566 +       }
567 +
568 +       return ((Result > 0) && (Result <= BuffSize)) ? Buffer : NULL;
569 +}
570 +
571 +wchar_t *utf8_to_utf16(const char *input)
572 +{
573 +       wchar_t *Buffer;
574 +       int BuffSize = 0, Result = 0;
575 +
576 +       BuffSize = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
577 +       Buffer = (wchar_t*) malloc(sizeof(wchar_t) * BuffSize);
578 +       if(Buffer)
579 +       {
580 +               Result = MultiByteToWideChar(CP_UTF8, 0, input, -1, Buffer, BuffSize);
581 +       }
582 +
583 +       return ((Result > 0) && (Result <= BuffSize)) ? Buffer : NULL;
584 +}
585 +
586 +void init_commandline_arguments_utf8(int *argc, char ***argv)
587 +{
588 +       int i, nArgs;
589 +       LPWSTR *szArglist;
590 +
591 +       szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
592 +
593 +       if(NULL == szArglist)
594 +       {
595 +               fprintf(stderr, "\nFATAL: CommandLineToArgvW failed\n\n");
596 +               exit(-1);
597 +       }
598 +
599 +       *argv = (char**) malloc(sizeof(char*) * nArgs);
600 +       *argc = nArgs;
601 +
602 +       if(NULL == *argv)
603 +       {
604 +               fprintf(stderr, "\nFATAL: Malloc failed\n\n");
605 +               exit(-1);
606 +       }
607 +       
608 +       for(i = 0; i < nArgs; i++)
609 +       {
610 +               (*argv)[i] = utf16_to_utf8(szArglist[i]);
611 +               if(NULL == (*argv)[i])
612 +               {
613 +                       fprintf(stderr, "\nFATAL: utf16_to_utf8 failed\n\n");
614 +                       exit(-1);
615 +               }
616 +       }
617 +
618 +       LocalFree(szArglist);
619 +}
620 +
621 +void free_commandline_arguments_utf8(int *argc, char ***argv)
622 +{
623 +       int i = 0;
624 +       
625 +       if(*argv != NULL)
626 +       {
627 +               for(i = 0; i < *argc; i++)
628 +               {
629 +                       if((*argv)[i] != NULL)
630 +                       {
631 +                               free((*argv)[i]);
632 +                               (*argv)[i] = NULL;
633 +                       }
634 +               }
635 +               free(*argv);
636 +               *argv = NULL;
637 +       }
638 +}
639 +
640 +FILE *fopen_utf8(const char *filename_utf8, const char *mode_utf8)
641 +{
642 +       FILE *ret = NULL;
643 +       wchar_t *filename_utf16 = utf8_to_utf16(filename_utf8);
644 +       wchar_t *mode_utf16 = utf8_to_utf16(mode_utf8);
645 +       
646 +       if(filename_utf16 && mode_utf16)
647 +       {
648 +               ret = _wfopen(filename_utf16, mode_utf16);
649 +       }
650 +
651 +       if(filename_utf16) free(filename_utf16);
652 +       if(mode_utf16) free(mode_utf16);
653 +
654 +       return ret;
655 +}
656 +
657 +int stat_utf8(const char *path_utf8, struct _stat *buf)
658 +{
659 +       int ret = -1;
660 +       
661 +       wchar_t *path_utf16 = utf8_to_utf16(path_utf8);
662 +       if(path_utf16)
663 +       {
664 +               ret = _wstat(path_utf16, buf);
665 +               free(path_utf16);
666 +       }
667 +       
668 +       return ret;
669 +}
670 +
671 +int unlink_utf8(const char *path_utf8)
672 +{
673 +       int ret = -1;
674 +       
675 +       wchar_t *path_utf16 = utf8_to_utf16(path_utf8);
676 +       if(path_utf16)
677 +       {
678 +               ret = _wunlink(path_utf16);
679 +               free(path_utf16);
680 +       }
681 +       
682 +       return ret;
683 +}
684 +
685 +void init_console_utf8(void)
686 +{
687 +       g_old_output_cp = GetConsoleOutputCP();
688 +       SetConsoleOutputCP(CP_UTF8);
689 +}
690 +
691 +void uninit_console_utf8(void)
692 +{
693 +       if(g_old_output_cp != ((UINT)-1))
694 +       {
695 +               SetConsoleOutputCP(g_old_output_cp);
696 +       }
697 +}
698 +
699 +#endif
700 diff --git a/unicode_support.h b/unicode_support.h
701 new file mode 100644
702 index 0000000..40c2e33
703 --- /dev/null
704 +++ b/unicode_support.h
705 @@ -0,0 +1,49 @@
706 +/* Copyright (c) 2004-2012 LoRd_MuldeR <mulder2@gmx.de>
707 +   File: unicode_support.h
708 +
709 +   This file was originally part of a patch included with LameXP,
710 +   released under the same license as the original audio tools.
711 +
712 +   Redistribution and use in source and binary forms, with or without
713 +   modification, are permitted provided that the following conditions
714 +   are met:
715 +
716 +   - Redistributions of source code must retain the above copyright
717 +   notice, this list of conditions and the following disclaimer.
718 +
719 +   - Redistributions in binary form must reproduce the above copyright
720 +   notice, this list of conditions and the following disclaimer in the
721 +   documentation and/or other materials provided with the distribution.
722 +
723 +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
724 +   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
725 +   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
726 +   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
727 +   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
728 +   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
729 +   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
730 +   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
731 +   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
732 +   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
733 +   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
734 +*/
735 +#ifndef UNICODE_SUPPORT_H_INCLUDED
736 +#define UNICODE_SUPPORT_H_INCLUDED
737 +
738 +#include <stdio.h>
739 +#include <sys/stat.h>
740 +
741 +#define WIN_UNICODE 1
742 +
743 +char *utf16_to_utf8(const wchar_t *input);
744 +char *utf16_to_ansi(const wchar_t *input);
745 +wchar_t *utf8_to_utf16(const char *input);
746 +void init_commandline_arguments_utf8(int *argc, char ***argv);
747 +void free_commandline_arguments_utf8(int *argc, char ***argv);
748 +FILE *fopen_utf8(const char *filename_utf8, const char *mode_utf8);
749 +int stat_utf8(const char *path_utf8, struct _stat *buf);
750 +int unlink_utf8(const char *path_utf8);
751 +void init_console_utf8(void);
752 +void uninit_console_utf8(void);
753 +
754 +#endif
755 diff --git a/wave_out.h b/wave_out.h
756 index 608f2e5..4ecdcdc 100644
757 --- a/wave_out.h
758 +++ b/wave_out.h
759 @@ -1,6 +1,6 @@
760  //    WAVE_OUT.H - Necessary stuff for WIN_AUDIO
761  
762 -#define VERSION_STRING "OggDec v1.10.1 (libVorbis 1.3.4) Compiled on: " __DATE__ ""
763 +#define VERSION_STRING "OggDec v1.10.1 (%s), Compiled on: " __DATE__ ""
764  
765  #include <stdio.h>
766  #include <windows.h>