Remove compatibility workarounds
[x264/x264-sandbox.git] / autocomplete.c
1 /*****************************************************************************
2  * autocomplete: x264cli shell autocomplete
3  *****************************************************************************
4  * Copyright (C) 2018-2019 x264 project
5  *
6  * Authors: Henrik Gramner <henrik@gramner.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
21  *
22  * This program is also available under a commercial proprietary license.
23  * For more information, contact us at licensing@x264.com.
24  *****************************************************************************/
25
26 #include "x264cli.h"
27 #include "input/input.h"
28
29 #if HAVE_LAVF
30 #include <libavformat/avformat.h>
31 #include <libavutil/pixdesc.h>
32 #endif
33
34 static const char * const level_names[] =
35 {
36     "1", "1.1", "1.2", "1.3", "1b",
37     "2", "2.1", "2.2",
38     "3", "3.1", "3.2",
39     "4", "4.1", "4.2",
40     "5", "5.1", "5.2",
41     "6", "6.1", "6.2",
42     NULL
43 };
44
45 /* Options requiring a value for which we provide suggestions. */
46 static const char * const opts_suggest[] =
47 {
48     "--alternative-transfer",
49     "--aq-mode",
50     "--asm",
51     "--avcintra-class",
52     "--avcintra-flavor",
53     "--b-adapt",
54     "--b-pyramid",
55     "--colormatrix",
56     "--colorprim",
57     "--cqm",
58     "--demuxer",
59     "--direct",
60     "--frame-packing",
61     "--input-csp",
62     "--input-fmt",
63     "--input-range",
64     "--level",
65     "--log-level",
66     "--me",
67     "--muxer",
68     "--nal-hrd",
69     "--output-csp",
70     "--overscan",
71     "--pass", "-p",
72     "--preset",
73     "--profile",
74     "--pulldown",
75     "--range",
76     "--subme", "-m",
77     "--transfer",
78     "--trellis", "-t",
79     "--tune",
80     "--videoformat",
81     "--weightp",
82     NULL
83 };
84
85 /* Options requiring a value for which we don't provide suggestions. */
86 static const char * const opts_nosuggest[] =
87 {
88     "--b-bias",
89     "--bframes", "-b",
90     "--deblock", "-f",
91     "--bitrate", "-B",
92     "--chroma-qp-offset",
93     "--chromaloc",
94     "--cplxblur",
95     "--cqm4",
96     "--cqm4i",
97     "--cqm4ic",
98     "--cqm4iy",
99     "--cqm4p",
100     "--cqm4pc",
101     "--cqm4py",
102     "--cqm8",
103     "--cqm8i",
104     "--cqm8p",
105     "--crf",
106     "--crf-max",
107     "--crop-rect",
108     "--deadzone-inter",
109     "--deadzone-intra",
110     "--fps",
111     "--frames",
112     "--input-depth",
113     "--input-res",
114     "--ipratio",
115     "--keyint", "-I",
116     "--lookahead-threads",
117     "--merange",
118     "--min-keyint", "-i",
119     "--mvrange",
120     "--mvrange-thread",
121     "--nr",
122     "--opencl-device",
123     "--output-depth",
124     "--partitions", "-A",
125     "--pbratio",
126     "--psy-rd",
127     "--qblur",
128     "--qcomp",
129     "--qp", "-q",
130     "--qpmax",
131     "--qpmin",
132     "--qpstep",
133     "--ratetol",
134     "--ref", "-r",
135     "--rc-lookahead",
136     "--sar",
137     "--scenecut",
138     "--seek",
139     "--slices",
140     "--slices-max",
141     "--slice-max-size",
142     "--slice-max-mbs",
143     "--slice-min-mbs",
144     "--sps-id",
145     "--sync-lookahead",
146     "--threads",
147     "--timebase",
148     "--vbv-bufsize",
149     "--vbv-init",
150     "--vbv-maxrate",
151     "--video-filter", "--vf",
152     "--zones",
153     NULL
154 };
155
156 /* Options requiring a filename. */
157 static const char * const opts_filename[] =
158 {
159     "--cqmfile",
160     "--dump-yuv",
161     "--index",
162     "--opencl-clbin",
163     "--output", "-o",
164     "--qpfile",
165     "--stats",
166     "--tcfile-in",
167     "--tcfile-out",
168     NULL
169 };
170
171 /* Options without an associated value. */
172 static const char * const opts_standalone[] =
173 {
174     "--8x8dct",
175     "--aud",
176     "--bff",
177     "--bluray-compat",
178     "--cabac",
179     "--constrained-intra",
180     "--cpu-independent",
181     "--dts-compress",
182     "--fake-interlaced",
183     "--fast-pskip",
184     "--filler",
185     "--force-cfr",
186     "--mbtree",
187     "--mixed-refs",
188     "--no-8x8dct",
189     "--no-asm",
190     "--no-cabac",
191     "--no-chroma-me",
192     "--no-dct-decimate",
193     "--no-deblock",
194     "--no-fast-pskip",
195     "--no-mbtree",
196     "--no-mixed-refs",
197     "--no-progress",
198     "--no-psy",
199     "--no-scenecut",
200     "--no-weightb",
201     "--non-deterministic",
202     "--open-gop",
203     "--opencl",
204     "--pic-struct",
205     "--psnr",
206     "--quiet",
207     "--sliced-threads",
208     "--slow-firstpass",
209     "--ssim",
210     "--stitchable",
211     "--tff",
212     "--thread-input",
213     "--verbose", "-v",
214     "--weightb",
215     NULL
216 };
217
218 /* Options which shouldn't be suggested in combination with other options. */
219 static const char * const opts_special[] =
220 {
221     "--fullhelp",
222     "--help", "-h",
223     "--longhelp",
224     "--version",
225     NULL
226 };
227
228 static int list_contains( const char * const *list, const char *s )
229 {
230     if( *s )
231         for( ; *list; list++ )
232             if( !strcmp( *list, s ) )
233                 return 1;
234     return 0;
235 }
236
237 static void suggest( const char *s, const char *cur, int cur_len )
238 {
239     if( s && *s && !strncmp( s, cur, cur_len ) )
240         printf( "%s\n", s );
241 }
242
243 static void suggest_lower( const char *s, const char *cur, int cur_len )
244 {
245     if( s && *s && !strncasecmp( s, cur, cur_len ) )
246     {
247         for( ; *s; s++ )
248             putchar( *s < 'A' || *s > 'Z' ? *s : *s | 0x20 );
249         putchar( '\n' );
250     }
251 }
252
253 static void suggest_num_range( int start, int end, const char *cur, int cur_len )
254 {
255     char buf[16];
256     for( int i = start; i <= end; i++ )
257     {
258         snprintf( buf, sizeof( buf ), "%d", i );
259         suggest( buf, cur, cur_len );
260     }
261 }
262
263 #if HAVE_LAVF
264 /* Suggest each token in a string separated by delimiters. */
265 static void suggest_token( const char *s, int delim, const char *cur, int cur_len )
266 {
267     if( s && *s )
268     {
269         for( const char *tok_end; (tok_end = strchr( s, delim )); s = tok_end + 1 )
270         {
271             int tok_len = tok_end - s;
272             if( tok_len && tok_len >= cur_len && !strncmp( s, cur, cur_len ) )
273                 printf( "%.*s\n", tok_len, s );
274         }
275         suggest( s, cur, cur_len );
276     }
277 }
278 #endif
279
280 #define OPT( opt ) else if( !strcmp( prev, opt ) )
281 #define OPT2( opt1, opt2 ) else if( !strcmp( prev, opt1 ) || !strcmp( prev, opt2 ) )
282 #define OPT_TYPE( type ) list_contains( opts_##type, prev )
283
284 #define suggest( s ) suggest( s, cur, cur_len )
285 #define suggest_lower( s ) suggest_lower( s, cur, cur_len )
286 #define suggest_list( list ) for( const char * const *s = list; *s; s++ ) suggest( *s )
287 #define suggest_num_range( start, end ) suggest_num_range( start, end, cur, cur_len )
288 #define suggest_token( s, delim ) suggest_token( s, delim, cur, cur_len )
289
290 int x264_cli_autocomplete( const char *prev, const char *cur )
291 {
292     int cur_len = strlen( cur );
293     if( 0 );
294     OPT( "--alternative-transfer" )
295         suggest_list( x264_transfer_names );
296     OPT( "--aq-mode" )
297         suggest_num_range( 0, 3 );
298     OPT( "--asm" )
299         for( const x264_cpu_name_t *cpu = x264_cpu_names; cpu->flags; cpu++ )
300             suggest_lower( cpu->name );
301     OPT( "--avcintra-class" )
302         suggest_list( x264_avcintra_class_names );
303     OPT( "--avcintra-flavor" )
304         suggest_list( x264_avcintra_flavor_names );
305     OPT( "--b-adapt" )
306         suggest_num_range( 0, 2 );
307     OPT( "--b-pyramid" )
308         suggest_list( x264_b_pyramid_names );
309     OPT( "--colormatrix" )
310         suggest_list( x264_colmatrix_names );
311     OPT( "--colorprim" )
312         suggest_list( x264_colorprim_names );
313     OPT( "--cqm" )
314         suggest_list( x264_cqm_names );
315     OPT( "--demuxer" )
316         suggest_list( x264_demuxer_names );
317     OPT( "--direct" )
318         suggest_list( x264_direct_pred_names );
319     OPT( "--frame-packing" )
320         suggest_num_range( 0, 7 );
321     OPT( "--input-csp" )
322     {
323         for( int i = X264_CSP_NONE+1; i < X264_CSP_CLI_MAX; i++ )
324             suggest( x264_cli_csps[i].name );
325 #if HAVE_LAVF
326         for( const AVPixFmtDescriptor *d = NULL; (d = av_pix_fmt_desc_next( d )); )
327             suggest( d->name );
328 #endif
329     }
330     OPT( "--input-fmt" )
331     {
332 #if HAVE_LAVF
333         av_register_all();
334         for( const AVInputFormat *f = NULL; (f = av_iformat_next( f )); )
335             suggest_token( f->name, ',' );
336 #endif
337     }
338     OPT( "--input-range" )
339         suggest_list( x264_range_names );
340     OPT( "--level" )
341         suggest_list( level_names );
342     OPT( "--log-level" )
343         suggest_list( x264_log_level_names );
344     OPT( "--me" )
345         suggest_list( x264_motion_est_names );
346     OPT( "--muxer" )
347         suggest_list( x264_muxer_names );
348     OPT( "--nal-hrd" )
349         suggest_list( x264_nal_hrd_names );
350     OPT( "--output-csp" )
351         suggest_list( x264_output_csp_names );
352     OPT( "--output-depth" )
353     {
354 #if HAVE_BITDEPTH8
355         suggest( "8" );
356 #endif
357 #if HAVE_BITDEPTH10
358         suggest( "10" );
359 #endif
360     }
361     OPT( "--overscan" )
362         suggest_list( x264_overscan_names );
363     OPT2( "--partitions", "-A" )
364         suggest_list( x264_partition_names );
365     OPT2( "--pass", "-p" )
366         suggest_num_range( 1, 3 );
367     OPT( "--preset" )
368         suggest_list( x264_preset_names );
369     OPT( "--profile" )
370         suggest_list( x264_valid_profile_names );
371     OPT( "--pulldown" )
372         suggest_list( x264_pulldown_names );
373     OPT( "--range" )
374         suggest_list( x264_range_names );
375     OPT2( "--subme", "-m" )
376         suggest_num_range( 0, 11 );
377     OPT( "--transfer" )
378         suggest_list( x264_transfer_names );
379     OPT2( "--trellis", "-t" )
380         suggest_num_range( 0, 2 );
381     OPT( "--tune" )
382         suggest_list( x264_tune_names );
383     OPT( "--videoformat" )
384         suggest_list( x264_vidformat_names );
385     OPT( "--weightp" )
386         suggest_num_range( 0, 2 );
387     else if( !OPT_TYPE( nosuggest ) && !OPT_TYPE( special ) )
388     {
389         if( OPT_TYPE( filename ) || strncmp( cur, "--", 2 ) )
390             return 1; /* Fall back to default shell filename autocomplete. */
391
392         /* Suggest options. */
393         suggest_list( opts_suggest );
394         suggest_list( opts_nosuggest );
395         suggest_list( opts_filename );
396         suggest_list( opts_standalone );
397
398         /* Only suggest special options if no other options have been specified. */
399         if( !*prev )
400             suggest_list( opts_special );
401     }
402
403     return 0;
404 }