static void ffmpeg_source_activate(void *data)
{
	struct ffmpeg_source *s = data;

	if (s->restart_on_activate)
		ffmpeg_source_start(s);
}
static void ffmpeg_source_update(void *data, obs_data_t *settings)
{
	struct ffmpeg_source *s = data;

	bool is_local_file = obs_data_get_bool(settings, "is_local_file");

	char *input;
	char *input_format;

	bfree(s->input);
	bfree(s->input_format);

	if (is_local_file) {
		input = (char *)obs_data_get_string(settings, "local_file");
		input_format = NULL;
		s->is_looping = obs_data_get_bool(settings, "looping");
		s->close_when_inactive = obs_data_get_bool(settings,
				"close_when_inactive");

		obs_source_set_async_unbuffered(s->source, true);
	} else {
		input = (char *)obs_data_get_string(settings, "input");
		input_format = (char *)obs_data_get_string(settings,
				"input_format");
		s->is_looping = false;
		s->close_when_inactive = true;

		obs_source_set_async_unbuffered(s->source, false);
	}

	s->input = input ? bstrdup(input) : NULL;
	s->input_format = input_format ? bstrdup(input_format) : NULL;
#ifndef __APPLE__
	s->is_hw_decoding = obs_data_get_bool(settings, "hw_decode");
#endif
	s->is_clear_on_media_end = obs_data_get_bool(settings,
			"clear_on_media_end");
	s->restart_on_activate = obs_data_get_bool(settings,
			"restart_on_activate");
	s->range = (enum video_range_type)obs_data_get_int(settings,
			"color_range");
	s->buffering_mb = (int)obs_data_get_int(settings, "buffering_mb");
	s->is_local_file = is_local_file;

	if (s->media_valid) {
		mp_media_free(&s->media);
		s->media_valid = false;
	}

	bool active = obs_source_active(s->source);
	if (!s->close_when_inactive || active)
		ffmpeg_source_open(s);

	dump_source_info(s, input, input_format);
	if (!s->restart_on_activate || active)
		ffmpeg_source_start(s);
}
static void restart_hotkey(void *data, obs_hotkey_id id,
		obs_hotkey_t *hotkey, bool pressed)
{
	UNUSED_PARAMETER(id);
	UNUSED_PARAMETER(hotkey);
	UNUSED_PARAMETER(pressed);

	struct ffmpeg_source *s = data;
	if (obs_source_active(s->source))
		ffmpeg_source_start(s);
}
static void ffmpeg_source_update(void *data, obs_data_t *settings)
{
	struct ffmpeg_source *s = data;

	bool is_local_file = obs_data_get_bool(settings, "is_local_file");
	bool is_advanced = obs_data_get_bool(settings, "advanced");

	char *input;
	char *input_format;

	bfree(s->input);
	bfree(s->input_format);

	if (is_local_file) {
		input = (char *)obs_data_get_string(settings, "local_file");
		input_format = NULL;
		s->is_looping = obs_data_get_bool(settings, "looping");
	} else {
		input = (char *)obs_data_get_string(settings, "input");
		input_format = (char *)obs_data_get_string(settings,
				"input_format");
		s->is_looping = false;
	}

	s->input = input ? bstrdup(input) : NULL;
	s->input_format = input_format ? bstrdup(input_format) : NULL;
	s->is_advanced = is_advanced;
	s->is_hw_decoding = obs_data_get_bool(settings, "hw_decode");
	s->is_clear_on_media_end = obs_data_get_bool(settings,
			"clear_on_media_end");
	s->restart_on_activate = obs_data_get_bool(settings,
			"restart_on_activate");
	s->is_forcing_scale = true;

	if (is_advanced) {
		s->audio_buffer_size = (int)obs_data_get_int(settings,
				"audio_buffer_size");
		s->video_buffer_size = (int)obs_data_get_int(settings,
				"video_buffer_size");
		s->frame_drop = (enum AVDiscard)obs_data_get_int(settings,
					"frame_drop");
		s->is_forcing_scale = obs_data_get_bool(settings,
				"force_scale");

		if (s->audio_buffer_size < 1) {
			s->audio_buffer_size = 1;
			FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d",
					s->audio_buffer_size);
		}
		if (s->video_buffer_size < 1) {
			s->video_buffer_size = 1;
			FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d",
					s->audio_buffer_size);
		}

		if (s->frame_drop < AVDISCARD_NONE ||
		    s->frame_drop > AVDISCARD_ALL) {
			s->frame_drop = AVDISCARD_DEFAULT;
			FF_BLOG(LOG_WARNING, "invalid frame_drop %d",
					s->frame_drop);
		}
	}

	dump_source_info(s, input, input_format, is_advanced);
	if (!s->restart_on_activate || obs_source_active(s->source))
		ffmpeg_source_start(s);
}