static obs_properties_t *color_grade_filter_properties(void *data) { struct lut_filter_data *s = data; struct dstr path = {0}; const char *slash; obs_properties_t *props = obs_properties_create(); struct dstr filter_str = {0}; dstr_cat(&filter_str, "(*.png)"); if (s && s->file && *s->file) { dstr_copy(&path, s->file); } else { dstr_copy(&path, obs_module_file("LUTs")); dstr_cat_ch(&path, '/'); } dstr_replace(&path, "\\", "/"); slash = strrchr(path.array, '/'); if (slash) dstr_resize(&path, slash - path.array + 1); obs_properties_add_path(props, SETTING_IMAGE_PATH, TEXT_IMAGE_PATH, OBS_PATH_FILE, filter_str.array, path.array); obs_properties_add_float_slider(props, SETTING_CLUT_AMOUNT, TEXT_AMOUNT, 0, 1, 0.01); dstr_free(&filter_str); UNUSED_PARAMETER(data); return props; }
static obs_properties_t *image_source_properties(void *data) { struct image_source *s = data; struct dstr path = {0}; obs_properties_t *props = obs_properties_create(); if (s && s->file && *s->file) { const char *slash; dstr_copy(&path, s->file); dstr_replace(&path, "\\", "/"); slash = strrchr(path.array, '/'); if (slash) dstr_resize(&path, slash - path.array + 1); } obs_properties_add_path(props, "file", obs_module_text("File"), OBS_PATH_FILE, image_filter, path.array); obs_properties_add_bool(props, "unload", obs_module_text("UnloadWhenNotShowing")); dstr_free(&path); return props; }
static inline void make_data_dir(struct dstr *parsed_data_dir, const char *data_dir, const char *name) { dstr_copy(parsed_data_dir, data_dir); dstr_replace(parsed_data_dir, "%module%", name); if (dstr_end(parsed_data_dir) == '/') dstr_resize(parsed_data_dir, parsed_data_dir->len - 1); }
void dstr_from_wcs(struct dstr *dst, const wchar_t *wstr) { size_t len = wchar_to_utf8(wstr, 0, NULL, 0, 0); if (len) { dstr_resize(dst, len); wchar_to_utf8(wstr, 0, dst->array, len+1, 0); } else { dstr_free(dst); } }
static inline char *get_module_name(const char *file) { static size_t ext_len = 0; struct dstr name = {0}; if (ext_len == 0) { const char *ext = get_module_extension(); ext_len = strlen(ext); } dstr_copy(&name, file); dstr_resize(&name, name.len - ext_len); return name.array; }
static void process_found_module(struct obs_module_path *omp, const char *path, bool directory, obs_find_module_callback_t callback, void *param) { struct obs_module_info info; struct dstr name = {0}; struct dstr parsed_bin_path = {0}; const char *file; char *parsed_data_dir; bool bin_found = true; file = strrchr(path, '/'); file = file ? (file + 1) : path; if (strcmp(file, ".") == 0 || strcmp(file, "..") == 0) return; dstr_copy(&name, file); if (!directory) { char *ext = strrchr(name.array, '.'); if (ext) dstr_resize(&name, ext - name.array); dstr_copy(&parsed_bin_path, path); } else { bin_found = parse_binary_from_directory(&parsed_bin_path, omp->bin, file); } parsed_data_dir = make_data_directory(name.array, omp->data); if (parsed_data_dir && bin_found) { info.bin_path = parsed_bin_path.array; info.data_path = parsed_data_dir; callback(param, &info); } bfree(parsed_data_dir); dstr_free(&name); dstr_free(&parsed_bin_path); }
static void make_globent(struct os_globent *ent, WIN32_FIND_DATA *wfd, const char *pattern) { struct dstr name = {0}; struct dstr path = {0}; char *slash; dstr_from_wcs(&name, wfd->cFileName); dstr_copy(&path, pattern); slash = strrchr(path.array, '/'); if (slash) dstr_resize(&path, slash + 1 - path.array); else dstr_free(&path); dstr_cat_dstr(&path, &name); ent->path = path.array; ent->directory = is_dir(wfd); dstr_free(&name); }
static void find_modules_in_path(struct obs_module_path *omp, obs_find_module_callback_t callback, void *param) { struct dstr search_path = {0}; char *module_start; bool search_directories = false; os_glob_t *gi; dstr_copy(&search_path, omp->bin); module_start = strstr(search_path.array, "%module%"); if (module_start) { dstr_resize(&search_path, module_start - search_path.array); search_directories = true; } if (!dstr_is_empty(&search_path) && dstr_end(&search_path) != '/') dstr_cat_ch(&search_path, '/'); dstr_cat_ch(&search_path, '*'); if (!search_directories) dstr_cat(&search_path, get_module_extension()); if (os_glob(search_path.array, 0, &gi) == 0) { for (size_t i = 0; i < gi->gl_pathc; i++) { if (search_directories == gi->gl_pathv[i].directory) process_found_module(omp, gi->gl_pathv[i].path, search_directories, callback, param); } os_globfree(gi); } dstr_free(&search_path); }
/* * List available devices */ static void v4l2_device_list(obs_property_t *prop, obs_data_t *settings) { DIR *dirp; struct dirent *dp; struct dstr device; bool cur_device_found; size_t cur_device_index; const char *cur_device_name; #ifdef __FreeBSD__ dirp = opendir("/dev"); #else dirp = opendir("/sys/class/video4linux"); #endif if (!dirp) return; cur_device_found = false; cur_device_name = obs_data_get_string(settings, "device_id"); obs_property_list_clear(prop); dstr_init_copy(&device, "/dev/"); while ((dp = readdir(dirp)) != NULL) { int fd; uint32_t caps; struct v4l2_capability video_cap; #ifdef __FreeBSD__ if (strstr(dp->d_name, "video") == NULL) continue; #endif if (dp->d_type == DT_DIR) continue; dstr_resize(&device, 5); dstr_cat(&device, dp->d_name); if ((fd = v4l2_open(device.array, O_RDWR | O_NONBLOCK)) == -1) { blog(LOG_INFO, "Unable to open %s", device.array); continue; } if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) { blog(LOG_INFO, "Failed to query capabilities for %s", device.array); v4l2_close(fd); continue; } #ifndef V4L2_CAP_DEVICE_CAPS caps = video_cap.capabilities; #else /* ... since Linux 3.3 */ caps = (video_cap.capabilities & V4L2_CAP_DEVICE_CAPS) ? video_cap.device_caps : video_cap.capabilities; #endif if (!(caps & V4L2_CAP_VIDEO_CAPTURE)) { blog(LOG_INFO, "%s seems to not support video capture", device.array); v4l2_close(fd); continue; } obs_property_list_add_string(prop, (char *) video_cap.card, device.array); blog(LOG_INFO, "Found device '%s' at %s", video_cap.card, device.array); /* check if this is the currently used device */ if (cur_device_name && !strcmp(cur_device_name, device.array)) cur_device_found = true; v4l2_close(fd); } /* add currently selected device if not present, but disable it ... */ if (!cur_device_found && cur_device_name && strlen(cur_device_name)) { cur_device_index = obs_property_list_add_string(prop, cur_device_name, cur_device_name); obs_property_list_item_disable(prop, cur_device_index, true); } closedir(dirp); dstr_free(&device); }
void dstr_left(struct dstr *dst, const struct dstr *str, const size_t pos) { dstr_resize(dst, pos); if (dst != str) memcpy(dst->array, str->array, pos); }
static obs_properties_t *ffmpeg_source_getproperties(void *data) { struct ffmpeg_source *s = data; struct dstr filter = {0}; struct dstr path = {0}; UNUSED_PARAMETER(data); obs_properties_t *props = obs_properties_create(); obs_properties_set_flags(props, OBS_PROPERTIES_DEFER_UPDATE); obs_property_t *prop; // use this when obs allows non-readonly paths prop = obs_properties_add_bool(props, "is_local_file", obs_module_text("LocalFile")); obs_property_set_modified_callback(prop, is_local_file_modified); dstr_copy(&filter, obs_module_text("MediaFileFilter.AllMediaFiles")); dstr_cat(&filter, media_filter); dstr_cat(&filter, obs_module_text("MediaFileFilter.VideoFiles")); dstr_cat(&filter, video_filter); dstr_cat(&filter, obs_module_text("MediaFileFilter.AudioFiles")); dstr_cat(&filter, audio_filter); dstr_cat(&filter, obs_module_text("MediaFileFilter.AllFiles")); dstr_cat(&filter, " (*.*)"); if (s && s->input && *s->input) { const char *slash; dstr_copy(&path, s->input); dstr_replace(&path, "\\", "/"); slash = strrchr(path.array, '/'); if (slash) dstr_resize(&path, slash - path.array + 1); } obs_properties_add_path(props, "local_file", obs_module_text("LocalFile"), OBS_PATH_FILE, filter.array, path.array); dstr_free(&filter); dstr_free(&path); prop = obs_properties_add_bool(props, "looping", obs_module_text("Looping")); obs_properties_add_bool(props, "restart_on_activate", obs_module_text("RestartWhenActivated")); obs_properties_add_text(props, "input", obs_module_text("Input"), OBS_TEXT_DEFAULT); obs_properties_add_text(props, "input_format", obs_module_text("InputFormat"), OBS_TEXT_DEFAULT); #ifndef __APPLE__ obs_properties_add_bool(props, "hw_decode", obs_module_text("HardwareDecode")); #endif obs_properties_add_bool(props, "clear_on_media_end", obs_module_text("ClearOnMediaEnd")); prop = obs_properties_add_bool(props, "close_when_inactive", obs_module_text("CloseFileWhenInactive")); obs_property_set_long_description(prop, obs_module_text("CloseFileWhenInactive.ToolTip")); prop = obs_properties_add_list(props, "color_range", obs_module_text("ColorRange"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); obs_property_list_add_int(prop, obs_module_text("ColorRange.Auto"), VIDEO_RANGE_DEFAULT); obs_property_list_add_int(prop, obs_module_text("ColorRange.Partial"), VIDEO_RANGE_PARTIAL); obs_property_list_add_int(prop, obs_module_text("ColorRange.Full"), VIDEO_RANGE_FULL); return props; }
static obs_properties_t *ffmpeg_source_getproperties(void *data) { struct ffmpeg_source *s = data; struct dstr filter = {0}; struct dstr path = {0}; UNUSED_PARAMETER(data); obs_properties_t *props = obs_properties_create(); obs_properties_set_flags(props, OBS_PROPERTIES_DEFER_UPDATE); obs_property_t *prop; // use this when obs allows non-readonly paths prop = obs_properties_add_bool(props, "is_local_file", obs_module_text("LocalFile")); obs_property_set_modified_callback(prop, is_local_file_modified); dstr_copy(&filter, obs_module_text("MediaFileFilter.AllMediaFiles")); dstr_cat(&filter, media_filter); dstr_cat(&filter, obs_module_text("MediaFileFilter.VideoFiles")); dstr_cat(&filter, video_filter); dstr_cat(&filter, obs_module_text("MediaFileFilter.AudioFiles")); dstr_cat(&filter, audio_filter); dstr_cat(&filter, obs_module_text("MediaFileFilter.AllFiles")); dstr_cat(&filter, " (*.*)"); if (s && s->input && *s->input) { const char *slash; dstr_copy(&path, s->input); dstr_replace(&path, "\\", "/"); slash = strrchr(path.array, '/'); if (slash) dstr_resize(&path, slash - path.array + 1); } obs_properties_add_path(props, "local_file", obs_module_text("LocalFile"), OBS_PATH_FILE, filter.array, path.array); dstr_free(&filter); dstr_free(&path); obs_properties_add_bool(props, "looping", obs_module_text("Looping")); obs_properties_add_bool(props, "restart_on_activate", obs_module_text("RestartWhenActivated")); obs_properties_add_text(props, "input", obs_module_text("Input"), OBS_TEXT_DEFAULT); obs_properties_add_text(props, "input_format", obs_module_text("InputFormat"), OBS_TEXT_DEFAULT); obs_properties_add_bool(props, "hw_decode", obs_module_text("HardwareDecode")); obs_properties_add_bool(props, "clear_on_media_end", obs_module_text("ClearOnMediaEnd")); prop = obs_properties_add_bool(props, "advanced", obs_module_text("Advanced")); obs_property_set_modified_callback(prop, is_advanced_modified); obs_properties_add_bool(props, "force_scale", obs_module_text("ForceFormat")); prop = obs_properties_add_int(props, "audio_buffer_size", obs_module_text("AudioBufferSize"), 1, 9999, 1); obs_property_set_visible(prop, false); prop = obs_properties_add_int(props, "video_buffer_size", obs_module_text("VideoBufferSize"), 1, 9999, 1); obs_property_set_visible(prop, false); prop = obs_properties_add_list(props, "frame_drop", obs_module_text("FrameDropping"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); obs_property_list_add_int(prop, obs_module_text("DiscardNone"), AVDISCARD_NONE); obs_property_list_add_int(prop, obs_module_text("DiscardDefault"), AVDISCARD_DEFAULT); obs_property_list_add_int(prop, obs_module_text("DiscardNonRef"), AVDISCARD_NONREF); obs_property_list_add_int(prop, obs_module_text("DiscardBiDir"), AVDISCARD_BIDIR); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 67, 100) obs_property_list_add_int(prop, obs_module_text("DiscardNonIntra"), AVDISCARD_NONINTRA); #endif obs_property_list_add_int(prop, obs_module_text("DiscardNonKey"), AVDISCARD_NONKEY); obs_property_list_add_int(prop, obs_module_text("DiscardAll"), AVDISCARD_ALL); obs_property_set_visible(prop, false); prop = obs_properties_add_list(props, "color_range", obs_module_text("ColorRange"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); obs_property_list_add_int(prop, obs_module_text("ColorRange.Auto"), VIDEO_RANGE_DEFAULT); obs_property_list_add_int(prop, obs_module_text("ColorRange.Partial"), VIDEO_RANGE_PARTIAL); obs_property_list_add_int(prop, obs_module_text("ColorRange.Full"), VIDEO_RANGE_FULL); obs_property_set_visible(prop, false); return props; }