static xtk_widget_t* create_skinned_box(xtk_widget_t *c, skin_t *skin, tcconf_section_t *sec, tchash_table_t *parameters) { int x, y, width, height; widget_data_t *wd; int i=0; i += tcconf_getvalue(sec, "position", "%d %d", &x, &y); i += tcconf_getvalue(sec, "size", "%d %d", &width, &height); if(i != 4){ return NULL; } xtk_widget_t *w = xtk_widget_container_create(c, x, y, width, height); wd = tcallocdz(sizeof(*wd), NULL, widgetdata_free); wd->skin = tcref(skin); xtk_widget_container_set_data(w, wd); w->on_destroy = destroy_skinned_box; create_ui(w, skin, sec, parameters); return w; }
static v_state * vstate(tcconf_section_t *sec, char *name, void **state) { v_state *vs = *state; if(!vs){ char *tmp = strdup(name); char *v = strrchr(tmp, '/'); tcconf_section_t *ms; if(v){ *v++ = 0; if(!(sec = tcconf_getsection(sec, tmp))){ free(tmp); return NULL; } } else { v = tmp; tcref(sec); } vs = *state = calloc(1, sizeof(v_state)); vs->n = strdup(v); vs->ts = sec; ms = next_merge(sec, vs); if(ms) sec = ms; vs->sec = sec; free(tmp); } return vs; }
extern tcconf_section_t * tcconf_getsection(tcconf_section_t *ts, char *name) { tcref(ts); if(!name || getsection(&ts, ts->sec, name)) return ts; tcfree(ts); return NULL; }
extern tcconf_section_t * tcconf_nextsection(tcconf_section_t *ts, char *name, void **state) { tcconf_section_t *ns; v_state *vs; conf_section *sec = NULL; if(!(vs = vstate(ts, name, state))) return NULL; while(vs->ml){ tcconf_section_t *s = tcconf_nextsection(vs->sec, vs->n, &vs->vsr); if(!vs->vsr){ tcconf_section_t *ms = next_merge(vs->ts, vs); tcfree(vs->sec); if(ms){ vs->sec = ms; } else { vs->sec = vs->ts; } } if(s){ sec = s->sec; tcfree(s); break; } } if(!sec){ tcc_entry *te = tclist_prev_matched(vs->sec->sec->entries, &vs->li, vs->n, cmp_str_sec); if(!te){ *state = NULL; vsfree(vs); return NULL; } sec = te->section; } ns = tcallocd(sizeof(*ns), NULL, tcconf_free); ns->sec = tcref(sec); ns->parent = tcref(ts); return ns; }
extern tcconf_section_t * tcconf_merge(tcconf_section_t *sec, tcconf_section_t *s2) { tclist_item_t *li = NULL; tcc_entry *te; char *m; if(!sec){ sec = tcconf_new(NULL); if(s2->parent) sec->parent = tcref(s2->parent); /* if(s2->sec->parent) */ /* sec->sec->parent = tcref(s2->sec->parent); */ sec->sec->parent = s2->sec->parent; } while((te = tclist_next(s2->sec->entries, &li))) tclist_push(sec->sec->entries, tcref(te)); while((m = tclist_next(s2->sec->merge, &li))) tclist_push(sec->sec->merge, strdup(m)); return sec; }
extern int tcconf_getvalue(tcconf_section_t *sec, char *name, char *fmt, ...) { va_list args; tcc_entry *te; int n; tcref(sec); if(!(te = getvalue(sec->sec, name, &sec))){ tcfree(sec); return -1; } va_start(args, fmt); n = getentry(sec, te, fmt, args, NULL); va_end(args); tcfree(sec); return n < 0? -n: n; }
static xtk_widget_t* create_skinned_seek_bar(xtk_widget_t *win, skin_t *skin, tcconf_section_t *sec, tchash_table_t *parameters) { int x, y; int sp_x, sp_y; int ep_x, ep_y; int xd=0, yd=0, sx=0, sy=0; char *bg, *indicator, *value, *variable, *ind_over = NULL, *ind_down = NULL; int i=0; char *action = NULL; widget_data_t *wd = tcallocdz(sizeof(*wd), NULL, widgetdata_free); double *position = NULL, *def = NULL, p=0, snap; xtk_widget_t *s; int disable = 0; image_t *img; i += tcconf_getvalue(sec, "position", "%d %d", &x, &y); i += tcconf_getvalue(sec, "start_position", "%d %d", &sp_x, &sp_y); i += tcconf_getvalue(sec, "end_position", "%d %d", &ep_x, &ep_y); i += tcconf_getvalue(sec, "background", "%s", &bg); i += tcconf_getvalue(sec, "indicator", "%s", &indicator); i += tcconf_getvalue(sec, "value", "%s %s", &variable, &value); if(i != 10){ return NULL; } tcconf_getvalue(sec, "action", "%s", &action); tcconf_getvalue(sec, "mouse_over", "%s", &ind_over); tcconf_getvalue(sec, "pressed", "%s", &ind_down); tcconf_getvalue(sec, "scroll_direction", "%d %d %d %d", &xd, &yd, &sx, &sy); parse_variable("double", value, (void *)&position, (void *)&def); if(!position) { if(def) { p = *def; tcfree(def); } position = &p; } else if(*position < 0 || *position > 1) { disable = 1; } wd->action = action; wd->value = value; wd->skin = tcref(skin); img = load_image(skin->path, bg); s = xtk_widget_slider_create(win, x, y, img->params.width[0], img->params.height[0]); xtk_widget_slider_set_image(s, img); tcfree(img); xtk_widget_slider_set_data(s, wd); xtk_widget_slider_set_action(s, lookup_action); xtk_widget_slider_set_position(s, *position); xtk_widget_slider_set_bounds(s, sp_x, sp_y, ep_x, ep_y); xtk_widget_slider_set_scroll_direction(s, xd, yd, sx, sy); if(tcconf_getvalue(sec, "snap", "%lf", &snap) == 1) { xtk_widget_slider_set_snap(s, snap); } img = load_image(skin->path, indicator); xtk_widget_slider_set_indicator_image(s, img); tcfree(img); img = load_image(skin->path, ind_over); xtk_widget_slider_set_indicator_image_hover(s, img); if(img) tcfree(img); img = load_image(skin->path, ind_down); xtk_widget_slider_set_indicator_image_pressed(s, img); if(img) tcfree(img); if(s) { if(strcmp(variable, "position") == 0) { register_varwidget((xtk_widget_t *)s, seek_bar_update, "double", wd->value); } free(variable); s->on_destroy = destroy_skinned_seek_bar; if(disable) xtk_widget_disable(s); } free(ind_over); free(ind_down); free(indicator); free(bg); return s; }
static xtk_widget_t* create_skinned_label(xtk_widget_t *win, skin_t *skin, tcconf_section_t *sec, tchash_table_t *parameters) { int x, y; int width, height; int xoff = 0, yoff = 0; char *font; char *color, *align_s, *stype_s; int alpha = 0xff; int stype, align; int i = 0; char *action = NULL, *bg = NULL, *text, *default_text; widget_data_t *wd = tcallocdz(sizeof(*wd), NULL, widgetdata_free); xtk_widget_t *l, *w; tcconf_section_t *bfnt = NULL; image_t *bg_img; i += tcconf_getvalue(sec, "position", "%d %d", &x, &y); i += tcconf_getvalue(sec, "size", "%d %d", &width, &height); i += tcconf_getvalue(sec, "text", "%s", &text); if((bfnt = tcconf_getsection(sec, "bitmap"))){ tcconf_setvalue(bfnt, "path", "%s", skin->path); i++; } else if(tcconf_getvalue(sec, "font", "%s", &font) == 1){ i++; } i += tcconf_getvalue(sec, "color", "%s %d", &color, &alpha) > 0; if(tcconf_getvalue(sec, "scroll_style", "%s", &stype_s) < 1) stype_s = strdup("none"); if(tcconf_getvalue(sec, "align", "%s", &align_s) < 1) align_s = strdup("left"); if(strcasecmp(align_s, "left") == 0) { align = XTKLABELLEFT; } else if(strcasecmp(align_s, "right") == 0) { align = XTKLABELRIGHT; } else { align = XTKLABELCENTER; } free(align_s); if(strcasecmp(stype_s, "scroll") == 0) { stype = XTKLABELSCROLL; } else if(strcasecmp(stype_s, "pingpong") == 0) { stype = XTKLABELPINGPONG; } else { stype = 0; } free(stype_s); if(i != 7) return NULL; tcconf_getvalue(sec, "text_offset", "%d %d", &xoff, &yoff); tcconf_getvalue(sec, "action", "%s", &action); tcconf_getvalue(sec, "background", "%s", &bg); default_text = malloc(1024); parse_text(text, default_text, 1024); wd->action = action; wd->value = text; wd->skin = tcref(skin); l = xtk_widget_label_create(win, x, y, width, height); if(bfnt){ xtk_widget_label_set_bitmapfont(l, bfnt); tcfree(bfnt); } else { xtk_widget_label_set_font(l, font); free(font); } xtk_widget_label_set_offset(l, xoff, yoff); xtk_widget_label_set_color(l, color, alpha); xtk_widget_label_set_text(l, default_text); xtk_widget_label_set_data(l, wd); xtk_widget_label_set_action(l, lookup_action); xtk_widget_label_set_align(l, align); xtk_widget_label_set_scroll(l, stype); bg_img = load_image(skin->path, bg); w = xtk_widget_image_create(win, x, y, width, height); xtk_widget_image_set_image(w, bg_img); tcfree(bg_img); xtk_widget_show(w); register_textwidget(l, text); l->on_destroy = destroy_skinned_label; free(default_text); if(color) free(color); free(bg); return l; }
static xtk_widget_t* create_skinned_button(xtk_widget_t *c, skin_t *skin, tcconf_section_t *sec, tchash_table_t *parameters) { char *file = NULL, *of = NULL, *df = NULL, *bg = NULL; int x, y; int i=0; widget_data_t *wd = tcallocdz(sizeof(*wd), NULL, widgetdata_free); xtk_widget_t *bt; image_t *img; int shaped = 0; i += tcconf_getvalue(sec, "action", "%s", &wd->action); i += tcconf_getvalue(sec, "image", "%s", &file); i += tcconf_getvalue(sec, "position", "%d %d", &x, &y); if(i != 4){ return NULL; } tcconf_getvalue(sec, "shaped", "%d", &shaped); tcconf_getvalue(sec, "mouse_over", "%s", &of); tcconf_getvalue(sec, "pressed", "%s", &df); wd->skin = tcref(skin); /* tcconf_getvalue(sec, "background", "%s", &bg); */ if(!(img = load_image(skin->path, file))) return NULL; bt = xtk_widget_button_create(c, x, y, img->params.width[0], img->params.height[0]); xtk_widget_button_set_image(bt, img); if(shaped) xtk_widget_button_set_shape(bt, img); tcfree(img); if((img = load_image(skin->path, of))){ xtk_widget_button_set_hover_image(bt, img); if(shaped) xtk_widget_button_set_hover_shape(bt, img); tcfree(img); } if((img = load_image(skin->path, df))){ xtk_widget_button_set_pressed_image(bt, img); if(shaped) xtk_widget_button_set_pressed_shape(bt, img); tcfree(img); } xtk_widget_button_set_data(bt, wd); xtk_widget_button_set_action(bt, lookup_action); bt->on_destroy = destroy_skinned_button; free(file); free(of); free(df); free(bg); return bt; }
extern int lookup_action(xtk_widget_t *w, void *p) { action_cb_t acb = NULL; widget_data_t *wd; char *ac_c, *c; tcref(w); wd = xtk_widget_get_data(w); tcref(wd); if(wd && wd->action) { tc2_print("TCVPX", TC2_PRINT_DEBUG+5, "Looking up action \"%s\"\n", wd->action); ac_c = c = strdup(wd->action); while(c != NULL) { char *next, *param; param = strchr(c, '('); next = strchr(c, ','); if(param < next || (!next && param)) { char *tmp; param[0] = 0; wd->action_data = param+1; tmp = strchr(param+1, ')'); if(tmp) { tmp[0] = 0; } else { tc2_print("TCVPX", TC2_PRINT_ERROR, "Syntax error in skin config file\n"); } } if(next) { next[0] = 0; next++; } tchash_find(action_hash, c, -1, &acb); if(acb) { tc2_print("TCVPX", TC2_PRINT_DEBUG+2, "Action: \"%s(%s)\"\n", c, wd->action_data); acb(w, p); } else { tc2_print("TCVPX", TC2_PRINT_WARNING, "Action: \"%s\" not implemented\n", c); } wd->action_data = NULL; c = next; } free(ac_c); } tcfree(wd); tcfree(w); return 0; }
extern skin_t* tcvp_open_ui(xtk_widget_t *w, void *p) { char *buf; widget_data_t *wd; widget_data_t *owd = xtk_widget_get_data(w); char *uifile = owd->action_data; skin_t *s = owd->skin; buf = malloc(strlen(uifile) + strlen(s->path) + 2); sprintf(buf, "%s/%s", s->path, uifile); skin_t *skin = load_skin(buf); if(!skin) { return NULL; } skin->window = xtk_window_create(NULL, 0, 0, skin->width, skin->height); xtk_window_set_dnd_callback(skin->window, tcvp_add_file); xtk_window_set_class(skin->window, "TCVP"); if(create_ui(skin->window, skin, skin->config, NULL) != 0){ tc2_print("TCVPX", TC2_PRINT_ERROR, "Unable to load skin: \"%s\"\n", buf); return NULL; } free(buf); wd = tcallocdz(sizeof(*wd), NULL, widgetdata_free); wd->action = skin->dblclick; wd->skin = tcref(skin); xtk_widget_container_set_data(skin->window, wd); xtk_window_set_doubleclick_callback(skin->window, lookup_action); xtk_window_set_sticky_callback(skin->window, sticky_cb); xtk_window_set_on_top_callback(skin->window, on_top_cb); char *default_text = malloc(1024); tcconf_getvalue(skin->config, "title", "%s", &wd->value); if(wd->value == NULL) { wd->value = strdup(tcvp_ui_tcvpx_conf_window_title); } register_textwidget(skin->window, wd->value); parse_text(wd->value, default_text, 1024); xtk_window_set_title(skin->window, default_text); free(default_text); xtk_window_show(skin->window); if((s->state & ST_STICKY) != 0) { xtk_window_set_sticky(skin->window, 1); skin->state |= ST_STICKY; } if((s->state & ST_ON_TOP) != 0) { xtk_window_set_always_on_top(skin->window, 1); skin->state |= ST_ON_TOP; } tcconf_getvalue(skin->config, "id", "%s", &skin->id); skin->skin_hash = s->skin_hash; if(skin->id != NULL) { tchash_search(skin->skin_hash, skin->id, -1, skin, NULL); } ui_count++; return skin; }
static conf_section * getsection(tcconf_section_t **ts, conf_section *sec, char *name) { tcconf_section_t *path = NULL; char *tmp = strdup(name); char *tn = tmp; char *s; if(ts) path = *ts; /* fprintf(stderr, "enter getsection\n"); */ /* fprintf(stderr, "finding '%s' in ", name); */ /* if(path) */ /* tcconf_dumppath(path); */ /* else */ /* fprintf(stderr, "%s\n", sec->name); */ while((s = strsep(&tmp, "/")) != NULL){ if(*s == 0) continue; if(!strcmp(s, "..")){ if(path && path->parent){ tcconf_section_t *p = path; path = tcref(path->parent); sec = path->sec; tcfree(p); } else if(sec->parent){ sec = sec->parent; } } else { tcconf_section_t *np; tcc_entry *te; if(tclist_find(sec->entries, s, &te, cmp_str_sec)){ tclist_t *mlist = sec->merge; tclist_item_t *li = NULL; char *m; sec = NULL; while((m = tclist_prev(mlist, &li))){ conf_section *ps, *ms; if(path) ps = path->parent? path->parent->sec: path->sec; else ps = sec->parent? sec->parent: sec; ms = getsection(NULL, ps, m); if(ms && (sec = getsection(NULL, ms, s))) break; } if(li) tclist_unlock(sec->merge, li); } else { sec = te->section; } if(!sec) break; if(path){ np = tcallocdz(sizeof(*np), NULL, tcconf_free); np->sec = tcref(sec); np->parent = path; path = np; } } /* tcconf_dumppath(path); */ } if(ts) *ts = path; /* fprintf(stderr, "leave getsection\n"); */ free(tn); return sec; }
static int getentry(tcconf_section_t *ts, tcc_entry *te, char *fmt, va_list args, char **tail) { char *f = fmt, *p; int n = 0; tclist_item_t *li = NULL; tcc_value *tv; va_list ac; while((p = strchr(f, '%')) != NULL){ void *dest; int type = 0; if((tv = tclist_next(te->value.values, &li)) == NULL) break; f = p; if(tv->type == TCC_REF && strcmp(tv->value.string, "NULL")){ tcconf_section_t *rs = tcref(ts); tcc_entry *re; int r; if(!(re = getvalue(rs->sec, tv->value.string, &rs))){ n = -n; break; } #ifdef __va_copy __va_copy(ac, args); #else ac = args; #endif r = getentry(ts, re, f, ac, &f); tcfree(rs); if(r < 0){ n += -r; break; } n += r; while(r--) va_arg(args, void *); continue; } dest = va_arg(args, void *); f++; while(!(type & TCC_TYPEMASK) && *f){ switch(*f){ case 's': type |= TCC_STRING; break; case 'd': case 'i': type |= TCC_INTEGER; break; case 'f': type |= TCC_FLOAT; break; case 'l': type |= TCC_LONG; break; case 'u': type |= TCC_UNSIGNED; break; case 'z': type |= TCC_IGNORE; break; } f++; } if(cp_val(ts, tv, type, dest) < 0){ fprintf(stderr, "Type mismatch in '%s'.\n", te->value.key); n = -n; break; } else { n++; } } if(tail) *tail = f; if(li) tclist_unlock(te->value.values, li); return n; }
static char * vtostr(char *name, void *_ts) { tcconf_section_t *ts = _ts; tclist_item_t *li = NULL; tcc_value *tv; tcc_entry *te; int l = 0; char *s = NULL; char *p = s; int sp = 0; #define ext(n) do { \ int o = p - s; \ s = realloc(s, l += n); \ p = s + o; \ } while(0) tcref(ts); if(!(te = getvalue(ts->sec, name, &ts))) return NULL; while((tv = tclist_next(te->value.values, &li))){ union { uint64_t i; double d; char *s; } v; int sl; cp_val(ts, tv, tv->type | TCC_LONG, &v); if(sp) *p++ = ' '; switch(tv->type & TCC_TYPEMASK){ case TCC_INTEGER: ext(22); p += snprintf(p, 22, "%lli", v.i); break; case TCC_FLOAT: ext(40); p += snprintf(p, 40, "%lf", v.d); break; case TCC_REF: v.s = vtostr(tv->value.string, ts); case TCC_STRING: sl = strlen(v.s); ext(sl + 1); strcpy(p, v.s); free(v.s); p += sl; break; } sp = 1; } *p = 0; #undef ext tcfree(ts); return s; }
static xtk_widget_t* create_skinned_list(xtk_widget_t *win, skin_t *skin, tcconf_section_t *sec, tchash_table_t *parameters) { int x, y; int width, height; int i=0; char *action = NULL; widget_data_t *wd = tcallocdz(sizeof(*wd), NULL, widgetdata_free); xtk_widget_t *l; int disable = 0; int alpha = 0xff, calpha = 0xff; char *font, *color, *ccolor = NULL; tcconf_section_t *bfnt = NULL; tcconf_section_t *fig = NULL; int rows, spacing; int xs, ys; i += tcconf_getvalue(sec, "position", "%d %d", &x, &y); i += tcconf_getvalue(sec, "size", "%d %d", &width, &height); if((bfnt = tcconf_getsection(sec, "bitmap"))){ tcconf_setvalue(bfnt, "path", "%s", skin->path); i++; } else if(tcconf_getvalue(sec, "font", "%s", &font) == 1){ i++; } i += tcconf_getvalue(sec, "color", "%s %d", &color, &alpha) > 0; i += tcconf_getvalue(sec, "spacing", "%d", &spacing); i += tcconf_getvalue(sec, "rows", "%d", &rows); if(i != 8){ return NULL; } tcconf_getvalue(sec, "current-color", "%s %d", &ccolor, &calpha); fig = tcconf_getsection(sec, "background_figure"); tcconf_getvalue(sec, "action", "%s", &action); wd->action = action; wd->skin = tcref(skin); wd->values = calloc(1, sizeof(char *)); l = xtk_widget_list_create(win, x, y, width, height); if(tcconf_getvalue(sec, "scroll", "%d %d", &xs, &ys) == 2) { xtk_widget_list_set_scroll(l, xs, ys); } if(fig != NULL) { tcconf_setvalue(fig, "position", "%d %d", 0, 0); tcconf_setvalue(fig, "size", "%d %d", width, height); image_t *img = draw_figure(fig); xtk_widget_list_set_image(l, img); tcfree(img); tcfree(fig); } xtk_widget_list_set_data(l, wd); xtk_widget_list_set_action(l, lookup_action); if(l) { void *c = NULL; char *value, *variable; if(bfnt){ xtk_widget_list_set_bitmapfont(l, bfnt); tcfree(bfnt); } else { xtk_widget_list_set_font(l, font); free(font); } xtk_widget_list_set_color(l, color, alpha); free(color); if(ccolor) { xtk_widget_list_set_current_color(l, ccolor, calpha); free(ccolor); } xtk_widget_list_set_spacing(l, spacing); xtk_widget_list_set_rows(l, rows); while(i = tcconf_nextvalue(sec, "value", &c, "%s %s", &variable, &value), c) { if(i == 2) { if(strcmp(variable, "current_position") == 0) { int *val = NULL, *def = NULL; int p; save_varcb(l, list_set_current, "integer", value); register_varwidget(l, list_set_current, "integer", value); parse_variable("integer", value, (void *)&val, (void *)&def); if(!val) { if(def) { p = *def; tcfree(def); } val = &p; } list_set_current(l, val); } else if(strcmp(variable, "number_of_entries") == 0) { int *val = NULL, *def = NULL; int p; save_varcb(l, list_set_number_of_entries, "integer", value); register_varwidget(l, list_set_number_of_entries, "integer", value); parse_variable("integer", value, (void *)&val, (void *)&def); if(!val) { if(def) { p = *def; tcfree(def); } val = &p; } list_set_number_of_entries(l, val); } else if(strcmp(variable, "entries") == 0) { void *val = NULL; save_varcb(l, list_set_entries, "string_array", value); register_varwidget(l, list_set_entries, "string_array", value); parse_variable("string_array", value, &val, NULL); if(val) { list_set_entries(l, val); tcfree(val); } } free(value); free(variable); } } l->on_destroy = destroy_skinned_list; if(disable) xtk_widget_disable(l); } return l; }
static xtk_widget_t* create_skinned_state(xtk_widget_t *win, skin_t *skin, tcconf_section_t *sec, tchash_table_t *parameters) { int x, y; int ns = 0; image_t **imgs = NULL; char **states = NULL; void *c = NULL; int i; char *img, *st, def_state[512], *bg = NULL; widget_data_t *wd = tcallocdz(sizeof(*wd), NULL, widgetdata_free); xtk_widget_t *s = NULL; i = tcconf_getvalue(sec, "position", "%d %d", &x, &y); i += tcconf_getvalue(sec, "value", "%s", &wd->value); if (i != 3) { return NULL; } while(i = tcconf_nextvalue(sec, "image", &c, "%s %s", &st, &img), c) { if(i == 2) { imgs = realloc(imgs, sizeof(*imgs)*(ns+1)); states = realloc(states, sizeof(*states)*(ns+1)); imgs[ns] = load_image(skin->path, img); states[ns] = st; ns++; free(img); } } tcconf_getvalue(sec, "action", "%s", &wd->action); wd->skin = tcref(skin); parse_text(wd->value, def_state, 512); if(ns > 0) { s = xtk_widget_state_create(win, x, y, imgs[0]->params.width[0], imgs[0]->params.height[0]); for(i=0; i<ns; i++) { xtk_widget_state_add_state(s, states[i], imgs[i]); tcfree(imgs[i]); } xtk_widget_state_set_state(s, def_state); xtk_widget_state_set_data(s, wd); xtk_widget_state_set_action(s, lookup_action); register_textwidget((xtk_widget_t *)s, wd->value); s->on_destroy = destroy_skinned_state; } free(bg); if(imgs) free(imgs); if(states){ for(i = 0; i < ns; i++) free(states[i]); free(states); } return s; }
extern tcvp_pipe_t * new_pipe(tcvp_player_t *sh, muxed_stream_t *ms, stream_t *s) { tcvp_pipe_t *pipe = NULL, *pp = NULL, *pn = NULL; tcconf_section_t *f, *mcf; tcconf_section_t *pr = NULL; void *cs = NULL; int skip = 0; switch(s->stream_type){ case STREAM_TYPE_VIDEO: pr = tcconf_getsection(sh->profile, "video"); break; case STREAM_TYPE_AUDIO: pr = tcconf_getsection(sh->profile, "audio"); break; case STREAM_TYPE_SUBTITLE: pr = tcconf_getsection(sh->profile, "subtitle"); break; } if(!pr) return NULL; while((f = tcconf_nextsection(pr, "filter", &cs))){ char *type, *id = NULL; filter_new_t fn; if(skip){ tcfree(f); continue; } pn = NULL; if(tcconf_getvalue(f, "type", "%s", &type) < 1){ tc2_print("STREAM", TC2_PRINT_WARNING, "bad filter specification\n"); continue; } if(tcconf_getvalue(f, "id", "%s", &id) > 0) tchash_find(sh->filters, id, -1, &pn); if(!pn){ tc2_print("STREAM", TC2_PRINT_DEBUG, "opening new filter: %s\n", type); if(!(fn = tc2_get_symbol(type, "new"))) break; mcf = tcconf_merge(NULL, f); tcconf_merge(mcf, sh->conf); if(sh->outfile) tcconf_setvalue(mcf, "mux/url", "%s", sh->outfile); if(!(pn = fn(pp? &pp->format: s, mcf, sh->timer, ms))){ tc2_print("STREAM", TC2_PRINT_WARNING, "error opening filter '%s'\n", type); break; } if(id){ char *cid = tcalloc(strlen(id) + 1); strcpy(cid, id); tcattr_set(cid, "stream-shared", sh, NULL, NULL); tcattr_set(pn, "id", cid, NULL, pid_free); tchash_replace(sh->filters, id, -1, pn, NULL); } tcfree(mcf); } else { tcref(pn); } if(id) free(id); if(!pipe) pipe = pn; if(pp) pp->next = pn; pp = pn; free(type); tcfree(f); if(pp->next){ while((pp = pp->next)) tcref(pp); skip = 1; } } if(!pn){ close_pipe(pipe); pipe = NULL; } tcfree(pr); return pipe; }