flac_mac patches from Janne Hyvärinen <cse@sci.fi>.
[platform/upstream/flac.git] / src / monkeys_audio_utilities / flac_mac / main.c
1 /* flac_mac - wedge utility to add FLAC support to Monkey's Audio
2  * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 /*
20  * This program can be used to allow FLAC to masquerade as one of the other
21  * supported lossless codecs in Monkey's Audio.  See the documentation for
22  * how to do this.
23  */
24
25 #if HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include<stdio.h>
30 #include<stdlib.h>
31 #include<string.h>
32 #include<wtypes.h>
33 #include<process.h>
34 #include<winbase.h>
35
36 #include "share/compat.h"
37 #include "share/safe_str.h"
38
39 static int execit(char *prog, char *args);
40 static int forkit(char *prog, char *args);
41
42 int main(int argc, char *argv[])
43 {
44         int flac_return_val = 0, opt_arg = 1, from_arg = -1, to_arg = -1, flac_level = 5, i;
45         char prog[MAX_PATH], cmdline[MAX_PATH*2], from[MAX_PATH], to[MAX_PATH], macdir[MAX_PATH], options[256], *p;
46         enum { WAVPACK, RKAU, SHORTEN } codec;
47
48         /* get the directory where MAC external codecs reside */
49         if(0 != (p = strrchr(argv[0],'\\'))) {
50                 safe_strncpy(macdir, argv[0], sizeof(macdir));
51                 *(strrchr(macdir,'\\')+1) = '\0';
52         }
53         else {
54                 safe_strncpy(macdir, "", sizeof(macdir));
55         }
56
57         /* determine which codec we were called as and parse the options */
58         if(p == 0)
59                 p = argv[0];
60         else
61                 p++;
62         if(0 == strnicmp(p, "short", 5)) {
63                 codec = SHORTEN;
64         }
65         else if(0 == strnicmp(p, "rkau", 4)) {
66                 codec = RKAU;
67                 if(argv[1][0] == '-' && argv[1][1] == 'l') {
68                         opt_arg = 2;
69                         switch(argv[1][2]) {
70                                 case '1': flac_level = 1; break;
71                                 case '2': flac_level = 5; break;
72                                 case '3': flac_level = 8; break;
73                         }
74                 }
75         }
76         else if(0 == strnicmp(p, "wavpack", 7)) {
77                 codec = WAVPACK;
78                 if(argv[1][0] == '-') {
79                         opt_arg = 2;
80                         switch(argv[1][1]) {
81                                 case 'f': flac_level = 1; break;
82                                 case 'h': flac_level = 8; break;
83                                 default: opt_arg = 1;
84                         }
85                 }
86         }
87         else {
88                 return -5;
89         }
90
91         /* figure out which arguments are the source and destination files */
92         for(i = 1; i < argc; i++)
93                 if(argv[i][0] != '-') {
94                         from_arg = i++;
95                         break;
96                 }
97         for( ; i < argc; i++)
98                 if(argv[i][0] != '-') {
99                         to_arg = i++;
100                         break;
101                 }
102         if(to_arg < 0)
103                 return -4;
104
105         /* build the command to call flac with */
106         flac_snprintf(prog, sizeof (prog), "%sflac.exe", macdir);
107         flac_snprintf(options, sizeof (options), "-%d", flac_level);
108         for(i = opt_arg; i < argc; i++)
109                 if(argv[i][0] == '-') {
110                         safe_strncat(options, " ", sizeof(options));
111                         safe_strncat(options, argv[i], sizeof(options));
112                 }
113         flac_snprintf(cmdline, sizeof (cmdline), "\"%s\" %s -o \"%s\" \"%s\"", prog, options, argv[to_arg], argv[from_arg]);
114
115         flac_return_val = execit(prog, cmdline);
116
117         /*
118          * Now that flac has finished, we need to fork a process that will rename
119          * the resulting file with the correct extension once MAC has moved it to
120          * it's final resting place.
121          */
122         if(0 == flac_return_val) {
123                 char *cptr;
124                 /* get the destination directory, if any */
125                 if(0 != (p = strchr(argv[to_arg],'\\'))) {
126                         safe_strncpy(from, argv[to_arg], sizeof(from));
127                         *(strrchr(from,'\\')+1) = '\0';
128                 }
129                 else {
130                         safe_strncpy(from, "", sizeof(from));
131                 }
132
133                 /* for the full 'from' and 'to' paths for the renamer process */
134                 p = strrchr(argv[from_arg],'\\');
135                 safe_strncat(from, p? p+1 : argv[from_arg], sizeof(from));
136                 safe_strncpy(to, from, sizeof(to), sizeof(to));
137
138                 cptr = strrchr(from,'.');
139                 if(cptr == NULL)
140                         return -3;
141                 cptr [0] = 0;
142
143                 switch(codec) {
144                         case SHORTEN:
145                                 safe_strncat(from, ".shn", sizeof (from));
146                                 break;
147                         case WAVPACK:
148                                 safe_strncat(from, ".wv", sizeof (from));
149                                 break;
150                         case RKAU:
151                                 safe_strncpy(from, ".rka", sizeof (from));
152                                 break;
153                         default:
154                                 return -4;
155                 }
156
157                 cptr = strrchr(to,'.');
158                 if(cptr == NULL)
159                         return -3;
160                 cptr [0] = 0;
161
162                 safe_strncat(to, ".flac", sizeof(to));
163
164                 flac_snprintf(prog, sizeof (prog), "%sflac_ren.exe", macdir);
165                 flac_snprintf(cmdline, sizeof (cmdline), "\"%s\" \"%s\" \"%s\"", prog, from, to);
166
167                 flac_return_val = forkit(prog, cmdline);
168         }
169
170         return flac_return_val;
171 }
172
173 int execit(char *prog, char *args)
174 {
175         BOOL ok;
176         STARTUPINFO startup_info;
177         PROCESS_INFORMATION proc_info;
178
179         GetStartupInfo(&startup_info);
180
181         ok = CreateProcess(
182                 prog,
183                 args,
184                 0, /*process security attributes*/
185                 0, /*thread security attributes*/
186                 FALSE,
187                 0, /*dwCreationFlags*/
188                 0, /*environment*/
189                 0, /*lpCurrentDirectory*/
190                 &startup_info,
191                 &proc_info
192         );
193         if(ok) {
194                 DWORD dw;
195                 dw = WaitForSingleObject(proc_info.hProcess, INFINITE);
196                 ok = (dw != 0xFFFFFFFF);
197                 CloseHandle(proc_info.hThread);
198                 CloseHandle(proc_info.hProcess);
199         }
200
201         return ok? 0 : -1;
202 }
203
204 int forkit(char *prog, char *args)
205 {
206         BOOL ok;
207         STARTUPINFO startup_info;
208         PROCESS_INFORMATION proc_info;
209
210         GetStartupInfo(&startup_info);
211
212         ok = CreateProcess(
213                 prog,
214                 args,
215                 0, /*process security attributes*/
216                 0, /*thread security attributes*/
217                 FALSE,
218                 DETACHED_PROCESS, /*dwCreationFlags*/
219                 0, /*environment*/
220                 0, /*lpCurrentDirectory*/
221                 &startup_info,
222                 &proc_info
223         );
224         if(ok) {
225                 CloseHandle(proc_info.hThread);
226                 CloseHandle(proc_info.hProcess);
227         }
228
229         return ok? 0 : -2;
230 }