1 /*****************************************************************************
2 * lwinput.c
3 *****************************************************************************
4 * Copyright (C) 2011-2015 L-SMASH Works project
5 *
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
20
21 /* This file is available under an ISC license.
22 * However, when distributing its binary file, it will be under LGPL or GPL.
23 * Don't distribute it if its license is GPL. */
24
25 #include "lwinput.h"
26 #include "resource.h"
27
28 #include "config.h"
29
30 #include <commctrl.h>
31
32 #include <libavutil/channel_layout.h>
33 /* Version */
34 #include <libavutil/version.h>
35 #include <libavcodec/version.h>
36 #include <libavformat/version.h>
37 #include <libswscale/version.h>
38 #include <libavresample/version.h>
39 /* License */
40 #include <libavutil/avutil.h>
41 #include <libavcodec/avcodec.h>
42 #include <libavformat/avformat.h>
43 #include <libswscale/swscale.h>
44 #include <libavresample/avresample.h>
45
46 #define MAX_AUTO_NUM_THREADS 16
47
48 #define MPEG4_FILE_EXT "*.mp4;*.m4v;*.m4a;*.mov;*.qt;*.3gp;*.3g2;*.f4v;*.ismv;*.isma"
49 #define INDEX_FILE_EXT "*.lwi"
50 #define ANY_FILE_EXT "*.*"
51
52 static char plugin_information[512] = { 0 };
53
get_plugin_information(void)54 static void get_plugin_information( void )
55 {
56 sprintf( plugin_information,
57 "L-SMASH Works File Reader r%s\n"
58 " libavutil %s: %s / libavcodec %s: %s\n"
59 " libavformat %s: %s / libswscale %s: %s\n"
60 " libavresample %s: %s",
61 LSMASHWORKS_REV,
62 AV_STRINGIFY( LIBAVUTIL_VERSION ), avutil_license (),
63 AV_STRINGIFY( LIBAVCODEC_VERSION ), avcodec_license (),
64 AV_STRINGIFY( LIBAVFORMAT_VERSION ), avformat_license (),
65 AV_STRINGIFY( LIBSWSCALE_VERSION ), swscale_license (),
66 AV_STRINGIFY( LIBAVRESAMPLE_VERSION ), avresample_license() );
67 }
68
69 INPUT_PLUGIN_TABLE input_plugin_table =
70 {
71 INPUT_PLUGIN_FLAG_VIDEO | INPUT_PLUGIN_FLAG_AUDIO, /* INPUT_PLUGIN_FLAG_VIDEO : support images
72 * INPUT_PLUGIN_FLAG_AUDIO : support audio */
73 "L-SMASH Works File Reader", /* Name of plugin */
74 "MPEG-4 File (" MPEG4_FILE_EXT ")\0" MPEG4_FILE_EXT "\0" /* Filter for Input file */
75 "LW-Libav Index File (" INDEX_FILE_EXT ")\0" INDEX_FILE_EXT "\0"
76 "Any File (" ANY_FILE_EXT ")\0" ANY_FILE_EXT "\0",
77 "L-SMASH Works File Reader r" LSMASHWORKS_REV "\0", /* Information of plugin */
78 NULL, /* Pointer to function called when opening DLL (If NULL, won't be called.) */
79 NULL, /* Pointer to function called when closing DLL (If NULL, won't be called.) */
80 func_open, /* Pointer to function to open input file */
81 func_close, /* Pointer to function to close input file */
82 func_info_get, /* Pointer to function to get information of input file */
83 func_read_video, /* Pointer to function to read image data */
84 func_read_audio, /* Pointer to function to read audio data */
85 func_is_keyframe, /* Pointer to function to check if it is a keyframe or not (If NULL, all is keyframe.) */
86 func_config, /* Pointer to function called when configuration dialog is required */
87 };
88
GetInputPluginTable(void)89 EXTERN_C INPUT_PLUGIN_TABLE __declspec(dllexport) * __stdcall GetInputPluginTable( void )
90 {
91 return &input_plugin_table;
92 }
93
94 static reader_option_t reader_opt = { 0 };
95 static video_option_t *video_opt = &reader_opt.video_opt;
96 static audio_option_t *audio_opt = &reader_opt.audio_opt;
97 static int reader_disabled[5] = { 0 };
98 static int audio_delay = 0;
99 static char *settings_path = NULL;
100 static const char *settings_path_list[] = { "lsmash.ini", "plugins/lsmash.ini" };
101 static const char *seek_mode_list[] = { "Normal", "Unsafe", "Aggressive" };
102 static const char *dummy_colorspace_list[] = { "YUY2", "RGB", "YC48" };
103 static const char *scaler_list[] = { "Fast bilinear", "Bilinear", "Bicubic", "Experimental", "Nearest neighbor", "Area averaging",
104 "L-bicubic/C-bilinear", "Gaussian", "Sinc", "Lanczos", "Bicubic spline" };
105 static const char *field_dominance_list[] = { "Obey source flags", "Top -> Bottom", "Bottom -> Top" };
106 static const char *avs_bit_depth_list[] = { "8", "9", "10", "16" };
107
au_message_box_desktop(lw_log_handler_t * lhp,lw_log_level level,const char * message)108 void au_message_box_desktop
109 (
110 lw_log_handler_t *lhp,
111 lw_log_level level,
112 const char *message
113 )
114 {
115 UINT uType = *(UINT *)lhp->priv;
116 MessageBox( HWND_DESKTOP, message, "lwinput", uType );
117 }
118
open_settings(void)119 static FILE *open_settings( void )
120 {
121 FILE *ini = NULL;
122 for( int i = 0; i < 2; i++ )
123 {
124 ini = fopen( settings_path_list[i], "rb" );
125 if( ini )
126 {
127 settings_path = (char *)settings_path_list[i];
128 return ini;
129 }
130 }
131 return NULL;
132 }
133
get_auto_threads(void)134 static int get_auto_threads( void )
135 {
136 int n = atoi( getenv( "NUMBER_OF_PROCESSORS" ) );
137 if( n > MAX_AUTO_NUM_THREADS )
138 n = MAX_AUTO_NUM_THREADS;
139 return n;
140 }
141
clean_preferred_decoder_names(void)142 static inline void clean_preferred_decoder_names( void )
143 {
144 lw_freep( &reader_opt.preferred_decoder_names );
145 memset( reader_opt.preferred_decoder_names_buf, 0, PREFERRED_DECODER_NAMES_BUFSIZE );
146 }
147
set_preferred_decoder_names_on_buf(const char * preferred_decoder_names)148 static inline void set_preferred_decoder_names_on_buf
149 (
150 const char *preferred_decoder_names
151 )
152 {
153 clean_preferred_decoder_names();
154 memcpy( reader_opt.preferred_decoder_names_buf, preferred_decoder_names,
155 MIN( PREFERRED_DECODER_NAMES_BUFSIZE - 1, strlen(preferred_decoder_names) ) );
156 reader_opt.preferred_decoder_names = lw_tokenize_string( reader_opt.preferred_decoder_names_buf, ',', NULL );
157 }
158
get_settings(void)159 static void get_settings( void )
160 {
161 FILE *ini = open_settings();
162 char buf[512];
163 if( ini )
164 {
165 /* threads */
166 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "threads=%d", &reader_opt.threads ) != 1 )
167 reader_opt.threads = 0;
168 /* av_sync */
169 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "av_sync=%d", &reader_opt.av_sync ) != 1 )
170 reader_opt.av_sync = 1;
171 /* no_create_index */
172 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "no_create_index=%d", &reader_opt.no_create_index ) != 1 )
173 reader_opt.no_create_index = 0;
174 /* force stream index */
175 if( !fgets( buf, sizeof(buf), ini )
176 || sscanf( buf, "force_video_index=%d:%d",
177 &reader_opt.force_video, &reader_opt.force_video_index ) != 2 )
178 {
179 reader_opt.force_video = 0;
180 reader_opt.force_video_index = -1;
181 }
182 else
183 reader_opt.force_video_index = MAX( reader_opt.force_video_index, -1 );
184 if( !fgets( buf, sizeof(buf), ini )
185 || sscanf( buf, "force_audio_index=%d:%d",
186 &reader_opt.force_audio, &reader_opt.force_audio_index ) != 2 )
187 {
188 reader_opt.force_audio = 0;
189 reader_opt.force_audio_index = -1;
190 }
191 else
192 reader_opt.force_audio_index = MAX( reader_opt.force_audio_index, -1 );
193 /* seek_mode */
194 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "seek_mode=%d", &video_opt->seek_mode ) != 1 )
195 video_opt->seek_mode = 0;
196 else
197 video_opt->seek_mode = CLIP_VALUE( video_opt->seek_mode, 0, 2 );
198 /* forward_seek_threshold */
199 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "forward_threshold=%d", &video_opt->forward_seek_threshold ) != 1 )
200 video_opt->forward_seek_threshold = 10;
201 else
202 video_opt->forward_seek_threshold = CLIP_VALUE( video_opt->forward_seek_threshold, 1, 999 );
203 /* scaler */
204 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "scaler=%d", &video_opt->scaler ) != 1 )
205 video_opt->scaler = 0;
206 else
207 video_opt->scaler = CLIP_VALUE( video_opt->scaler, 0, 10 );
208 /* apply_repeat_flag */
209 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "apply_repeat_flag=%d", &video_opt->apply_repeat_flag ) != 1 )
210 video_opt->apply_repeat_flag = 0;
211 /* field_dominance */
212 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "field_dominance=%d", &video_opt->field_dominance ) != 1 )
213 video_opt->field_dominance = 0;
214 else
215 video_opt->field_dominance = CLIP_VALUE( video_opt->field_dominance, 0, 2 );
216 /* VFR->CFR */
217 if( !fgets( buf, sizeof(buf), ini )
218 || sscanf( buf, "vfr2cfr=%d:%d:%d",
219 &video_opt->vfr2cfr.active,
220 &video_opt->vfr2cfr.framerate_num,
221 &video_opt->vfr2cfr.framerate_den ) != 3 )
222 {
223 video_opt->vfr2cfr.active = 0;
224 video_opt->vfr2cfr.framerate_num = 60000;
225 video_opt->vfr2cfr.framerate_den = 1001;
226 }
227 else
228 {
229 video_opt->vfr2cfr.framerate_num = MAX( video_opt->vfr2cfr.framerate_num, 1 );
230 video_opt->vfr2cfr.framerate_den = MAX( video_opt->vfr2cfr.framerate_den, 1 );
231 }
232 /* LW48 output */
233 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "colorspace=%d", (int *)&video_opt->colorspace ) != 1 )
234 video_opt->colorspace = 0;
235 else
236 video_opt->colorspace = video_opt->colorspace ? OUTPUT_LW48 : 0;
237 /* AVS bit-depth */
238 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "avs_bit_depth=%d", &video_opt->avs.bit_depth ) != 1 )
239 video_opt->avs.bit_depth = 8;
240 else
241 {
242 video_opt->avs.bit_depth = CLIP_VALUE( video_opt->avs.bit_depth, 8, 16 );
243 if( video_opt->avs.bit_depth > 10 )
244 video_opt->avs.bit_depth = 16;
245 }
246 /* audio_delay */
247 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "audio_delay=%d", &audio_delay ) != 1 )
248 audio_delay = 0;
249 /* channel_layout */
250 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "channel_layout=0x%"SCNx64, &audio_opt->channel_layout ) != 1 )
251 audio_opt->channel_layout = 0;
252 /* sample_rate */
253 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "sample_rate=%d", &audio_opt->sample_rate ) != 1 )
254 audio_opt->sample_rate = 0;
255 /* mix_level */
256 if( !fgets( buf, sizeof(buf), ini )
257 || sscanf( buf, "mix_level=%d:%d:%d",
258 &audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ],
259 &audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND],
260 &audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ] ) != 3 )
261 {
262 audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ] = 71;
263 audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] = 71;
264 audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ] = 0;
265 }
266 else
267 {
268 audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ] = CLIP_VALUE( audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ], 0, 10000 );
269 audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] = CLIP_VALUE( audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND], 0, 10000 );
270 audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ] = CLIP_VALUE( audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ], 0, 30000 );
271 }
272 /* readers */
273 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "libavsmash_disabled=%d", &reader_disabled[0] ) != 1 )
274 reader_disabled[0] = 0;
275 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "avs_disabled=%d", &reader_disabled[1] ) != 1 )
276 reader_disabled[1] = 0;
277 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "vpy_disabled=%d", &reader_disabled[2] ) != 1 )
278 reader_disabled[2] = 0;
279 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "libav_disabled=%d", &reader_disabled[3] ) != 1 )
280 reader_disabled[3] = 0;
281 /* dummy reader */
282 if( !fgets( buf, sizeof(buf), ini )
283 || sscanf( buf, "dummy_resolution=%dx%d", &video_opt->dummy.width, &video_opt->dummy.height ) != 2 )
284 {
285 video_opt->dummy.width = 720;
286 video_opt->dummy.height = 480;
287 }
288 else
289 {
290 video_opt->dummy.width = MAX( video_opt->dummy.width, 32 );
291 video_opt->dummy.height = MAX( video_opt->dummy.height, 32 );
292 }
293 if( !fgets( buf, sizeof(buf), ini )
294 || sscanf( buf, "dummy_framerate=%d/%d", &video_opt->dummy.framerate_num, &video_opt->dummy.framerate_den ) != 2 )
295 {
296 video_opt->dummy.framerate_num = 24;
297 video_opt->dummy.framerate_den = 1;
298 }
299 else
300 {
301 video_opt->dummy.framerate_num = MAX( video_opt->dummy.framerate_num, 1 );
302 video_opt->dummy.framerate_den = MAX( video_opt->dummy.framerate_den, 1 );
303 }
304 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "dummy_colorspace=%d", (int *)&video_opt->dummy.colorspace ) != 1 )
305 video_opt->dummy.colorspace = OUTPUT_YUY2;
306 else
307 video_opt->dummy.colorspace = CLIP_VALUE( video_opt->dummy.colorspace, 0, 2 );
308 /* preferred decoders settings */
309 char preferred_decoder_names[512] = { 0 };
310 if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "preferred_decoders=%s", preferred_decoder_names ) != 1 )
311 clean_preferred_decoder_names();
312 else
313 set_preferred_decoder_names_on_buf( preferred_decoder_names );
314 fclose( ini );
315 }
316 else
317 {
318 /* Set up defalut values. */
319 clean_preferred_decoder_names();
320 reader_opt.threads = 0;
321 reader_opt.av_sync = 1;
322 reader_opt.no_create_index = 0;
323 reader_opt.force_video = 0;
324 reader_opt.force_video_index = -1;
325 reader_opt.force_audio = 0;
326 reader_opt.force_audio_index = -1;
327 reader_disabled[0] = 0;
328 reader_disabled[1] = 0;
329 reader_disabled[2] = 0;
330 reader_disabled[3] = 0;
331 video_opt->seek_mode = 0;
332 video_opt->forward_seek_threshold = 10;
333 video_opt->scaler = 0;
334 video_opt->apply_repeat_flag = 0;
335 video_opt->field_dominance = 0;
336 video_opt->vfr2cfr.active = 0;
337 video_opt->vfr2cfr.framerate_num = 60000;
338 video_opt->vfr2cfr.framerate_den = 1001;
339 video_opt->colorspace = 0;
340 video_opt->dummy.width = 720;
341 video_opt->dummy.height = 480;
342 video_opt->dummy.framerate_num = 24;
343 video_opt->dummy.framerate_den = 1;
344 video_opt->dummy.colorspace = OUTPUT_YUY2;
345 video_opt->avs.bit_depth = 8;
346 audio_delay = 0;
347 audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ] = 71;
348 audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] = 71;
349 audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ] = 0;
350 }
351 }
352
func_open(LPSTR file)353 INPUT_HANDLE func_open( LPSTR file )
354 {
355 lsmash_handler_t *hp = (lsmash_handler_t *)lw_malloc_zero( sizeof(lsmash_handler_t) );
356 if( !hp )
357 return NULL;
358 hp->video_reader = READER_NONE;
359 hp->audio_reader = READER_NONE;
360 get_settings();
361 if( reader_opt.threads <= 0 )
362 reader_opt.threads = get_auto_threads();
363 extern lsmash_reader_t libavsmash_reader;
364 extern lsmash_reader_t avs_reader;
365 extern lsmash_reader_t vpy_reader;
366 extern lsmash_reader_t libav_reader;
367 extern lsmash_reader_t dummy_reader;
368 enum
369 {
370 AU_VIDEO_READER = 1,
371 AU_SCRIPT_READER = 2,
372 AU_DUMMY_READER = 3
373 };
374 static const struct
375 {
376 lsmash_reader_t *reader;
377 int attribute;
378 } lsmash_reader_table[] =
379 {
380 { &libavsmash_reader, AU_VIDEO_READER },
381 { &avs_reader , AU_SCRIPT_READER },
382 { &vpy_reader , AU_SCRIPT_READER },
383 { &libav_reader , AU_VIDEO_READER },
384 { &dummy_reader , AU_DUMMY_READER },
385 { NULL , 0 }
386 };
387 for( int i = 0; lsmash_reader_table[i].reader; i++ )
388 {
389 if( reader_disabled[lsmash_reader_table[i].reader->type - 1] )
390 continue;
391 int video_none = 1;
392 int audio_none = 1;
393 lsmash_reader_t reader = *lsmash_reader_table[i].reader;
394 int reader_attr = lsmash_reader_table[i].attribute;
395 void *private_stuff = reader.open_file( file, &reader_opt );
396 if( private_stuff )
397 {
398 if( !hp->video_private )
399 {
400 hp->video_private = private_stuff;
401 if( reader.get_video_track
402 && reader.get_video_track( hp, video_opt ) == 0 )
403 {
404 hp->video_reader = reader.type;
405 hp->read_video = reader.read_video;
406 hp->is_keyframe = reader.is_keyframe;
407 hp->video_cleanup = reader.video_cleanup;
408 hp->close_video_file = reader.close_file;
409 video_none = 0;
410 }
411 else
412 hp->video_private = NULL;
413 }
414 if( !hp->audio_private )
415 {
416 hp->audio_private = private_stuff;
417 if( reader.get_audio_track
418 && reader.get_audio_track( hp, audio_opt ) == 0 )
419 {
420 hp->audio_reader = reader.type;
421 hp->read_audio = reader.read_audio;
422 hp->delay_audio = reader.delay_audio;
423 hp->audio_cleanup = reader.audio_cleanup;
424 hp->close_audio_file = reader.close_file;
425 audio_none = 0;
426 }
427 else
428 hp->audio_private = NULL;
429 }
430 }
431 if( video_none && audio_none )
432 {
433 if( reader.close_file )
434 reader.close_file( private_stuff );
435 }
436 else
437 if( reader.destroy_disposable )
438 reader.destroy_disposable( private_stuff );
439 /* Found both video and audio reader. */
440 if( hp->video_reader != READER_NONE && hp->audio_reader != READER_NONE )
441 break;
442 if( reader_attr == AU_SCRIPT_READER )
443 {
444 if( hp->video_reader == reader.type )
445 break;
446 if( hp->audio_reader == reader.type )
447 while( lsmash_reader_table[i + 1].attribute != AU_DUMMY_READER )
448 i++;
449 }
450 }
451 if( hp->video_reader == hp->audio_reader )
452 {
453 hp->global_private = hp->video_private;
454 hp->close_file = hp->close_video_file;
455 hp->close_video_file = NULL;
456 hp->close_audio_file = NULL;
457 }
458 if( hp->video_reader == READER_NONE && hp->audio_reader == READER_NONE )
459 {
460 DEBUG_MESSAGE_BOX_DESKTOP( MB_OK, "No readable video and/or audio stream" );
461 func_close( hp );
462 return NULL;
463 }
464 return hp;
465 }
466
func_close(INPUT_HANDLE ih)467 BOOL func_close( INPUT_HANDLE ih )
468 {
469 lw_freep( &reader_opt.preferred_decoder_names );
470 lsmash_handler_t *hp = (lsmash_handler_t *)ih;
471 if( !hp )
472 return TRUE;
473 if( hp->video_cleanup )
474 hp->video_cleanup( hp );
475 if( hp->audio_cleanup )
476 hp->audio_cleanup( hp );
477 if( hp->close_file )
478 hp->close_file( hp->global_private );
479 else
480 {
481 if( hp->close_video_file )
482 hp->close_video_file( hp->video_private );
483 if( hp->close_audio_file )
484 hp->close_audio_file( hp->audio_private );
485 }
486 lw_free( hp );
487 return TRUE;
488 }
489
func_info_get(INPUT_HANDLE ih,INPUT_INFO * iip)490 BOOL func_info_get( INPUT_HANDLE ih, INPUT_INFO *iip )
491 {
492 lsmash_handler_t *hp = (lsmash_handler_t *)ih;
493 memset( iip, 0, sizeof(INPUT_INFO) );
494 if( hp->video_reader != READER_NONE )
495 {
496 iip->flag |= INPUT_INFO_FLAG_VIDEO | INPUT_INFO_FLAG_VIDEO_RANDOM_ACCESS;
497 iip->rate = hp->framerate_num;
498 iip->scale = hp->framerate_den;
499 iip->n = hp->video_sample_count;
500 iip->format = &hp->video_format;
501 iip->format_size = hp->video_format.biSize;
502 iip->handler = 0;
503 }
504 if( hp->audio_reader != READER_NONE )
505 {
506 iip->flag |= INPUT_INFO_FLAG_AUDIO;
507 iip->audio_n = hp->audio_pcm_sample_count + audio_delay;
508 iip->audio_format = &hp->audio_format.Format;
509 iip->audio_format_size = sizeof( WAVEFORMATEX ) + hp->audio_format.Format.cbSize;
510 }
511 return TRUE;
512 }
513
func_read_video(INPUT_HANDLE ih,int sample_number,void * buf)514 int func_read_video( INPUT_HANDLE ih, int sample_number, void *buf )
515 {
516 lsmash_handler_t *hp = (lsmash_handler_t *)ih;
517 return hp->read_video ? hp->read_video( hp, sample_number, buf ) : 0;
518 }
519
func_read_audio(INPUT_HANDLE ih,int start,int length,void * buf)520 int func_read_audio( INPUT_HANDLE ih, int start, int length, void *buf )
521 {
522 lsmash_handler_t *hp = (lsmash_handler_t *)ih;
523 if( hp->read_audio && hp->delay_audio( hp, &start, length, audio_delay ) )
524 return hp->read_audio( hp, start, length, buf );
525 uint8_t silence = hp->audio_format.Format.wBitsPerSample == 8 ? 128 : 0;
526 memset( buf, silence, length * hp->audio_format.Format.nBlockAlign );
527 return length;
528 }
529
func_is_keyframe(INPUT_HANDLE ih,int sample_number)530 BOOL func_is_keyframe( INPUT_HANDLE ih, int sample_number )
531 {
532 lsmash_handler_t *hp = (lsmash_handler_t *)ih;
533 if( sample_number >= hp->video_sample_count )
534 return FALSE; /* In reading as double framerate, keyframe detection doesn't work at all
535 * since sample_number exceeds the number of video samples. */
536 return hp->is_keyframe ? hp->is_keyframe( hp, sample_number ) : TRUE;
537 }
538
set_buddy_window_for_updown_control(HWND hwnd,int spin_idc,int buddy_idc)539 static inline void set_buddy_window_for_updown_control
540 (
541 HWND hwnd,
542 int spin_idc,
543 int buddy_idc
544 )
545 {
546 SendMessage( GetDlgItem( hwnd, spin_idc ), UDM_SETBUDDY, (WPARAM)GetDlgItem( hwnd, buddy_idc ), 0 );
547 }
548
set_check_state(HWND hwnd,int idc,int value)549 static inline void set_check_state
550 (
551 HWND hwnd,
552 int idc, /* identifier for control */
553 int value
554 )
555 {
556 SendMessage( GetDlgItem( hwnd, idc ), BM_SETCHECK, (WPARAM) value ? BST_CHECKED : BST_UNCHECKED, 0 );
557 }
558
get_check_state(HWND hwnd,int idc)559 static inline int get_check_state
560 (
561 HWND hwnd,
562 int idc /* identifier for control */
563 )
564 {
565 return (BST_CHECKED == SendMessage( GetDlgItem( hwnd, idc ), BM_GETCHECK, 0, 0 ));
566 }
567
set_int_to_dlg(HWND hwnd,int idc,int value)568 static void set_int_to_dlg
569 (
570 HWND hwnd,
571 int idc, /* identifier for control */
572 int value /* message value */
573 )
574 {
575 char edit_buf[512];
576 sprintf( edit_buf, "%d", value );
577 SetDlgItemText( hwnd, idc, (LPCTSTR)edit_buf );
578 }
579
get_int_from_dlg(HWND hwnd,int idc)580 static int get_int_from_dlg
581 (
582 HWND hwnd,
583 int idc /* identifier for control */
584 )
585 {
586 char edit_buf[512];
587 GetDlgItemText( hwnd, idc, (LPTSTR)edit_buf, sizeof(edit_buf) );
588 return atoi( edit_buf );
589 }
590
get_int_from_dlg_with_min(HWND hwnd,int idc,int min)591 static int get_int_from_dlg_with_min
592 (
593 HWND hwnd,
594 int idc, /* identifier for control */
595 int min
596 )
597 {
598 int value = get_int_from_dlg( hwnd, idc );
599 return MAX( value, min );
600 }
601
set_string_to_dlg(HWND hwnd,int idc,char * value)602 static inline void set_string_to_dlg
603 (
604 HWND hwnd,
605 int idc, /* identifier for control */
606 char *value /* message value */
607 )
608 {
609 SetDlgItemText( hwnd, idc, (LPCTSTR)value );
610 }
611
send_mix_level(HWND hwnd,int slider_idc,int text_idc,int range_min,int range_max,int mix_level)612 static void send_mix_level
613 (
614 HWND hwnd,
615 int slider_idc,
616 int text_idc,
617 int range_min,
618 int range_max,
619 int mix_level
620 )
621 {
622 char edit_buf[512];
623 HWND hslider = GetDlgItem( hwnd, slider_idc );
624 SendMessage( hslider, TBM_SETRANGE, TRUE, MAKELPARAM( range_min, range_max ) );
625 SendMessage( hslider, TBM_SETTICFREQ, 1, 0 );
626 SendMessage( hslider, TBM_SETPOS, TRUE, mix_level );
627 SendMessage( hslider, TBM_SETLINESIZE, 0, 1 );
628 SendMessage( hslider, TBM_SETPAGESIZE, 0, 1 );
629 sprintf( edit_buf, "%.2f", mix_level / 100.0 );
630 SetWindowText( GetDlgItem( hwnd, text_idc ), (LPCTSTR)edit_buf );
631 }
632
get_mix_level(HWND hwnd,int slider_idc,int text_idc,int * mix_level)633 static void get_mix_level
634 (
635 HWND hwnd,
636 int slider_idc,
637 int text_idc,
638 int *mix_level
639 )
640 {
641 char edit_buf[512];
642 HWND hslider = GetDlgItem( hwnd, slider_idc );
643 *mix_level = SendMessage( hslider, TBM_GETPOS, 0, 0 );
644 sprintf( edit_buf, "%.2f", *mix_level / 100.0 );
645 SetWindowText( GetDlgItem( hwnd, text_idc ), (LPCTSTR)edit_buf );
646 }
647
dialog_proc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)648 static BOOL CALLBACK dialog_proc
649 (
650 HWND hwnd,
651 UINT message,
652 WPARAM wparam,
653 LPARAM lparam
654 )
655 {
656 switch( message )
657 {
658 case WM_INITDIALOG :
659 InitCommonControls();
660 get_settings();
661 /* threads */
662 set_int_to_dlg( hwnd, IDC_EDIT_THREADS, reader_opt.threads );
663 set_buddy_window_for_updown_control( hwnd, IDC_SPIN_THREADS, IDC_EDIT_THREADS );
664 /* av_sync */
665 set_check_state( hwnd, IDC_CHECK_AV_SYNC, reader_opt.av_sync );
666 /* no_create_index */
667 set_check_state( hwnd, IDC_CHECK_CREATE_INDEX_FILE, !reader_opt.no_create_index );
668 /* force stream index */
669 set_check_state( hwnd, IDC_CHECK_FORCE_VIDEO, reader_opt.force_video );
670 set_check_state( hwnd, IDC_CHECK_FORCE_AUDIO, reader_opt.force_audio );
671 set_int_to_dlg( hwnd, IDC_EDIT_FORCE_VIDEO_INDEX, reader_opt.force_video_index );
672 set_int_to_dlg( hwnd, IDC_EDIT_FORCE_AUDIO_INDEX, reader_opt.force_audio_index );
673 /* forward_seek_threshold */
674 set_int_to_dlg( hwnd, IDC_EDIT_FORWARD_THRESHOLD, video_opt->forward_seek_threshold );
675 set_buddy_window_for_updown_control( hwnd, IDC_SPIN_FORWARD_THRESHOLD, IDC_EDIT_FORWARD_THRESHOLD );
676 /* seek mode */
677 HWND hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_SEEK_MODE );
678 for( int i = 0; i < 3; i++ )
679 SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)seek_mode_list[i] );
680 SendMessage( hcombo, CB_SETCURSEL, video_opt->seek_mode, 0 );
681 /* scaler */
682 hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_SCALER );
683 for( int i = 0; i < 11; i++ )
684 SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)scaler_list[i] );
685 SendMessage( hcombo, CB_SETCURSEL, video_opt->scaler, 0 );
686 /* apply_repeat_flag */
687 set_check_state( hwnd, IDC_CHECK_APPLY_REPEAT_FLAG, video_opt->apply_repeat_flag );
688 /* field_dominance */
689 hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_FIELD_DOMINANCE );
690 for( int i = 0; i < 3; i++ )
691 SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)field_dominance_list[i] );
692 SendMessage( hcombo, CB_SETCURSEL, video_opt->field_dominance, 0 );
693 /* VFR->CFR */
694 set_check_state( hwnd, IDC_CHECK_VFR_TO_CFR, video_opt->vfr2cfr.active );
695 set_int_to_dlg( hwnd, IDC_EDIT_CONST_FRAMERATE_NUM, video_opt->vfr2cfr.framerate_num );
696 set_int_to_dlg( hwnd, IDC_EDIT_CONST_FRAMERATE_DEN, video_opt->vfr2cfr.framerate_den );
697 /* LW48 output */
698 set_check_state( hwnd, IDC_CHECK_LW48_OUTPUT, video_opt->colorspace != 0 );
699 /* AVS bit-depth */
700 hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_AVS_BITDEPTH );
701 for( int i = 0; i < 4; i++ )
702 {
703 SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)avs_bit_depth_list[i] );
704 if( video_opt->avs.bit_depth == atoi( avs_bit_depth_list[i] ) )
705 SendMessage( hcombo, CB_SETCURSEL, i, 0 );
706 }
707 /* audio_delay */
708 set_int_to_dlg( hwnd, IDC_EDIT_AUDIO_DELAY, audio_delay );
709 /* channel_layout */
710 if( audio_opt->channel_layout )
711 {
712 char edit_buf[512] = { 0 };
713 char *buf = edit_buf;
714 for( int i = 0; i < 64; i++ )
715 {
716 uint64_t audio_channel = audio_opt->channel_layout & (1ULL << i);
717 if( audio_channel )
718 {
719 const char *channel_name = av_get_channel_name( audio_channel );
720 if( channel_name )
721 {
722 int name_length = strlen( channel_name );
723 memcpy( buf, channel_name, name_length );
724 buf += name_length;
725 *(buf++) = '+';
726 }
727 }
728 }
729 if( buf > edit_buf )
730 {
731 *(buf - 1) = '\0'; /* Replace the last '+' with NULL terminator. */
732 SetDlgItemText( hwnd, IDC_EDIT_CHANNEL_LAYOUT, (LPCTSTR)edit_buf );
733 }
734 else
735 set_string_to_dlg( hwnd, IDC_EDIT_CHANNEL_LAYOUT, "Unspecified" );
736 }
737 else
738 set_string_to_dlg( hwnd, IDC_EDIT_CHANNEL_LAYOUT, "Unspecified" );
739 /* sample_rate */
740 if( audio_opt->sample_rate > 0 )
741 set_int_to_dlg( hwnd, IDC_EDIT_SAMPLE_RATE, audio_opt->sample_rate );
742 else
743 {
744 audio_opt->sample_rate = 0;
745 set_string_to_dlg( hwnd, IDC_EDIT_SAMPLE_RATE, "0 (Auto)" );
746 }
747 /* mix_level */
748 send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER, IDC_TEXT_MIX_LEVEL_CENTER, 0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ] );
749 send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND, IDC_TEXT_MIX_LEVEL_SURROUND, 0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] );
750 send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_LFE, IDC_TEXT_MIX_LEVEL_LFE, 0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ] );
751 /* readers */
752 set_check_state( hwnd, IDC_CHECK_LIBAVSMASH_INPUT, !reader_disabled[0] );
753 set_check_state( hwnd, IDC_CHECK_AVS_INPUT, !reader_disabled[1] );
754 set_check_state( hwnd, IDC_CHECK_VPY_INPUT, !reader_disabled[2] );
755 set_check_state( hwnd, IDC_CHECK_LIBAV_INPUT, !reader_disabled[3] );
756 /* dummy reader */
757 set_int_to_dlg( hwnd, IDC_EDIT_DUMMY_WIDTH, video_opt->dummy.width );
758 set_int_to_dlg( hwnd, IDC_EDIT_DUMMY_HEIGHT, video_opt->dummy.height );
759 set_int_to_dlg( hwnd, IDC_EDIT_DUMMY_FRAMERATE_NUM, video_opt->dummy.framerate_num );
760 set_int_to_dlg( hwnd, IDC_EDIT_DUMMY_FRAMERATE_DEN, video_opt->dummy.framerate_den );
761 hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_DUMMY_COLORSPACE );
762 for( int i = 0; i < 3; i++ )
763 SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)dummy_colorspace_list[i] );
764 SendMessage( hcombo, CB_SETCURSEL, video_opt->dummy.colorspace, 0 );
765 /* preferred decoders */
766 if( reader_opt.preferred_decoder_names )
767 {
768 char edit_buf[512] = { 0 };
769 char *buf = edit_buf;
770 for( const char **decoder = reader_opt.preferred_decoder_names; *decoder != NULL; decoder++ )
771 {
772 if( *decoder != *reader_opt.preferred_decoder_names )
773 *(buf++) = ',';
774 int length = strlen( *decoder );
775 memcpy( buf, *decoder, length );
776 buf += length;
777 }
778 set_string_to_dlg( hwnd, IDC_EDIT_PREFERRED_DECODERS, edit_buf );
779 }
780 else
781 set_string_to_dlg( hwnd, IDC_EDIT_PREFERRED_DECODERS, "" );
782 /* Library informations */
783 if( plugin_information[0] == 0 )
784 get_plugin_information();
785 SetDlgItemText( hwnd, IDC_TEXT_LIBRARY_INFO, (LPCTSTR)plugin_information );
786 HFONT hfont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );
787 LOGFONT lf = { 0 };
788 GetObject( hfont, sizeof(lf), &lf );
789 lf.lfWidth *= 0.90;
790 lf.lfHeight *= 0.90;
791 lf.lfQuality = ANTIALIASED_QUALITY;
792 SendMessage( GetDlgItem( hwnd, IDC_TEXT_LIBRARY_INFO ), WM_SETFONT, (WPARAM)CreateFontIndirect( &lf ), 1 );
793 return TRUE;
794 case WM_NOTIFY :
795 if( wparam == IDC_SPIN_THREADS )
796 {
797 LPNMUPDOWN lpnmud = (LPNMUPDOWN)lparam;
798 if( lpnmud->hdr.code == UDN_DELTAPOS )
799 {
800 reader_opt.threads = get_int_from_dlg( hwnd, IDC_EDIT_THREADS );
801 if( lpnmud->iDelta )
802 reader_opt.threads += lpnmud->iDelta > 0 ? -1 : 1;
803 if( reader_opt.threads < 0 )
804 reader_opt.threads = 0;
805 set_int_to_dlg( hwnd, IDC_EDIT_THREADS, reader_opt.threads );
806 }
807 }
808 else if( wparam == IDC_SPIN_FORWARD_THRESHOLD )
809 {
810 LPNMUPDOWN lpnmud = (LPNMUPDOWN)lparam;
811 if( lpnmud->hdr.code == UDN_DELTAPOS )
812 {
813 video_opt->forward_seek_threshold = get_int_from_dlg( hwnd, IDC_EDIT_FORWARD_THRESHOLD );
814 if( lpnmud->iDelta )
815 video_opt->forward_seek_threshold += lpnmud->iDelta > 0 ? -1 : 1;
816 video_opt->forward_seek_threshold = CLIP_VALUE( video_opt->forward_seek_threshold, 1, 999 );
817 set_int_to_dlg( hwnd, IDC_EDIT_FORWARD_THRESHOLD, video_opt->forward_seek_threshold );
818 }
819 }
820 return TRUE;
821 case WM_HSCROLL :
822 if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER ) == (HWND)lparam )
823 get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER, IDC_TEXT_MIX_LEVEL_CENTER, &audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ] );
824 else if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND ) == (HWND)lparam )
825 get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND, IDC_TEXT_MIX_LEVEL_SURROUND, &audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] );
826 else if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_LFE ) == (HWND)lparam )
827 get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_LFE, IDC_TEXT_MIX_LEVEL_LFE, &audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ] );
828 return FALSE;
829 case WM_COMMAND :
830 switch( wparam )
831 {
832 case IDCANCEL :
833 EndDialog( hwnd, IDCANCEL );
834 return TRUE;
835 case IDOK :
836 {
837 /* Open */
838 if( !settings_path )
839 settings_path = (char *)settings_path_list[0];
840 FILE *ini = fopen( settings_path, "w" );
841 if( !ini )
842 {
843 MESSAGE_BOX_DESKTOP( MB_ICONERROR | MB_OK, "Failed to update configuration file" );
844 return FALSE;
845 }
846 /* threads */
847 reader_opt.threads = get_int_from_dlg_with_min( hwnd, IDC_EDIT_THREADS, 0 );
848 if( reader_opt.threads > 0 )
849 fprintf( ini, "threads=%d\n", reader_opt.threads );
850 else
851 fprintf( ini, "threads=0 (auto)\n" );
852 /* av_sync */
853 reader_opt.av_sync = get_check_state( hwnd, IDC_CHECK_AV_SYNC );
854 fprintf( ini, "av_sync=%d\n", reader_opt.av_sync );
855 /* no_create_index */
856 reader_opt.no_create_index = !get_check_state( hwnd, IDC_CHECK_CREATE_INDEX_FILE );
857 fprintf( ini, "no_create_index=%d\n", reader_opt.no_create_index );
858 /* force stream index */
859 reader_opt.force_video = get_check_state( hwnd, IDC_CHECK_FORCE_VIDEO );
860 reader_opt.force_audio = get_check_state( hwnd, IDC_CHECK_FORCE_AUDIO );
861 reader_opt.force_video_index = get_int_from_dlg_with_min( hwnd, IDC_EDIT_FORCE_VIDEO_INDEX, -1 );
862 reader_opt.force_audio_index = get_int_from_dlg_with_min( hwnd, IDC_EDIT_FORCE_AUDIO_INDEX, -1 );
863 fprintf( ini, "force_video_index=%d:%d\n", reader_opt.force_video, reader_opt.force_video_index );
864 fprintf( ini, "force_audio_index=%d:%d\n", reader_opt.force_audio, reader_opt.force_audio_index );
865 /* seek_mode */
866 video_opt->seek_mode = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_SEEK_MODE ), CB_GETCURSEL, 0, 0 );
867 fprintf( ini, "seek_mode=%d\n", video_opt->seek_mode );
868 /* forward_seek_threshold */
869 video_opt->forward_seek_threshold = get_int_from_dlg( hwnd, IDC_EDIT_FORWARD_THRESHOLD );
870 video_opt->forward_seek_threshold = CLIP_VALUE( video_opt->forward_seek_threshold, 1, 999 );
871 fprintf( ini, "forward_threshold=%d\n", video_opt->forward_seek_threshold );
872 /* scaler */
873 video_opt->scaler = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_SCALER ), CB_GETCURSEL, 0, 0 );
874 fprintf( ini, "scaler=%d\n", video_opt->scaler );
875 /* apply_repeat_flag */
876 video_opt->apply_repeat_flag = get_check_state( hwnd, IDC_CHECK_APPLY_REPEAT_FLAG );
877 fprintf( ini, "apply_repeat_flag=%d\n", video_opt->apply_repeat_flag );
878 /* field_dominance */
879 video_opt->field_dominance = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_FIELD_DOMINANCE ), CB_GETCURSEL, 0, 0 );
880 fprintf( ini, "field_dominance=%d\n", video_opt->field_dominance );
881 /* VFR->CFR */
882 video_opt->vfr2cfr.active = get_check_state( hwnd, IDC_CHECK_VFR_TO_CFR );
883 video_opt->vfr2cfr.framerate_num = get_int_from_dlg_with_min( hwnd, IDC_EDIT_CONST_FRAMERATE_NUM, 1 );
884 video_opt->vfr2cfr.framerate_den = get_int_from_dlg_with_min( hwnd, IDC_EDIT_CONST_FRAMERATE_DEN, 1 );
885 fprintf( ini, "vfr2cfr=%d:%d:%d\n", video_opt->vfr2cfr.active, video_opt->vfr2cfr.framerate_num, video_opt->vfr2cfr.framerate_den );
886 /* LW48 output */
887 video_opt->colorspace = (get_check_state( hwnd, IDC_CHECK_LW48_OUTPUT ) ? OUTPUT_LW48 : 0);
888 fprintf( ini, "colorspace=%d\n", video_opt->colorspace );
889 /* AVS bit-depth */
890 video_opt->avs.bit_depth = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_AVS_BITDEPTH ), CB_GETCURSEL, 0, 0 );
891 video_opt->avs.bit_depth = atoi( avs_bit_depth_list[ video_opt->avs.bit_depth ] );
892 fprintf( ini, "avs_bit_depth=%d\n", video_opt->avs.bit_depth );
893 /* audio_delay */
894 audio_delay = get_int_from_dlg( hwnd, IDC_EDIT_AUDIO_DELAY );
895 fprintf( ini, "audio_delay=%d\n", audio_delay );
896 /* channel_layout */
897 {
898 char edit_buf[512];
899 GetDlgItemText( hwnd, IDC_EDIT_CHANNEL_LAYOUT, (LPTSTR)edit_buf, sizeof(edit_buf) );
900 audio_opt->channel_layout = av_get_channel_layout( edit_buf );
901 }
902 fprintf( ini, "channel_layout=0x%"PRIx64"\n", audio_opt->channel_layout );
903 /* sample_rate */
904 audio_opt->sample_rate = get_int_from_dlg_with_min( hwnd, IDC_EDIT_SAMPLE_RATE, 0 );
905 fprintf( ini, "sample_rate=%d\n", audio_opt->sample_rate );
906 /* mix_level */
907 fprintf( ini, "mix_level=%d:%d:%d\n",
908 audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER ],
909 audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND],
910 audio_opt->mix_level[MIX_LEVEL_INDEX_LFE ] );
911 /* readers */
912 reader_disabled[0] = !get_check_state( hwnd, IDC_CHECK_LIBAVSMASH_INPUT );
913 reader_disabled[1] = !get_check_state( hwnd, IDC_CHECK_AVS_INPUT );
914 reader_disabled[2] = !get_check_state( hwnd, IDC_CHECK_VPY_INPUT );
915 reader_disabled[3] = !get_check_state( hwnd, IDC_CHECK_LIBAV_INPUT );
916 fprintf( ini, "libavsmash_disabled=%d\n", reader_disabled[0] );
917 fprintf( ini, "avs_disabled=%d\n", reader_disabled[1] );
918 fprintf( ini, "vpy_disabled=%d\n", reader_disabled[2] );
919 fprintf( ini, "libav_disabled=%d\n", reader_disabled[3] );
920 /* dummy reader */
921 video_opt->dummy.width = get_int_from_dlg_with_min( hwnd, IDC_EDIT_DUMMY_WIDTH, 32 );
922 video_opt->dummy.height = get_int_from_dlg_with_min( hwnd, IDC_EDIT_DUMMY_HEIGHT, 32 );
923 video_opt->dummy.framerate_num = get_int_from_dlg_with_min( hwnd, IDC_EDIT_DUMMY_FRAMERATE_NUM, 1 );
924 video_opt->dummy.framerate_den = get_int_from_dlg_with_min( hwnd, IDC_EDIT_DUMMY_FRAMERATE_DEN, 1 );
925 video_opt->dummy.colorspace = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_DUMMY_COLORSPACE ), CB_GETCURSEL, 0, 0 );
926 fprintf( ini, "dummy_resolution=%dx%d\n", video_opt->dummy.width, video_opt->dummy.height );
927 fprintf( ini, "dummy_framerate=%d/%d\n", video_opt->dummy.framerate_num, video_opt->dummy.framerate_den );
928 fprintf( ini, "dummy_colorspace=%d\n", video_opt->dummy.colorspace );
929 /* preferred decoders */
930 {
931 char edit_buf[512];
932 GetDlgItemText( hwnd, IDC_EDIT_PREFERRED_DECODERS, (LPTSTR)edit_buf, sizeof(edit_buf) );
933 set_preferred_decoder_names_on_buf( edit_buf );
934 fprintf( ini, "preferred_decoders=%s\n", edit_buf );
935 }
936 /* Close */
937 fclose( ini );
938 EndDialog( hwnd, IDOK );
939 MESSAGE_BOX_DESKTOP( MB_OK, "Please reopen the input file for updating settings!" );
940 return TRUE;
941 }
942 default :
943 return FALSE;
944 }
945 case WM_CLOSE :
946 EndDialog( hwnd, IDOK );
947 return TRUE;
948 default :
949 return FALSE;
950 }
951 }
952
func_config(HWND hwnd,HINSTANCE dll_hinst)953 BOOL func_config( HWND hwnd, HINSTANCE dll_hinst )
954 {
955 DialogBox( dll_hinst, "LWINPUT_CONFIG", hwnd, dialog_proc );
956 return TRUE;
957 }
958