Added animated gif support and translations
This commit is contained in:
parent
4dd0f01d56
commit
3080b3db9e
@ -1,5 +1,5 @@
|
|||||||
# OBS Image Reaction Plugin
|
# OBS Image Reaction Plugin
|
||||||
Image that reacts to sound source. It change picture from one to another based on volume.
|
Image that reacts to sound source.
|
||||||
|
|
||||||
## Installing binaries
|
## Installing binaries
|
||||||
Download binaries from [Releases](https://github.com/scaledteam/obs-image-reaction/releases/).
|
Download binaries from [Releases](https://github.com/scaledteam/obs-image-reaction/releases/).
|
||||||
@ -18,6 +18,7 @@ cmake ..
|
|||||||
make
|
make
|
||||||
mkdir -p ~/.config/obs-studio/plugins/libimage-reaction/bin/64bit
|
mkdir -p ~/.config/obs-studio/plugins/libimage-reaction/bin/64bit
|
||||||
cp libimage-reaction.so ~/.config/obs-studio/plugins/libimage-reaction/bin/64bit/
|
cp libimage-reaction.so ~/.config/obs-studio/plugins/libimage-reaction/bin/64bit/
|
||||||
|
cp -r ../data ~/.config/obs-studio/plugins/libimage-reaction/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building for Windows from GNU/Linux:
|
## Building for Windows from GNU/Linux:
|
||||||
|
10
data/locale/en-US.ini
Normal file
10
data/locale/en-US.ini
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ImageReactionSource="Image Reaction"
|
||||||
|
Reaction1="Image when silence"
|
||||||
|
Reaction2="Image when sound"
|
||||||
|
AnimReset1="Reset animation of the first image after reaction"
|
||||||
|
AnimReset2="Reset animation of the second image after reaction"
|
||||||
|
UnloadWhenNotShowing="Unload image when not showing"
|
||||||
|
LinearAlpha="Apply alpha in linear space"
|
||||||
|
Threshold="Reaction threshold"
|
||||||
|
Smoothness="Smoothness"
|
||||||
|
AudioSource="Audio source"
|
10
data/locale/ru-RU.ini
Normal file
10
data/locale/ru-RU.ini
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ImageReactionSource="Реактивная картинка"
|
||||||
|
Reaction1="Изображение при тишине"
|
||||||
|
Reaction2="Изображение при звуке"
|
||||||
|
AnimReset1="Сбрасывать анимацию первой картинки после реакции"
|
||||||
|
AnimReset2="Сбрасывать анимацию второй картинки после реакции"
|
||||||
|
UnloadWhenNotShowing="Выгружать изображения, которые не показываются"
|
||||||
|
LinearAlpha="Применить альфа канал в линейном пространстве"
|
||||||
|
Threshold="Порог срабатывания"
|
||||||
|
Smoothness="Плавность"
|
||||||
|
AudioSource="Источник звука"
|
@ -37,6 +37,13 @@ struct image_reaction_source {
|
|||||||
float threshold;
|
float threshold;
|
||||||
float smoothness;
|
float smoothness;
|
||||||
float average;
|
float average;
|
||||||
|
|
||||||
|
uint64_t last_time;
|
||||||
|
|
||||||
|
bool animReset1;
|
||||||
|
bool animReset2;
|
||||||
|
bool loudOld;
|
||||||
|
bool animResetTrigger;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*int MAX(int a, int b) {
|
/*int MAX(int a, int b) {
|
||||||
@ -49,7 +56,7 @@ struct image_reaction_source {
|
|||||||
static const char *image_reaction_source_get_name(void *unused)
|
static const char *image_reaction_source_get_name(void *unused)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(unused);
|
UNUSED_PARAMETER(unused);
|
||||||
return obs_module_text("Image Reaction Source");
|
return obs_module_text("ImageReactionSource");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void image_reaction_source_load(struct image_reaction_source *context)
|
static void image_reaction_source_load(struct image_reaction_source *context)
|
||||||
@ -92,7 +99,6 @@ static void audio_capture(void *param, obs_source_t *src, const struct audio_dat
|
|||||||
{
|
{
|
||||||
struct image_reaction_source *context = param;
|
struct image_reaction_source *context = param;
|
||||||
|
|
||||||
context->loud = false;
|
|
||||||
|
|
||||||
uint32_t samplesCount = data->frames;
|
uint32_t samplesCount = data->frames;
|
||||||
float* samples = (float*)data->data[0];
|
float* samples = (float*)data->data[0];
|
||||||
@ -104,10 +110,11 @@ static void audio_capture(void *param, obs_source_t *src, const struct audio_dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
context->average += context->smoothness * (averageLocal - context->average);
|
context->average += context->smoothness * (averageLocal - context->average);
|
||||||
if (context->average > context->threshold) {
|
context->loudOld = context->loud;
|
||||||
context->loud = true;
|
context->loud = context->average > context->threshold;
|
||||||
}
|
|
||||||
//printf("%f\n", average);
|
if (context->loud != context->loudOld)
|
||||||
|
context->animResetTrigger = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void image_reaction_source_update(void *data, obs_data_t *settings)
|
static void image_reaction_source_update(void *data, obs_data_t *settings)
|
||||||
@ -115,6 +122,8 @@ static void image_reaction_source_update(void *data, obs_data_t *settings)
|
|||||||
struct image_reaction_source *context = data;
|
struct image_reaction_source *context = data;
|
||||||
const char *file1 = obs_data_get_string(settings, "file1");
|
const char *file1 = obs_data_get_string(settings, "file1");
|
||||||
const char *file2 = obs_data_get_string(settings, "file2");
|
const char *file2 = obs_data_get_string(settings, "file2");
|
||||||
|
const bool anim_reset_1 = obs_data_get_bool(settings, "anim_reset_1");
|
||||||
|
const bool anim_reset_2 = obs_data_get_bool(settings, "anim_reset_2");
|
||||||
const bool unload = obs_data_get_bool(settings, "unload");
|
const bool unload = obs_data_get_bool(settings, "unload");
|
||||||
const bool linear_alpha = obs_data_get_bool(settings, "linear_alpha");
|
const bool linear_alpha = obs_data_get_bool(settings, "linear_alpha");
|
||||||
const double threshold = obs_data_get_double(settings, "threshold");
|
const double threshold = obs_data_get_double(settings, "threshold");
|
||||||
@ -128,6 +137,9 @@ static void image_reaction_source_update(void *data, obs_data_t *settings)
|
|||||||
bfree(context->file2);
|
bfree(context->file2);
|
||||||
context->file2 = bstrdup(file2);
|
context->file2 = bstrdup(file2);
|
||||||
|
|
||||||
|
context->animReset1 = anim_reset_1;
|
||||||
|
context->animReset2 = anim_reset_2;
|
||||||
|
|
||||||
context->persistent = !unload;
|
context->persistent = !unload;
|
||||||
context->linear_alpha = linear_alpha;
|
context->linear_alpha = linear_alpha;
|
||||||
context->threshold = db_to_mul(threshold);
|
context->threshold = db_to_mul(threshold);
|
||||||
@ -260,6 +272,67 @@ static void image_reaction_source_render(void *data, gs_effect_t *effect)
|
|||||||
gs_enable_framebuffer_srgb(previous);
|
gs_enable_framebuffer_srgb(previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void image_reaction_tick(void *data, float seconds)
|
||||||
|
{
|
||||||
|
struct image_reaction_source *context = data;
|
||||||
|
uint64_t frame_time = obs_get_video_frame_time();
|
||||||
|
|
||||||
|
for (int i = 0; i <=1; i++) {
|
||||||
|
gs_image_file3_t *if3 = i == 0 ? &context->if31 : &context->if32;
|
||||||
|
bool animReset = i == 0 ? context->animReset1 : context->animReset2;
|
||||||
|
|
||||||
|
if (obs_source_active(context->source)) {
|
||||||
|
if (!context->active) {
|
||||||
|
if (if3->image2.image.is_animated_gif)
|
||||||
|
context->last_time = frame_time;
|
||||||
|
context->active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (context->active) {
|
||||||
|
if (if3->image2.image.is_animated_gif) {
|
||||||
|
if3->image2.image.cur_frame = 0;
|
||||||
|
if3->image2.image.cur_loop = 0;
|
||||||
|
if3->image2.image.cur_time = 0;
|
||||||
|
|
||||||
|
obs_enter_graphics();
|
||||||
|
gs_image_file3_update_texture(if3);
|
||||||
|
obs_leave_graphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
context->active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->last_time && if3->image2.image.is_animated_gif) {
|
||||||
|
if (animReset && context->animResetTrigger) {
|
||||||
|
if3->image2.image.cur_frame = 0;
|
||||||
|
if3->image2.image.cur_loop = 0;
|
||||||
|
if3->image2.image.cur_time = 0;
|
||||||
|
|
||||||
|
obs_enter_graphics();
|
||||||
|
gs_image_file3_update_texture(if3);
|
||||||
|
obs_leave_graphics();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint64_t elapsed = frame_time - context->last_time;
|
||||||
|
bool updated = gs_image_file3_tick(if3, elapsed);
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
obs_enter_graphics();
|
||||||
|
gs_image_file3_update_texture(if3);
|
||||||
|
obs_leave_graphics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context->animResetTrigger = false;
|
||||||
|
|
||||||
|
context->last_time = frame_time;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *image_filter =
|
static const char *image_filter =
|
||||||
"All formats (*.bmp *.tga *.png *.jpeg *.jpg *.gif *.psd *.webp);;"
|
"All formats (*.bmp *.tga *.png *.jpeg *.jpg *.gif *.psd *.webp);;"
|
||||||
"BMP Files (*.bmp);;"
|
"BMP Files (*.bmp);;"
|
||||||
@ -309,8 +382,12 @@ static obs_properties_t *image_reaction_source_properties(void *data)
|
|||||||
|
|
||||||
obs_properties_add_path(props, "file1", obs_module_text("Reaction1"),
|
obs_properties_add_path(props, "file1", obs_module_text("Reaction1"),
|
||||||
OBS_PATH_FILE, image_filter, path.array);
|
OBS_PATH_FILE, image_filter, path.array);
|
||||||
|
obs_properties_add_bool(props, "anim_reset_1",
|
||||||
|
obs_module_text("AnimReset1"));
|
||||||
obs_properties_add_path(props, "file2", obs_module_text("Reaction2"),
|
obs_properties_add_path(props, "file2", obs_module_text("Reaction2"),
|
||||||
OBS_PATH_FILE, image_filter, path.array);
|
OBS_PATH_FILE, image_filter, path.array);
|
||||||
|
obs_properties_add_bool(props, "anim_reset_2",
|
||||||
|
obs_module_text("AnimReset2"));
|
||||||
dstr_free(&path);
|
dstr_free(&path);
|
||||||
|
|
||||||
obs_properties_add_bool(props, "unload",
|
obs_properties_add_bool(props, "unload",
|
||||||
@ -366,12 +443,13 @@ static struct obs_source_info image_reaction_source_info = {
|
|||||||
.get_width = image_reaction_source_getwidth,
|
.get_width = image_reaction_source_getwidth,
|
||||||
.get_height = image_reaction_source_getheight,
|
.get_height = image_reaction_source_getheight,
|
||||||
.video_render = image_reaction_source_render,
|
.video_render = image_reaction_source_render,
|
||||||
|
.video_tick = image_reaction_tick,
|
||||||
.get_properties = image_reaction_source_properties,
|
.get_properties = image_reaction_source_properties,
|
||||||
.icon_type = OBS_ICON_TYPE_IMAGE,
|
.icon_type = OBS_ICON_TYPE_IMAGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
OBS_DECLARE_MODULE()
|
OBS_DECLARE_MODULE()
|
||||||
OBS_MODULE_USE_DEFAULT_LOCALE("image-source", "en-US")
|
OBS_MODULE_USE_DEFAULT_LOCALE("image-reaction", "en-US")
|
||||||
MODULE_EXPORT const char *obs_module_description(void)
|
MODULE_EXPORT const char *obs_module_description(void)
|
||||||
{
|
{
|
||||||
return "Image reaction source";
|
return "Image reaction source";
|
||||||
|
Loading…
Reference in New Issue
Block a user