static inline void ep_write_var(struct dstr *shader, struct ep_var *var) { if (var->var_type == EP_VAR_INOUT) dstr_cat(shader, "inout "); else if (var->var_type == EP_VAR_OUT) dstr_cat(shader, "out "); else if (var->var_type == EP_VAR_UNIFORM) dstr_cat(shader, "uniform "); // The "in" input modifier is implied by default, so leave it blank // in that case. dstr_cat(shader, var->type); dstr_cat(shader, " "); dstr_cat(shader, var->name); if (var->mapping) { dstr_cat(shader, " : "); dstr_cat(shader, var->mapping); } }
char *obs_find_module_file(obs_module_t *module, const char *file) { struct dstr output = {0}; if (!file) file = ""; if (!module) return NULL; dstr_copy(&output, module->data_path); if (!dstr_is_empty(&output) && dstr_end(&output) != '/' && *file) dstr_cat_ch(&output, '/'); dstr_cat(&output, file); if (!os_file_exists(output.array)) dstr_free(&output); return output.array; }
/* FIXME */ void qc_command(client c) { char buf[64]; dstr rid; struct crss *crss; snprintf(buf, sizeof buf, "%p,", c); rid = dstr_new(buf); rid = dstr_cat(rid, c->argv[1]); if (rids == NULL) rids = table_new(cmpstr, hashmurmur2, kfree, NULL); table_lock(rids); if ((crss = table_get_value(rids, rid))) { crss->cancel = 1; xcb_log(XCB_LOG_DEBUG, "Query with rid '%s' got cancelled", c->argv[1]); } table_unlock(rids); add_reply_string(c, "\r\n", 2); dstr_free(rid); }
void dstr_insert(struct dstr *dst, const size_t idx, const char *array) { size_t new_len, len; if (!array || !*array) return; if (idx == dst->len) { dstr_cat(dst, array); return; } len = strlen(array); new_len = dst->len + len; dstr_ensure_capacity(dst, new_len + 1); dst->len = new_len; memmove(dst->array+idx+len, dst->array+idx, dst->len - idx + 1); memcpy(dst->array+idx, array, len); }
static void gl_write_main_storage_assign(struct gl_shader_parser *glsp, struct shader_var *var, const char *dst, const char *src, bool input) { struct shader_struct *st; struct dstr dst_copy = {0}; char ch_left = input ? '.' : '_'; char ch_right = input ? '_' : '.'; if (dst) { dstr_copy(&dst_copy, dst); dstr_cat_ch(&dst_copy, ch_left); } else { dstr_copy(&dst_copy, "\t"); } dstr_cat(&dst_copy, var->name); st = shader_parser_getstruct(&glsp->parser, var->type); if (st) { struct dstr src_copy = {0}; size_t i; if (src) dstr_copy(&src_copy, src); dstr_cat(&src_copy, var->name); dstr_cat_ch(&src_copy, ch_right); for (i = 0; i < st->vars.num; i++) { struct shader_var *st_var = st->vars.array+i; gl_write_main_storage_assign(glsp, st_var, dst_copy.array, src_copy.array, input); } dstr_free(&src_copy); } else { if (!dstr_isempty(&dst_copy)) dstr_cat_dstr(&glsp->gl_string, &dst_copy); dstr_cat(&glsp->gl_string, " = "); if (src) dstr_cat(&glsp->gl_string, src); dstr_cat(&glsp->gl_string, var->name); dstr_cat(&glsp->gl_string, ";\n"); if (!input) gl_write_main_interface_assign(glsp, var, src); } dstr_free(&dst_copy); }
static inline void ep_write_var(struct dstr *shader, struct ep_var *var) { if (var->uniform) dstr_cat(shader, "uniform "); dstr_cat(shader, var->type); dstr_cat(shader, " "); dstr_cat(shader, var->name); if (var->mapping) { dstr_cat(shader, " : "); dstr_cat(shader, var->mapping); } }
bool load_graphics_offsets(bool is32bit) { char *offset_exe_path = NULL; struct dstr offset_exe = {0}; struct dstr str = {0}; os_process_pipe_t *pp; bool success = false; char data[128]; dstr_copy(&offset_exe, "get-graphics-offsets"); dstr_cat(&offset_exe, is32bit ? "32.exe" : "64.exe"); offset_exe_path = obs_module_file(offset_exe.array); pp = os_process_pipe_create(offset_exe_path, "r"); if (!pp) { blog(LOG_INFO, "load_graphics_offsets: Failed to start '%s'", offset_exe.array); goto error; } for (;;) { size_t len = os_process_pipe_read(pp, (uint8_t*)data, 128); if (!len) break; dstr_ncat(&str, data, len); } success = load_offsets_from_string(is32bit ? &offsets32 : &offsets64, str.array); if (!success) { blog(LOG_INFO, "load_graphics_offsets: Failed to load string"); } os_process_pipe_destroy(pp); error: bfree(offset_exe_path); dstr_free(&offset_exe); dstr_free(&str); return success; }
void *os_dlopen(const char *path) { struct dstr dll_name; wchar_t *wpath; HMODULE h_library = NULL; dstr_init_copy(&dll_name, path); dstr_cat(&dll_name, ".dll"); os_utf8_to_wcs(dll_name.array, 0, &wpath); h_library = LoadLibraryW(wpath); bfree(wpath); dstr_free(&dll_name); if (!h_library) blog(LOG_INFO, "LoadLibrary failed for '%s', error: %u", path, GetLastError()); return h_library; }
/* writes mapped vars used by the call as parameters for main */ static void ep_write_main_params(struct effect_parser *ep, struct dstr *shader, struct dstr *param_str, struct ep_func *func) { size_t i; bool empty_params = dstr_is_empty(param_str); for (i = 0; i < func->param_vars.num; i++) { struct ep_var *var = func->param_vars.array+i; struct ep_struct *st = NULL; bool mapped = (var->mapping != NULL); if (!mapped) { st = ep_getstruct(ep, var->type); if (st) mapped = ep_struct_mapped(st); } if (mapped) { dstr_cat(shader, var->type); dstr_cat(shader, " "); dstr_cat(shader, var->name); if (!st) { dstr_cat(shader, " : "); dstr_cat(shader, var->mapping); } if (!dstr_is_empty(param_str)) dstr_cat(param_str, ", "); dstr_cat(param_str, var->name); } } if (!empty_params) dstr_cat(param_str, ", "); }
dstr dstr_cat_vprintf(dstr ds, const char *fmt, va_list ap) { char *buf, *tmp; size_t len = 16; va_list cpy; for (;;) { if ((buf = ALLOC(len)) == NULL) return NULL; buf[len - 2] = '\0'; va_copy(cpy, ap); vsnprintf(buf, len, fmt, cpy); if (buf[len - 2] != '\0') { FREE(buf); len *= 2; continue; } break; } tmp = dstr_cat(ds, buf); FREE(buf); return tmp; }
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); }
static void gl_write_struct(struct gl_shader_parser *glsp, struct shader_struct *st) { size_t i; dstr_cat(&glsp->gl_string, "struct "); dstr_cat(&glsp->gl_string, st->name); dstr_cat(&glsp->gl_string, " {\n"); for (i = 0; i < st->vars.num; i++) { struct shader_var *var = st->vars.array+i; dstr_cat(&glsp->gl_string, "\t"); gl_write_var(glsp, var); dstr_cat(&glsp->gl_string, ";\n"); } dstr_cat(&glsp->gl_string, "};\n\n"); }
static void ep_write_struct(struct dstr *shader, struct ep_struct *st) { size_t i; if (st->written) return; dstr_cat(shader, "struct "); dstr_cat(shader, st->name); dstr_cat(shader, " {"); for (i = 0; i < st->vars.num; i++) { dstr_cat(shader, "\n\t"); ep_write_var(shader, st->vars.array+i); dstr_cat(shader, ";"); } dstr_cat(shader, "\n};\n"); st->written = true; }
static bool gl_write_intrinsic(struct gl_shader_parser *glsp, struct cf_token **p_token) { struct cf_token *token = *p_token; bool written = true; if (strref_cmp(&token->str, "atan2") == 0) { dstr_cat(&glsp->gl_string, "atan2"); } else if (strref_cmp(&token->str, "ddx") == 0) { dstr_cat(&glsp->gl_string, "dFdx"); } else if (strref_cmp(&token->str, "ddy") == 0) { dstr_cat(&glsp->gl_string, "dFdy"); } else if (strref_cmp(&token->str, "frac") == 0) { dstr_cat(&glsp->gl_string, "fract"); } else if (strref_cmp(&token->str, "lerp") == 0) { dstr_cat(&glsp->gl_string, "mix"); } else if (strref_cmp(&token->str, "fmod") == 0) { dstr_cat(&glsp->gl_string, "mod"); } else if (strref_cmp(&token->str, "rsqrt") == 0) { dstr_cat(&glsp->gl_string, "inversesqrt"); } else if (strref_cmp(&token->str, "saturate") == 0) { written = gl_write_saturate(glsp, &token); } else if (strref_cmp(&token->str, "mul") == 0) { written = gl_write_mul(glsp, &token); } else { struct shader_var *var = sp_getparam(glsp, token); if (var && astrcmp_n(var->type, "texture", 7) == 0) written = gl_write_texture_code(glsp, &token, var); else written = false; } if (written) *p_token = token; return written; }
static inline bool ep_compile_pass_shader(struct effect_parser *ep, struct gs_effect_technique *tech, struct gs_effect_pass *pass, struct ep_pass *pass_in, size_t pass_idx, enum gs_shader_type type) { struct dstr shader_str; struct dstr location; struct darray used_params; /* struct dstr */ struct darray *pass_params = NULL; /* struct pass_shaderparam */ gs_shader_t *shader = NULL; bool success = true; dstr_init(&shader_str); darray_init(&used_params); dstr_init(&location); dstr_copy(&location, ep->cfp.lex.file); if (type == GS_SHADER_VERTEX) dstr_cat(&location, " (Vertex "); else if (type == GS_SHADER_PIXEL) dstr_cat(&location, " (Pixel "); /*else if (type == SHADER_GEOMETRY) dstr_cat(&location, " (Geometry ");*/ assert(pass_idx <= UINT_MAX); dstr_catf(&location, "shader, technique %s, pass %u)", tech->name, (unsigned)pass_idx); if (type == GS_SHADER_VERTEX) { ep_makeshaderstring(ep, &shader_str, &pass_in->vertex_program.da, &used_params); pass->vertshader = gs_vertexshader_create(shader_str.array, location.array, NULL); shader = pass->vertshader; pass_params = &pass->vertshader_params.da; } else if (type == GS_SHADER_PIXEL) { ep_makeshaderstring(ep, &shader_str, &pass_in->fragment_program.da, &used_params); pass->pixelshader = gs_pixelshader_create(shader_str.array, location.array, NULL); shader = pass->pixelshader; pass_params = &pass->pixelshader_params.da; } #if 0 blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++"); blog(LOG_DEBUG, " %s", location.array); blog(LOG_DEBUG, "-----------------------------------"); blog(LOG_DEBUG, "%s", shader_str.array); blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++"); #endif if (shader) success = ep_compile_pass_shaderparams(ep, pass_params, &used_params, shader); else success = false; dstr_free(&location); dstr_array_free(used_params.array, used_params.num); darray_free(&used_params); dstr_free(&shader_str); return success; }
static void *recv_thread(void *data) { NOT_USED(data); while (loop) { struct pollfd rfd[1]; char buf[256]; int nread; rfd[0].fd = tcpsock; rfd[0].events = POLLIN; if (poll(rfd, 1, -1) == -1) { if (execute) { fprintf(stderr, "Reading from server: %s\n", strerror(errno)); exit(1); } else { snprintf(buf, sizeof buf, "Reading from server: %s", strerror(errno)); CLIPRINT(buf); break; } } if ((nread = read(tcpsock, inbuf + inpos, sizeof inbuf - inpos)) == -1) { if (errno == EAGAIN || errno == EINTR) nread = 0; else { if (execute) { fprintf(stderr, "Reading from server: %s\n", strerror(errno)); exit(1); } else { snprintf(buf, sizeof buf, "Reading from server: %s", strerror(errno)); CLIPRINT(buf); break; } } } else if (nread == 0) { if (execute) { fprintf(stderr, "Server closed connection\n"); exit(1); } else { snprintf(buf, sizeof buf, "Server closed connection"); CLIPRINT(buf); break; } } if (nread) inpos += nread; else continue; inbuf[inpos] = '\0'; while (inpos > 0) { char *newline; size_t len; if ((newline = strstr(inbuf, "\r\n")) == NULL) { if (inpos == sizeof inbuf - 1) { if (execute) { fprintf(stderr, "Server error: too big reply\n"); exit(1); } else { snprintf(buf, sizeof buf, "Server error: too big reply"); CLIPRINT(buf); inpos = 0; } } break; } if ((len = newline - inbuf) == 0) { const char one = '1'; if (execute && write(proceed_pipe[1], &one, sizeof(one)) == -1) { fprintf(stderr, "Error writing: %s", strerror(errno)); exit(1); } } else { /* FIXME */ *newline = '\0'; if (timestamp) { struct timeval tv; char datestr[64]; int off; dstr res; gettimeofday(&tv, NULL); off = strftime(datestr, sizeof datestr, "[%b %e %T.", localtime(&tv.tv_sec)); snprintf(datestr + off, sizeof datestr - off, "%06d]", (int)tv.tv_usec); res = dstr_new(datestr); res = dstr_cat(res, inbuf); if (execute) { if (strncasecmp(inbuf, "HEARTBEAT", 9) && strncasecmp(inbuf, "INDICES", 7)) fprintf(stdout, "%s\n", res); } else CLIPRINT(res); dstr_free(res); } else { if (execute) { if (strncasecmp(inbuf, "HEARTBEAT", 9) && strncasecmp(inbuf, "INDICES", 7)) fprintf(stdout, "%s\n", inbuf); } else CLIPRINT(inbuf); } } memmove(inbuf, inbuf + len + 2, sizeof inbuf - len - 2); inpos -= len + 2; } } close(tcpsock); tcpsock = -1; return NULL; }
int main(int argc, char **argv) { int opt, count = 1; pthread_t thread; /* FIXME */ ip = dstr_new("127.0.0.1"); port = 33330; while ((opt = getopt(argc, argv, "h:p:xt?")) != -1) switch (opt) { case 'h': dstr_free(ip); ip = dstr_new(optarg); count += 2; break; case 'p': port = atoi(optarg); count += 2; break; case 'x': execute = 1; count += 1; break; case 't': timestamp = 1; count += 1; break; case '?': default: usage(); } if ((tcpsock = net_tcp_nonblock_connect(ip, port, neterr, sizeof neterr)) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, neterr); exit(1); } if (errno == EINPROGRESS) { struct pollfd wfd[1]; int res, err = 0; socklen_t errlen = sizeof err; wfd[0].fd = tcpsock; wfd[0].events = POLLOUT; /* wait for 5 seconds */ if ((res = poll(wfd, 1, 5000)) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } else if (res == 0) { errno = ETIMEDOUT; fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } if (getsockopt(tcpsock, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } if (err) { errno = err; fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } } if (execute && pipe(proceed_pipe) != 0) { fprintf(stderr, "Error creating pipe: %s\n", strerror(errno)); exit(1); } if (execute) { argc -= count; argv += count; if (argc > 0) { dstr cmd; int i; struct pollfd rfd[1]; if (pthread_create(&thread, NULL, recv_thread, NULL) != 0) { fprintf(stderr, "Error initializing receiver thread\n"); exit(1); } cmd = dstr_new(argv[0]); for (i = 1; i < argc; ++i) { cmd = dstr_cat(cmd, " "); cmd = dstr_cat(cmd, argv[i]); } cmd = dstr_cat(cmd, "\r\n"); net_try_write(tcpsock, cmd, dstr_length(cmd), 100, NET_NONBLOCK); /* dstr_free(cmd); */ rfd[0].fd = proceed_pipe[0]; rfd[0].events = POLLIN; if (poll(rfd, 1, -1) == -1) { fprintf(stderr, "Error polling: %s\n", strerror(errno)); exit(1); } } } else { fprintf(stdout, "XCUBE CLI, Copyright (c) 2013-2015, " "Dalian Futures Information Technology Co., Ltd.\n"); fprintf(stdout, "Type 'help' or '?' for help.\n"); init_readline(); stifle_history(100); if (pthread_create(&thread, NULL, recv_thread, NULL) != 0) { fprintf(stderr, "Error initializing receiver thread\n"); exit(1); } while (loop) { char *line; line = readline(prompt); if (rl_inited == 0) rl_inited = 1; if (line == NULL) continue; LTRIM(line); RTRIM(line); if (*line) { add_history(line); if (tcpsock == -1) execute_line(line); else { net_try_write(tcpsock, line, strlen(line), 100, NET_NONBLOCK); net_try_write(tcpsock, "\r\n", 2, 100, NET_NONBLOCK); if (!strncasecmp(line, "quit", 4)) com_quit(NULL); } } FREE(line); } } return 0; }
static bool build_flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size, size_t a_idx) { obs_encoder_t *vencoder = obs_output_get_video_encoder(context); obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, a_idx); video_t *video = obs_encoder_video(vencoder); audio_t *audio = obs_encoder_audio(aencoder); char buf[4096]; char *enc = buf; char *end = enc+sizeof(buf); struct dstr encoder_name = {0}; if (a_idx > 0 && !aencoder) return false; enc_str(&enc, end, "onMetaData"); *enc++ = AMF_ECMA_ARRAY; enc = AMF_EncodeInt32(enc, end, a_idx == 0 ? 14 : 9); enc_num_val(&enc, end, "duration", 0.0); enc_num_val(&enc, end, "fileSize", 0.0); if (a_idx == 0) { enc_num_val(&enc, end, "width", (double)obs_encoder_get_width(vencoder)); enc_num_val(&enc, end, "height", (double)obs_encoder_get_height(vencoder)); enc_str_val(&enc, end, "videocodecid", "avc1"); enc_num_val(&enc, end, "videodatarate", encoder_bitrate(vencoder)); enc_num_val(&enc, end, "framerate", video_output_get_frame_rate(video)); } enc_str_val(&enc, end, "audiocodecid", "mp4a"); enc_num_val(&enc, end, "audiodatarate", encoder_bitrate(aencoder)); enc_num_val(&enc, end, "audiosamplerate", (double)obs_encoder_get_sample_rate(aencoder)); enc_num_val(&enc, end, "audiosamplesize", 16.0); enc_num_val(&enc, end, "audiochannels", (double)audio_output_get_channels(audio)); enc_bool_val(&enc, end, "stereo", audio_output_get_channels(audio) == 2); enc_bool_val(&enc, end, "2.1", audio_output_get_channels(audio) == 3); enc_bool_val(&enc, end, "3.1", audio_output_get_channels(audio) == 4); enc_bool_val(&enc, end, "4.0", audio_output_get_channels(audio) == 4); enc_bool_val(&enc, end, "4.1", audio_output_get_channels(audio) == 5); enc_bool_val(&enc, end, "5.1", audio_output_get_channels(audio) == 6); enc_bool_val(&enc, end, "7.1", audio_output_get_channels(audio) == 8); dstr_printf(&encoder_name, "%s (libobs version ", MODULE_NAME); #ifdef HAVE_OBSCONFIG_H dstr_cat(&encoder_name, OBS_VERSION); #else dstr_catf(&encoder_name, "%d.%d.%d", LIBOBS_API_MAJOR_VER, LIBOBS_API_MINOR_VER, LIBOBS_API_PATCH_VER); #endif dstr_cat(&encoder_name, ")"); enc_str_val(&enc, end, "encoder", encoder_name.array); dstr_free(&encoder_name); *enc++ = 0; *enc++ = 0; *enc++ = AMF_OBJECT_END; *size = enc-buf; *output = bmemdup(buf, *size); return true; }
static int server_cron(event_loop el, unsigned long id, void *data) { dlist_iter_t iter; dlist_node_t node; NOT_USED(el); NOT_USED(id); NOT_USED(data); if (log_reload) { close_logger(); if (init_logger("/var/log/xcb/xcb-dp2.log", __LOG_DEBUG) == 0) { const char *tmp; pthread_mutex_lock(&cfg_lock); if ((tmp = variable_retrieve(cfg, "general", "log_level"))) { if (!strcasecmp(tmp, "debug")) set_logger_level(__LOG_DEBUG); else if (!strcasecmp(tmp, "info")) set_logger_level(__LOG_INFO); else if (!strcasecmp(tmp, "notice")) set_logger_level(__LOG_NOTICE); else if (!strcasecmp(tmp, "warning")) set_logger_level(__LOG_WARNING); } pthread_mutex_unlock(&cfg_lock); log_reload = 0; } /* FIXME */ if (addms) table_clear(times); } if (shut_down) { if (prepare_for_shutdown() == 0) exit(0); xcb_log(XCB_LOG_WARNING, "SIGTERM received, but errors trying to shutdown the server"); } /* FIXME */ iter = dlist_iter_new(clients_to_close, DLIST_START_HEAD); while ((node = dlist_next(iter))) { client c = (client)dlist_node_value(node); if (c->refcount == 0) client_free(c); } dlist_iter_free(&iter); /* FIXME */ if (cronloops % 200 == 0) { char meme[] = "SU OT GNOLEB ERA ESAB RUOY LLA"; int status; /* heartbeat */ dlist_lock(clients); if (dlist_length(clients) > 0) { dstr res = dstr_new("HEARTBEAT|"); dstr ip = getipv4(); res = dstr_cat(res, ip); res = dstr_cat(res, "\r\n"); iter = dlist_iter_new(clients, DLIST_START_HEAD); while ((node = dlist_next(iter))) { client c = (client)dlist_node_value(node); pthread_spin_lock(&c->lock); if (net_try_write(c->fd, res, dstr_length(res), 100, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", c, strerror(errno)); pthread_spin_unlock(&c->lock); } dlist_iter_free(&iter); dstr_free(ip); dstr_free(res); } dlist_unlock(clients); /* FIXME: trying to lower the high CPU load while idle */ if ((status = pgm_send(pgm_sender, meme, sizeof meme, NULL)) != PGM_IO_STATUS_NORMAL) xcb_log(XCB_LOG_WARNING, "Communication test failed"); } ++cronloops; return 100; }
static inline void gl_write_type(struct gl_shader_parser *glsp, const char *type) { if (!gl_write_type_n(glsp, type, strlen(type))) dstr_cat(&glsp->gl_string, type); }
/* FIXME */ void q_command(client c) { struct tm tm; char *end; char buf[64]; dstr rid; struct crss *crss; if (!persistence) { add_reply_error(c, "database not open\r\n"); return; } if (dstr_length(c->argv[0]) == 1) { add_reply_error(c, "index can't be empty\r\n"); return; } if ((end = strptime(c->argv[3], "%F %T", &tm)) && *end == '\0') c->argv[3] = dstr_cat(c->argv[3], ".000"); else if ((end = strptime(c->argv[3], "%F %R", &tm)) && *end == '\0') c->argv[3] = dstr_cat(c->argv[3], ":00.000"); else { add_reply_error(c, "invalid time format, " "please use 'YYYY-mm-dd HH:MM:SS' or 'YYYY-mm-dd HH:MM'.\r\n"); return; } if ((end = strptime(c->argv[4], "%F %T", &tm)) && *end == '\0') c->argv[4] = dstr_cat(c->argv[4], ".999"); else if ((end = strptime(c->argv[4], "%F %R", &tm)) && *end == '\0') c->argv[4] = dstr_cat(c->argv[4], ":59.999"); else { add_reply_error(c, "invalid time format, " "please use 'YYYY-mm-dd HH:MM:SS' or 'YYYY-mm-dd HH:MM'.\r\n"); return; } snprintf(buf, sizeof buf, "%p,", c); rid = dstr_new(buf); rid = dstr_cat(rid, c->argv[1]); if (rids == NULL) rids = table_new(cmpstr, hashmurmur2, kfree, NULL); table_lock(rids); if ((crss = table_get_value(rids, rid))) { add_reply_error_format(c, "query with rid '%s' already exists\r\n", c->argv[1]); dstr_free(rid); } else if (NEW(crss)) { pthread_t thread; crss->c = c; crss->rid = dstr_new(c->argv[1]); crss->match = dstr_new(c->argv[2]); crss->start = dstr_new(c->argv[0] + 1); crss->start = dstr_cat(crss->start, ","); crss->start = dstr_cat(crss->start, c->argv[3]); crss->stop = dstr_new(c->argv[0] + 1); crss->stop = dstr_cat(crss->stop, ","); crss->stop = dstr_cat(crss->stop, c->argv[4]); crss->cancel = 0; if (pthread_create(&thread, NULL, q_thread, crss) != 0) { add_reply_error(c, strerror(errno)); add_reply_string(c, "\r\n", 2); dstr_free(crss->rid); dstr_free(crss->match); dstr_free(crss->start); dstr_free(crss->stop); FREE(crss); dstr_free(rid); } else { client_incr(crss->c); table_insert(rids, rid, crss); } } else { add_reply_error(c, "error allocating memory for crss\r\n"); dstr_free(rid); } table_unlock(rids); }
static int try_connect(struct rtmp_stream *stream) { if (dstr_is_empty(&stream->path)) { warn("URL is empty"); return OBS_OUTPUT_BAD_PATH; } info("Connecting to RTMP URL %s...", stream->path.array); memset(&stream->rtmp.Link, 0, sizeof(stream->rtmp.Link)); if (!RTMP_SetupURL(&stream->rtmp, stream->path.array)) return OBS_OUTPUT_BAD_PATH; RTMP_EnableWrite(&stream->rtmp); dstr_copy(&stream->encoder_name, "FMLE/3.0 (compatible; obs-studio/"); #ifdef HAVE_OBSCONFIG_H dstr_cat(&stream->encoder_name, OBS_VERSION); #else dstr_catf(&stream->encoder_name, "%d.%d.%d", LIBOBS_API_MAJOR_VER, LIBOBS_API_MINOR_VER, LIBOBS_API_PATCH_VER); #endif dstr_cat(&stream->encoder_name, "; FMSc/1.0)"); set_rtmp_dstr(&stream->rtmp.Link.pubUser, &stream->username); set_rtmp_dstr(&stream->rtmp.Link.pubPasswd, &stream->password); set_rtmp_dstr(&stream->rtmp.Link.flashVer, &stream->encoder_name); stream->rtmp.Link.swfUrl = stream->rtmp.Link.tcUrl; RTMP_AddStream(&stream->rtmp, stream->key.array); for (size_t idx = 1;; idx++) { obs_encoder_t *encoder = obs_output_get_audio_encoder( stream->output, idx); const char *encoder_name; if (!encoder) break; encoder_name = obs_encoder_get_name(encoder); RTMP_AddStream(&stream->rtmp, encoder_name); } stream->rtmp.m_outChunkSize = 4096; stream->rtmp.m_bSendChunkSizeInfo = true; stream->rtmp.m_bUseNagle = true; #ifdef _WIN32 win32_log_interface_type(stream); #endif if (!RTMP_Connect(&stream->rtmp, NULL)) return OBS_OUTPUT_CONNECT_FAILED; if (!RTMP_ConnectStream(&stream->rtmp, 0)) return OBS_OUTPUT_INVALID_STREAM; info("Connection to %s successful", stream->path.array); return init_send(stream); }
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 bool gl_write_type_n(struct gl_shader_parser *glsp, const char *type, size_t len) { if (cmp_type(type, len, "float2", 6) == 0) dstr_cat(&glsp->gl_string, "vec2"); else if (cmp_type(type, len, "float3", 6) == 0) dstr_cat(&glsp->gl_string, "vec3"); else if (cmp_type(type, len, "float4", 6) == 0) dstr_cat(&glsp->gl_string, "vec4"); else if (cmp_type(type, len, "int2", 4) == 0) dstr_cat(&glsp->gl_string, "ivec2"); else if (cmp_type(type, len, "int3", 4) == 0) dstr_cat(&glsp->gl_string, "ivec3"); else if (cmp_type(type, len, "int4", 4) == 0) dstr_cat(&glsp->gl_string, "ivec4"); else if (cmp_type(type, len, "float3x3", 8) == 0) dstr_cat(&glsp->gl_string, "mat3x3"); else if (cmp_type(type, len, "float3x4", 8) == 0) dstr_cat(&glsp->gl_string, "mat3x4"); else if (cmp_type(type, len, "float4x4", 8) == 0) dstr_cat(&glsp->gl_string, "mat4x4"); else if (cmp_type(type, len, "texture2d", 9) == 0) dstr_cat(&glsp->gl_string, "sampler2D"); else if (cmp_type(type, len, "texture3d", 9) == 0) dstr_cat(&glsp->gl_string, "sampler3D"); else if (cmp_type(type, len, "texture_cube", 12) == 0) dstr_cat(&glsp->gl_string, "samplerCube"); else if (cmp_type(type, len, "texture_rect", 12) == 0) dstr_cat(&glsp->gl_string, "sampler2DRect"); else return false; return true; }
/* FIXME */ void s_command(client c) { dstr pkey, skey; int i; dlist_t dlist; struct kvd *kvd; if (dstr_length(c->argv[0]) == 1) { add_reply_error(c, "index can't be empty\r\n"); return; } pkey = dstr_new(c->argv[0] + 1); skey = dstr_new(pkey); //------------------------------------------------------------------------ dstr pre = dstr_new(pkey); dstr rest = dstr_new(""); //------------------------------------------------------------------------ if (c->argc > 1) for (i = 1; i < c->argc; ++i) { skey = dstr_cat(skey, ","); skey = dstr_cat(skey, c->argv[i]); //------------------------------------------------------------------------ rest = dstr_cat(rest,c->argv[i]); //------------------------------------------------------------------------ } /* table_lock(cache); if ((dlist = table_get_value(cache, pkey))) { dlist_iter_t iter = dlist_iter_new(dlist, DLIST_START_HEAD); dlist_node_t node; */ /* FIXME: still has room to improve */ /* while ((node = dlist_next(iter))) { kvd = (struct kvd *)dlist_node_value(node); if (dstr_length(kvd->key) >= dstr_length(skey) && !memcmp(kvd->key, skey, dstr_length(skey))) { dstr *fields = NULL; int nfield = 0; dstr res, contracts = NULL; fields = dstr_split_len(kvd->key, dstr_length(kvd->key), ",", 1, &nfield); res = dstr_new(fields[0]); if (nfield > 1) { contracts = dstr_new(fields[1]); for (i = 2; i < nfield; ++i) { contracts = dstr_cat(contracts, ","); contracts = dstr_cat(contracts, fields[i]); } } dstr_free_tokens(fields, nfield); fields = NULL, nfield = 0; fields = dstr_split_len(kvd->u.value, dstr_length(kvd->u.value), ",", 1, &nfield); res = dstr_cat(res, ","); res = dstr_cat(res, fields[0]); if (contracts) { res = dstr_cat(res, ","); res = dstr_cat(res, contracts); } for (i = 1; i < nfield; ++i) { res = dstr_cat(res, ","); res = dstr_cat(res, fields[i]); } res = dstr_cat(res, "\r\n"); pthread_spin_lock(&c->lock); if (!(c->flags & CLIENT_CLOSE_ASAP)) { if (net_try_write(c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", c, strerror(errno)); if (++c->eagcount >= 3) { client_free_async(c); pthread_spin_unlock(&c->lock); dstr_free(contracts); dstr_free(res); dstr_free_tokens(fields, nfield); table_unlock(cache); dstr_free(skey); dstr_free(pkey); return; } } else if (c->eagcount) c->eagcount = 0; } pthread_spin_unlock(&c->lock); dstr_free(contracts); dstr_free(res); dstr_free_tokens(fields, nfield); } } dlist_iter_free(&iter); } table_unlock(cache); */ //--------------------------------------------------------------------------------------------------- /* table_rwlock_wrlock(subscribers); if ((dlist = table_get_value(subscribers, pkey)) == NULL) { if (NEW(kvd)) { kvd->key = skey; kvd->u.dlist = dlist_new(NULL, NULL); dlist_insert_tail(kvd->u.dlist, c); dlist = dlist_new(cmpkvd, kdfree); dlist_insert_sort(dlist, kvd); table_insert(subscribers, pkey, dlist); } else { add_reply_error(c, "error allocating memory for kvd\r\n"); dstr_free(skey); dstr_free(pkey); } } else { if (NEW(kvd)) { dlist_node_t node; kvd->key = skey; kvd->u.dlist = dlist_new(NULL, NULL); if ((node = dlist_find(dlist, kvd)) == NULL) { dlist_insert_tail(kvd->u.dlist, c); dlist_insert_sort(dlist, kvd); } else { kdfree(kvd); kvd = (struct kvd *)dlist_node_value(node); if (dlist_find(kvd->u.dlist, c) == NULL) dlist_insert_tail(kvd->u.dlist, c); } } else { add_reply_error(c, "error allocating memory for kvd\r\n"); dstr_free(skey); } dstr_free(pkey); } table_rwlock_unlock(subscribers); */ //-------------------------------------------------------------------------------------------------------------------- // table_rwlock_wrlock(subscribers_radix); radix_block_insert(pre, ",", subscribers_radix->head); radix_insert(rest, radix_match(pre, subscribers_radix->head, subscribers_radix->head)); pre = dstr_cat(pre,rest); insert_value(pre, c, subscribers_radix->head); dstr_free(pre); dstr_free(rest); // table_rwlock_unlock(subscribers_radix); //--------------------------------------------------------------------------------------------------- }
static bool update_remote_files(void *param, obs_data_t *remote_file) { struct update_info *info = param; struct file_update_data data = { .name = obs_data_get_string(remote_file, "name"), .version = (int)obs_data_get_int(remote_file, "version") }; enum_files(info->cache_package, newer_than_cache, &data); if (!data.newer && data.found) return true; if (!do_relative_http_request(info, info->remote_url, data.name)) return true; if (info->callback) { struct file_download_data download_data; bool confirm; download_data.name = data.name; download_data.version = data.version; download_data.buffer.da = info->file_data.da; confirm = info->callback(info->param, &download_data); info->file_data.da = download_data.buffer.da; if (!confirm) { info("Update file '%s' (version %d) rejected", data.name, data.version); return true; } } write_file_data(info, info->temp, data.name); replace_file(info->temp, info->cache, data.name); info("Successfully updated file '%s' (version %d)", data.name, data.version); return true; } static void update_save_metadata(struct update_info *info) { struct dstr path = { 0 }; if (!info->etag_remote) return; dstr_copy(&path, info->cache); dstr_cat(&path, "meta.json"); obs_data_t *data; data = obs_data_create(); obs_data_set_string(data, "etag", info->etag_remote); obs_data_save_json(data, path.array); obs_data_release(data); } static void update_remote_version(struct update_info *info, int cur_version) { int remote_version; long response_code; if (!do_http_request(info, info->url, &response_code)) return; if (response_code == 304) return; if (!info->file_data.array || info->file_data.array[0] != '{') { warn("Remote package does not exist or is not valid json"); return; } update_save_metadata(info); info->remote_package = obs_data_create_from_json( (char*)info->file_data.array); if (!info->remote_package) { warn("Failed to initialize remote package json"); return; } remote_version = (int)obs_data_get_int(info->remote_package, "version"); if (remote_version <= cur_version) return; write_file_data(info, info->temp, "package.json"); info->remote_url = obs_data_get_string(info->remote_package, "url"); if (!info->remote_url) { warn("No remote url in package file"); return; } /* download new files */ enum_files(info->remote_package, update_remote_files, info); replace_file(info->temp, info->cache, "package.json"); info("Successfully updated package (version %d)", remote_version); return; }
static obs_properties_t *ffmpeg_source_getproperties(void *data) { struct dstr filter = {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, " (*.*)"); obs_properties_add_path(props, "local_file", obs_module_text("LocalFile"), OBS_PATH_FILE, filter.array, NULL); dstr_free(&filter); 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); return props; }
void obs_hotkeys_set_translations_s( struct obs_hotkeys_translations *translations, size_t size) { #define ADD_TRANSLATION(key_name, var_name) \ if (t.var_name) \ obs_set_key_translation(key_name, t.var_name); struct obs_hotkeys_translations t = {0}; struct dstr numpad = {0}; struct dstr mouse = {0}; struct dstr button = {0}; if (!translations) { return; } memcpy(&t, translations, (size < sizeof(t)) ? size : sizeof(t)); ADD_TRANSLATION(OBS_KEY_INSERT, insert); ADD_TRANSLATION(OBS_KEY_DELETE, del); ADD_TRANSLATION(OBS_KEY_HOME, home); ADD_TRANSLATION(OBS_KEY_END, end); ADD_TRANSLATION(OBS_KEY_PAGEUP, page_up); ADD_TRANSLATION(OBS_KEY_PAGEDOWN, page_down); ADD_TRANSLATION(OBS_KEY_NUMLOCK, num_lock); ADD_TRANSLATION(OBS_KEY_SCROLLLOCK, scroll_lock); ADD_TRANSLATION(OBS_KEY_CAPSLOCK, caps_lock); ADD_TRANSLATION(OBS_KEY_BACKSPACE, backspace); ADD_TRANSLATION(OBS_KEY_TAB, tab); ADD_TRANSLATION(OBS_KEY_PRINT, print); ADD_TRANSLATION(OBS_KEY_PAUSE, pause); ADD_TRANSLATION(OBS_KEY_SHIFT, shift); ADD_TRANSLATION(OBS_KEY_ALT, alt); ADD_TRANSLATION(OBS_KEY_CONTROL, control); ADD_TRANSLATION(OBS_KEY_META, meta); ADD_TRANSLATION(OBS_KEY_MENU, menu); ADD_TRANSLATION(OBS_KEY_SPACE, space); #ifdef __APPLE__ const char *numpad_str = t.apple_keypad_num; ADD_TRANSLATION(OBS_KEY_NUMSLASH, apple_keypad_divide); ADD_TRANSLATION(OBS_KEY_NUMASTERISK, apple_keypad_multiply); ADD_TRANSLATION(OBS_KEY_NUMMINUS, apple_keypad_minus); ADD_TRANSLATION(OBS_KEY_NUMPLUS, apple_keypad_plus); ADD_TRANSLATION(OBS_KEY_NUMPERIOD, apple_keypad_decimal); ADD_TRANSLATION(OBS_KEY_NUMEQUAL, apple_keypad_equal); #else const char *numpad_str = t.numpad_num; ADD_TRANSLATION(OBS_KEY_NUMSLASH, numpad_divide); ADD_TRANSLATION(OBS_KEY_NUMASTERISK, numpad_multiply); ADD_TRANSLATION(OBS_KEY_NUMMINUS, numpad_minus); ADD_TRANSLATION(OBS_KEY_NUMPLUS, numpad_plus); ADD_TRANSLATION(OBS_KEY_NUMPERIOD, numpad_decimal); #endif if (numpad_str) { dstr_copy(&numpad, numpad_str); dstr_depad(&numpad); if (dstr_find(&numpad, "%1") == NULL) { dstr_cat(&numpad, " %1"); } #define ADD_NUMPAD_NUM(idx) \ dstr_copy_dstr(&button, &numpad); \ dstr_replace(&button, "%1", #idx); \ obs_set_key_translation(OBS_KEY_NUM ## idx, button.array) ADD_NUMPAD_NUM(0); ADD_NUMPAD_NUM(1); ADD_NUMPAD_NUM(2); ADD_NUMPAD_NUM(3); ADD_NUMPAD_NUM(4); ADD_NUMPAD_NUM(5); ADD_NUMPAD_NUM(6); ADD_NUMPAD_NUM(7); ADD_NUMPAD_NUM(8); ADD_NUMPAD_NUM(9); } if (t.mouse_num) { dstr_copy(&mouse, t.mouse_num); dstr_depad(&mouse); if (dstr_find(&mouse, "%1") == NULL) { dstr_cat(&mouse, " %1"); } #define ADD_MOUSE_NUM(idx) \ dstr_copy_dstr(&button, &mouse); \ dstr_replace(&button, "%1", #idx); \ obs_set_key_translation(OBS_KEY_MOUSE ## idx, button.array) ADD_MOUSE_NUM(1); ADD_MOUSE_NUM(2); ADD_MOUSE_NUM(3); ADD_MOUSE_NUM(4); ADD_MOUSE_NUM(5); ADD_MOUSE_NUM(6); ADD_MOUSE_NUM(7); ADD_MOUSE_NUM(8); ADD_MOUSE_NUM(9); ADD_MOUSE_NUM(10); ADD_MOUSE_NUM(11); ADD_MOUSE_NUM(12); ADD_MOUSE_NUM(13); ADD_MOUSE_NUM(14); ADD_MOUSE_NUM(15); ADD_MOUSE_NUM(16); ADD_MOUSE_NUM(17); ADD_MOUSE_NUM(18); ADD_MOUSE_NUM(19); ADD_MOUSE_NUM(20); ADD_MOUSE_NUM(21); ADD_MOUSE_NUM(22); ADD_MOUSE_NUM(23); ADD_MOUSE_NUM(24); ADD_MOUSE_NUM(25); ADD_MOUSE_NUM(26); ADD_MOUSE_NUM(27); ADD_MOUSE_NUM(28); ADD_MOUSE_NUM(29); } dstr_free(&numpad); dstr_free(&mouse); dstr_free(&button); }
/* * 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); }
/* FIXME */ static void *q_thread(void *data) { struct crss *crss = (struct crss *)data; char buf[64]; dstr rid, res = NULL; db_iterator_t *it; const char *key, *value; size_t klen, vlen; snprintf(buf, sizeof buf, "%p,", crss->c); rid = dstr_new(buf); rid = dstr_cat(rid, crss->rid); it = db_iterator_create(db, db_ro); db_iterator_seek(it, crss->start, dstr_length(crss->start)); /* seek failed */ if (!db_iterator_valid(it)) { res = dstr_new(crss->rid); res = dstr_cat(res, ",1\r\n\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); goto end; } key = db_iterator_key(it, &klen); while (memcmp(key, crss->stop, dstr_length(crss->stop)) <= 0) { if (crss->cancel) break; if (!strcmp(crss->match, "") || strstr(key, crss->match)) { value = db_iterator_value(it, &vlen); res = dstr_new(crss->rid); res = dstr_cat(res, ",0,"); res = dstr_cat_len(res, key, klen); res = dstr_cat(res, ","); res = dstr_cat_len(res, value, vlen); res = dstr_cat(res, "\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) { xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); goto end; } pthread_spin_unlock(&crss->c->lock); dstr_free(res); } db_iterator_next(it); if (!db_iterator_valid(it) || crss->cancel) break; key = db_iterator_key(it, &klen); } res = dstr_new(crss->rid); res = dstr_cat(res, ",1\r\n\r\n"); pthread_spin_lock(&crss->c->lock); if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno)); pthread_spin_unlock(&crss->c->lock); end: db_iterator_destroy(&it); dstr_free(res); table_lock(rids); table_remove(rids, rid); table_unlock(rids); dstr_free(rid); client_decr(crss->c); dstr_free(crss->rid); dstr_free(crss->match); dstr_free(crss->start); dstr_free(crss->stop); FREE(crss); return NULL; }