static void audio_mastervol_init(void) { htsmsg_t *m = htsmsg_store_load("audiomixer"); int32_t i32; prop_t *pa, *mv, *mm; pa = prop_create(prop_get_global(), "audio"); mv = prop_create(pa, "mastervolume"); mm = prop_create(pa, "mastermute"); prop_set_float_clipping_range(mv, -75, 12); if(m != NULL && !htsmsg_get_s32(m, "master-volume", &i32)) prop_set_float(mv, (float)i32 / 1000); prop_set_int(mm, 0); htsmsg_release(m); prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_CALLBACK_FLOAT, save_matervol, NULL, PROP_TAG_ROOT, mv, NULL); prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_SET_INT, &audio_master_mute, PROP_TAG_ROOT, mm, NULL); }
static void nav_page_setup_prop(navigator_t *nav, nav_page_t *np, const char *view) { np->np_prop_root = prop_create_root("page"); if(view != NULL) { np->np_view = strdup(view); prop_set_string(prop_create(np->np_prop_root, "requestedView"), view); } // XXX Change this into event-style subscription np->np_close_sub = prop_subscribe(0, PROP_TAG_ROOT, prop_create(np->np_prop_root, "close"), PROP_TAG_CALLBACK_INT, nav_page_close_set, np, PROP_TAG_COURIER, nav->nav_pc, NULL); prop_set_string(prop_create(np->np_prop_root, "url"), np->np_url); np->np_direct_close_sub = prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_ROOT, prop_create(np->np_prop_root, "directClose"), PROP_TAG_CALLBACK_INT, nav_page_direct_close_set, np, PROP_TAG_COURIER, nav->nav_pc, NULL); }
static navigator_t * nav_create(prop_t *prop) { navigator_t *nav = calloc(1, sizeof(navigator_t)); nav->nav_prop_root = prop; TAILQ_INIT(&nav->nav_pages); TAILQ_INIT(&nav->nav_history); nav->nav_prop_pages = prop_create(nav->nav_prop_root, "pages"); nav->nav_prop_curpage = prop_create(nav->nav_prop_root, "currentpage"); nav->nav_prop_can_go_back = prop_create(nav->nav_prop_root, "canGoBack"); nav->nav_prop_can_go_fwd = prop_create(nav->nav_prop_root, "canGoForward"); nav->nav_prop_can_go_home = prop_create(nav->nav_prop_root, "canGoHome"); prop_set_int(nav->nav_prop_can_go_home, 1); nav->nav_pc = prop_courier_create_thread(NULL, "navigator"); nav->nav_eventsink = prop_subscribe(0, PROP_TAG_NAME("nav", "eventsink"), PROP_TAG_CALLBACK, nav_eventsink, nav, PROP_TAG_COURIER, nav->nav_pc, PROP_TAG_ROOT, nav->nav_prop_root, NULL); nav->nav_dtor_tracker = prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, nav_dtor_tracker, nav, PROP_TAG_COURIER, nav->nav_pc, PROP_TAG_ROOT, nav->nav_prop_root, NULL); return nav; }
void prop_reorder_create(prop_t *dst, prop_t *src, int flags, const char *id) { prop_reorder_t *pr = calloc(1, sizeof(prop_reorder_t)); pr->pr_order = htsmsg_store_load(id); if(pr->pr_order == NULL) pr->pr_order = htsmsg_create_list(); pr->pr_store = strdup(id); pr->pr_dst = flags & PROP_REORDER_TAKE_DST_OWNERSHIP ? dst : prop_xref_addref(dst); hts_mutex_lock(&prop_mutex); pr->pr_srcsub = prop_subscribe(PROP_SUB_INTERNAL | PROP_SUB_DONTLOCK | PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, src_cb, pr, PROP_TAG_ROOT, src, NULL); pr->pr_dstsub = prop_subscribe(PROP_SUB_INTERNAL | PROP_SUB_DONTLOCK | PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, dst_cb, pr, PROP_TAG_ROOT, dst, NULL); hts_mutex_unlock(&prop_mutex); }
static void bookmark_add(const char *title, const char *url, const char *type) { bookmark_t *bm = calloc(1, sizeof(bookmark_t)); prop_t *p = prop_create_root(NULL); prop_t *src = prop_create(p, "model"); prop_set_string(prop_create(src, "type"), "bookmark"); bm->bm_title_sub = bookmark_add_prop(src, "title", title, bm, set_title); bm->bm_url_sub = bookmark_add_prop(src, "url", url, bm, set_url); bm->bm_type_sub = bookmark_add_prop(src, "svctype", type, bm, set_type); bm->bm_service = service_create(title, url, type, NULL, 1, 1); prop_link(service_get_status_prop(bm->bm_service), prop_create(src, "status")); prop_link(service_get_statustxt_prop(bm->bm_service), prop_create(src, "statustxt")); prop_subscribe(PROP_SUB_TRACK_DESTROY | PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_CALLBACK, bookmark_destroyed, bm, PROP_TAG_ROOT, p, PROP_TAG_MUTEX, &bookmark_mutex, NULL); if(prop_set_parent(p, prop_create(bookmarks, "nodes"))) abort(); }
prop_t * add_news(const char *message, const char *location, const char *caption) { prop_t *p, *ret = NULL; prop_t *root = prop_create(prop_get_global(), "news"); hts_mutex_lock(&news_mutex); if(dismissed_news_out != NULL) { if(htsmsg_get_u32_or_default(dismissed_news_in, message, 0)) { dismis_news(message); } else { p = prop_create_root(NULL); prop_set_string(prop_create(p, "message"), message); prop_set_string(prop_create(p, "location"), location); prop_set_string(prop_create(p, "caption"), caption); prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, news_sink, prop_ref_inc(p), PROP_TAG_ROOT, prop_create(p, "eventSink"), PROP_TAG_MUTEX, &news_mutex, NULL); ret = prop_ref_inc(p); if(prop_set_parent(p, root)) prop_destroy(p); } } hts_mutex_unlock(&news_mutex); return ret; }
static void add_header(prop_courier_t *pc, GtkWidget *parent, prop_t *root) { GtkWidget *hbox, *w; prop_sub_t *s; hbox = gtk_hbox_new(FALSE, 1); gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, TRUE, 0); /* Artist name */ w = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(w), 0, 0); gtk_label_set_ellipsize(GTK_LABEL(w), PANGO_ELLIPSIZE_END); gtk_box_pack_start(GTK_BOX(hbox), w, TRUE, TRUE, 0); s = prop_subscribe(0, PROP_TAG_NAME("self", "model", "artist_name"), PROP_TAG_CALLBACK_STRING, gu_subscription_set_label_xl, w, PROP_TAG_COURIER, pc, PROP_TAG_NAMED_ROOT, root, "self", NULL); gu_unsubscribe_on_destroy(GTK_OBJECT(w), s); }
static void add_albums(gu_tab_t *gt, GtkWidget *parent, prop_t *root) { GtkWidget *sbox; albumbrowse_t *ab = calloc(1, sizeof(albumbrowse_t)); ab->gt = gt; /* Scrolled window */ sbox = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sbox), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(parent), sbox, TRUE, TRUE, 0); /* vbox for all albums */ ab->vbox = gtk_vbox_new(FALSE, 1); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sbox), ab->vbox); ab->sub = prop_subscribe(0, PROP_TAG_NAME("self", "model", "nodes"), PROP_TAG_CALLBACK, collection_albums, ab, PROP_TAG_COURIER, gt->gt_gw->gw_gu->gu_pc, PROP_TAG_NAMED_ROOT, root, "self", NULL); g_signal_connect(sbox, "destroy", G_CALLBACK(ab_destroy), ab); }
static JSBool js_item_onEvent(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { js_item_t *ji = JS_GetPrivate(cx, obj); if(!JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[1]))) { JS_ReportError(cx, "Argument is not a function"); return JS_FALSE; } if(ji->ji_eventsub == NULL) { ji->ji_eventsub = prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, js_item_eventsub, ji, PROP_TAG_ROOT, ji->ji_root, PROP_TAG_COURIER, ji->ji_model->jm_pc, NULL); ji->ji_model->jm_subs++; ji->ji_this = OBJECT_TO_JSVAL(obj); JS_AddNamedRoot(cx, &ji->ji_this, "item_this"); } js_event_handler_create(cx, &ji->ji_event_handlers, JSVAL_IS_STRING(argv[0]) ? JS_GetStringBytes(JS_ValueToString(cx, argv[0])) : NULL, argv[1]); *rval = JSVAL_VOID; return JS_TRUE; }
void backend_prop_make(prop_t *model, char *url, size_t urllen) { proppage_t *pp; hts_mutex_lock(&pp_mutex); pp = malloc(sizeof(proppage_t)); pp_tally++; snprintf(url, urllen, "prop:%d", pp_tally); pp->pp_url = strdup(url); pp->pp_model = prop_ref_inc(model); pp->pp_model_sub = prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, pp_cb, pp, PROP_TAG_MUTEX, &pp_mutex, PROP_TAG_ROOT, model, NULL); LIST_INSERT_HEAD(&proppages, pp, pp_link); hts_mutex_unlock(&pp_mutex); }
void bookmarks_init(void) { htsmsg_field_t *f; htsmsg_t *m, *n, *o; hts_mutex_init(&bookmark_mutex); bookmarks = prop_create(settings_add_dir(NULL, "Bookmarks", "bookmark", NULL), "model"); prop_set_int(prop_create(bookmarks, "mayadd"), 1); prop_subscribe(0, PROP_TAG_CALLBACK, bookmarks_callback, NULL, PROP_TAG_ROOT, prop_create(bookmarks, "nodes"), PROP_TAG_MUTEX, &bookmark_mutex, NULL); if((m = htsmsg_store_load("bookmarks")) != NULL) { n = htsmsg_get_map(m, "nodes"); HTSMSG_FOREACH(f, n) { if((o = htsmsg_get_map_by_field(f)) == NULL) continue; bookmark_load(o); } htsmsg_destroy(m); }
static prop_t * add_news_locked(const char *id, const char *message, const char *location, const char *caption, const char *action) { prop_t *p, *ret = NULL; prop_t *root = prop_create(prop_get_global(), "news"); if(dismissed_news_out != NULL) { if(htsmsg_get_u32_or_default(dismissed_news_in, id, 0)) { dismis_news(id); } else { p = prop_create_root(id); prop_set(p, "message", PROP_SET_STRING, message); prop_set(p, "id", PROP_SET_STRING, id); prop_set(p, "location", PROP_SET_STRING, location); prop_set(p, "caption", PROP_SET_STRING, caption); prop_set(p, "action", PROP_SET_STRING, action); prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, news_sink, prop_ref_inc(p), PROP_TAG_ROOT, prop_create(p, "eventSink"), PROP_TAG_MUTEX, &news_mutex, NULL); ret = prop_ref_inc(p); if(prop_set_parent(p, root)) prop_destroy(p); } } return ret; }
static int be_prop_open(prop_t *page, const char *url) { proppage_t *pp; openpage_t *op; hts_mutex_lock(&pp_mutex); LIST_FOREACH(pp, &proppages, pp_link) if(!strcmp(rstr_get(pp->pp_url), url)) break; if(pp == NULL) { hts_mutex_unlock(&pp_mutex); return 1; } op = calloc(1, sizeof(openpage_t)); LIST_INSERT_HEAD(&pp->pp_pages, op, op_link); op->op_pp = pp; op->op_root = prop_ref_inc(page); op->op_page_sub = prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, op_cb, op, PROP_TAG_MUTEX, &pp_mutex, PROP_TAG_ROOT, page, NULL); prop_link(pp->pp_model, prop_create(page, "model")); hts_mutex_unlock(&pp_mutex); return 0; }
event_t * popup_display(prop_t *p) { prop_courier_t *pc = prop_courier_create_waitable(); event_t *e = NULL; prop_t *r = prop_create(p, "eventSink"); prop_sub_t *s = prop_subscribe(0, PROP_TAG_CALLBACK, eventsink, &e, PROP_TAG_ROOT, r, PROP_TAG_COURIER, pc, NULL); /* Will show the popup */ if(prop_set_parent(p, prop_create(prop_get_global(), "popups"))) { /* popuproot is a zombie, this is an error */ abort(); } while(e == NULL) prop_courier_wait_and_dispatch(pc); prop_unsubscribe(s); return e; }
setting_t * settings_create_bool(prop_t *parent, const char *id, prop_t *title, int initial, htsmsg_t *store, prop_callback_int_t *cb, void *opaque, int flags, prop_courier_t *pc, settings_saver_t *saver, void *saver_opaque) { setting_t *s = setting_create_leaf(parent, title, "bool", "value", flags); prop_sub_t *sub; s->s_id = strdup(id); s->s_callback = cb; s->s_opaque = opaque; if(store != NULL) initial = htsmsg_get_u32_or_default(store, id, initial); prop_set_int(s->s_val, !!initial); if(flags & SETTINGS_INITIAL_UPDATE) settings_int_callback(s, !!initial); sub = prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_CALLBACK_INT, settings_int_callback, s, PROP_TAG_ROOT, s->s_val, PROP_TAG_COURIER, pc, NULL); s->s_sub = sub; s->s_store = store; s->s_saver = saver; s->s_saver_opaque = saver_opaque; return s; }
static void bind_to_property(glw_t *w, prop_t *p, const char **pname, prop_t *view, prop_t *args, prop_t *clone, prop_t *core) { glw_text_bitmap_t *gtb = (void *)w; gtb_unbind(gtb); gtb->gtb_sub = prop_subscribe(PROP_SUB_DIRECT_UPDATE | PROP_SUB_SEND_VALUE_PROP, PROP_TAG_NAME_VECTOR, pname, PROP_TAG_CALLBACK, prop_callback, gtb, PROP_TAG_COURIER, w->glw_root->gr_courier, PROP_TAG_NAMED_ROOT, p, "self", PROP_TAG_NAMED_ROOT, view, "view", PROP_TAG_NAMED_ROOT, args, "args", PROP_TAG_NAMED_ROOT, clone, "clone", PROP_TAG_NAMED_ROOT, core, "core", PROP_TAG_ROOT, w->glw_root->gr_prop_ui, PROP_TAG_NAMED_ROOT, w->glw_root->gr_prop_nav, "nav", NULL); if(w->glw_flags2 & GLW2_AUTOHIDE) glw_unhide(w); }
void audio_mastervol_init(void) { htsmsg_t *m = htsmsg_store_load("audiomixer"); int32_t i32; prop_t *prop_audio; prop_audio = prop_create(prop_get_global(), "audio"); prop_mastervol = prop_create(prop_audio, "mastervolume"); prop_mastermute = prop_create(prop_audio, "mastermute"); prop_set_float_clipping_range(prop_mastervol, -75, 0); prop_set_int(prop_mastermute, 0); if(m != NULL && !htsmsg_get_s32(m, "master-volume", &i32)) prop_set_float(prop_mastervol, (float)i32 / 1000); htsmsg_destroy(m); prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_CALLBACK_FLOAT, save_matervol, NULL, PROP_TAG_ROOT, prop_mastervol, NULL); }
static jni_subscription_t * makesub(JNIEnv *env, prop_callback_t *cb, jint j_propid, jstring j_path, jobject j_cbif) { jni_subscription_t *js = malloc(sizeof(jni_subscription_t)); const char *path = (*env)->GetStringUTFChars(env, j_path, 0); js->js_cbif = (*env)->NewGlobalRef(env, j_cbif); prop_t *p = j_propid ? (prop_t *)j_propid : prop_get_global(); js->js_id = ++jni_sub_tally; if(RB_INSERT_SORTED(&jni_subscriptions, js, js_link, js_cmp)) abort(); js->js_sub = prop_subscribe(PROP_SUB_ALT_PATH, PROP_TAG_NAMESTR, path, PROP_TAG_CALLBACK, cb, js, PROP_TAG_ROOT, p, PROP_TAG_COURIER, jni_courier, NULL); (*env)->ReleaseStringUTFChars(env, j_path, path); return js; }
rstr_t * backend_prop_make(prop_t *model, const char *suggest) { proppage_t *pp; rstr_t *r; hts_mutex_lock(&pp_mutex); pp = calloc(1, sizeof(proppage_t)); if(suggest == NULL) { char url[50]; pp_tally++; snprintf(url, sizeof(url), "prop:%d", pp_tally); r = rstr_alloc(url); } else { r = rstr_alloc(suggest); } pp->pp_url = rstr_dup(r); pp->pp_model = prop_ref_inc(model); pp->pp_model_sub = prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, pp_cb, pp, PROP_TAG_MUTEX, &pp_mutex, PROP_TAG_ROOT, model, NULL); LIST_INSERT_HEAD(&proppages, pp, pp_link); hts_mutex_unlock(&pp_mutex); return r; }
static void opts_clicked(GtkToolButton *toolbutton, gpointer user_data) { int event_time = gtk_get_current_event_time(); gu_tab_t *gt = user_data; gtk_ui_t *gu = gt->gt_gw->gw_gu; dyn_menu_t *dm = calloc(1, sizeof(dyn_menu_t)); dm->dm_menu = gtk_menu_new(); gtk_widget_show_all(dm->dm_menu); gtk_menu_attach_to_widget(GTK_MENU(dm->dm_menu), GTK_WIDGET(toolbutton), NULL); gtk_menu_popup(GTK_MENU(dm->dm_menu), NULL, NULL, NULL, NULL, 0, event_time); gu_cloner_init(&dm->dm_nodes, dm, dyn_menu_item_add, dyn_menu_item_del, sizeof(dyn_menu_item_t), gu, GU_CLONER_TRACK_POSITION); dm->dm_node_sub = prop_subscribe(0, PROP_TAG_NAME("nav", "currentpage", "model", "options"), PROP_TAG_CALLBACK, gu_cloner_subscription, &dm->dm_nodes, PROP_TAG_NAMED_ROOT, gt->gt_nav, "nav", PROP_TAG_COURIER, gu->gu_pc, NULL); g_signal_connect(dm->dm_menu, "destroy", G_CALLBACK(dyn_menu_destroyed), dm); }
gu_tab_t * gu_tab_create(gu_window_t *gw, int select, prop_t *nav) { gu_tab_t *gt = calloc(1, sizeof(gu_tab_t)); prop_sub_t *s; int idx; gt->gt_gw = gw; LIST_INSERT_HEAD(&gw->gw_tabs, gt, gt_link); gw->gw_current_tab = gt; gw->gw_ntabs++; gt->gt_nav = nav ?: nav_spawn(); if(prop_set_parent(gt->gt_nav, prop_get_global())) abort(); gt->gt_vbox = gtk_vbox_new(FALSE, 1); gtk_widget_show(gt->gt_vbox); gt->gt_notebook = gtk_notebook_new(); gtk_widget_show(gt->gt_notebook); gtk_notebook_set_show_border(GTK_NOTEBOOK(gt->gt_notebook), 0); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gt->gt_notebook), 0); gu_toolbar_add(gt, gt->gt_vbox); gtk_container_add(GTK_CONTAINER(gt->gt_vbox), gt->gt_notebook); build_tab_header(gt); s = prop_subscribe(0, PROP_TAG_NAME("nav", "pages"), PROP_TAG_CALLBACK, gu_nav_pages, gt, PROP_TAG_COURIER, glibcourier, PROP_TAG_NAMED_ROOT, gt->gt_nav, "nav", NULL); gu_unsubscribe_on_destroy(GTK_OBJECT(gt->gt_notebook), s); // Add to tab's notebook idx = gtk_notebook_append_page(GTK_NOTEBOOK(gw->gw_notebook), gt->gt_vbox, gt->gt_label); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(gw->gw_notebook), gt->gt_vbox, 1); if(select) gtk_notebook_set_current_page(GTK_NOTEBOOK(gw->gw_notebook), idx); if(gw->gw_ntabs > 1) gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gw->gw_notebook), 1); return gt; }
static void nav_open0(navigator_t *nav, const char *url, const char *view, prop_t *origin) { nav_page_t *np = calloc(1, sizeof(nav_page_t)); np->np_nav = nav; np->np_url = url ? strdup(url) : NULL; np->np_direct_close = 0; TAILQ_INSERT_TAIL(&nav->nav_pages, np, np_global_link); np->np_prop_root = prop_create_root("page"); if(view != NULL) { np->np_view = strdup(view); prop_set_string(prop_create(np->np_prop_root, "requestedView"), view); } // XXX Change this into event-style subscription np->np_close_sub = prop_subscribe(0, PROP_TAG_ROOT, prop_create(np->np_prop_root, "close"), PROP_TAG_CALLBACK_INT, nav_page_close_set, np, PROP_TAG_COURIER, nav->nav_pc, NULL); if(url != NULL) prop_set_string(prop_create(np->np_prop_root, "url"), url); np->np_url_sub = prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_ROOT, prop_create(np->np_prop_root, "url"), PROP_TAG_CALLBACK_STRING, nav_page_url_set, np, PROP_TAG_COURIER, nav->nav_pc, NULL); np->np_direct_close_sub = prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_ROOT, prop_create(np->np_prop_root, "directClose"), PROP_TAG_CALLBACK_INT, nav_page_direct_close_set, np, PROP_TAG_COURIER, nav->nav_pc, NULL); TRACE(TRACE_INFO, "navigator", "Opening %s", url); if(backend_open(np->np_prop_root, url)) nav_open_errorf(np->np_prop_root, url, "No handler for URL"); nav_insert_page(nav, np, origin); }
static void gu_openerror_create(gu_nav_page_t *gnp) { prop_sub_t *s; GtkWidget *l; gnp->gnp_pageroot = gtk_vbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(gnp->gnp_pagebin), gnp->gnp_pageroot); l = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(l), "<span size=\"x-large\">Unable to open page</span>"); gtk_box_pack_start(GTK_BOX(gnp->gnp_pageroot), l, FALSE, FALSE, 0); gtk_label_set_ellipsize(GTK_LABEL(l), PANGO_ELLIPSIZE_END); l = gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(gnp->gnp_pageroot), l, FALSE, FALSE, 0); gtk_label_set_ellipsize(GTK_LABEL(l), PANGO_ELLIPSIZE_END); s = prop_subscribe(PROP_SUB_DIRECT_UPDATE, PROP_TAG_NAME("self", "url"), PROP_TAG_CALLBACK_STRING, gu_subscription_set_label, l, PROP_TAG_COURIER, glibcourier, PROP_TAG_NAMED_ROOT, gnp->gnp_prop, "self", NULL); gu_unsubscribe_on_destroy(GTK_OBJECT(l), s); l = gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(gnp->gnp_pageroot), l, FALSE, FALSE, 0); gtk_label_set_ellipsize(GTK_LABEL(l), PANGO_ELLIPSIZE_END); s = prop_subscribe(PROP_SUB_DIRECT_UPDATE, PROP_TAG_NAME("self", "model", "error"), PROP_TAG_CALLBACK_STRING, gu_subscription_set_label, l, PROP_TAG_COURIER, glibcourier, PROP_TAG_NAMED_ROOT, gnp->gnp_prop, "self", NULL); gu_unsubscribe_on_destroy(GTK_OBJECT(l), s); gtk_widget_show_all(gnp->gnp_pageroot); }
void gu_popup_init(gtk_ui_t *gu) { gu->gu_popup_sub = prop_subscribe(0, PROP_TAG_NAME("global", "popups"), PROP_TAG_CALLBACK, popups_update, gu, PROP_TAG_COURIER, glibcourier, NULL); }
static void build_tab_header(gu_tab_t *gt) { prop_courier_t *pc = gt->gt_gw->gw_gu->gu_pc; GtkWidget *l, *img; prop_sub_t *s; // Tab header gt->gt_label = gtk_hbox_new(FALSE, 0); gtk_widget_set_size_request(gt->gt_label, 150, -1); img = gtk_image_new(); gtk_box_pack_start(GTK_BOX(gt->gt_label), img, FALSE, TRUE, 0); s = prop_subscribe(PROP_SUB_DIRECT_UPDATE, PROP_TAG_NAME("nav", "currentpage", "model", "type"), PROP_TAG_CALLBACK_STRING, gu_set_icon_by_type, img, PROP_TAG_COURIER, pc, PROP_TAG_NAMED_ROOT, gt->gt_nav, "nav", NULL); gu_unsubscribe_on_destroy(GTK_OBJECT(img), s); l = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(gt->gt_label), l, TRUE, TRUE, 0); gtk_label_set_ellipsize(GTK_LABEL(l), PANGO_ELLIPSIZE_END); gtk_misc_set_alignment(GTK_MISC(l), 0, 0.5); gtk_misc_set_padding(GTK_MISC(l), 5, 0); s = prop_subscribe(PROP_SUB_DIRECT_UPDATE, PROP_TAG_NAME("nav", "currentpage", "model", "metadata", "title"), PROP_TAG_CALLBACK_STRING, gu_subscription_set_label, l, PROP_TAG_COURIER, pc, PROP_TAG_NAMED_ROOT, gt->gt_nav, "nav", NULL); gu_unsubscribe_on_destroy(GTK_OBJECT(l), s); gtk_widget_show_all(gt->gt_label); }
static void dyn_menu_item_add(gtk_ui_t *gu, dyn_menu_t *dm, prop_t *p, dyn_menu_item_t *dmi, dyn_menu_item_t *before, int position) { dmi->dmi_dm = dm; dmi->dmi_prop = prop_ref_inc(p); dmi->dmi_type_sub = prop_subscribe(0, PROP_TAG_NAME("node", "type"), PROP_TAG_CALLBACK_STRING, dmi_set_type, dmi, PROP_TAG_NAMED_ROOT, p, "node", PROP_TAG_COURIER, gu->gu_pc, NULL); dmi->dmi_title_sub = prop_subscribe(0, PROP_TAG_NAME("node", "metadata", "title"), PROP_TAG_CALLBACK_STRING, dmi_set_title, dmi, PROP_TAG_NAMED_ROOT, p, "node", PROP_TAG_COURIER, gu->gu_pc, NULL); dmi->dmi_enabled_sub = prop_subscribe(0, PROP_TAG_NAME("node", "enabled"), PROP_TAG_CALLBACK_INT, dmi_set_enabled, dmi, PROP_TAG_NAMED_ROOT, p, "node", PROP_TAG_COURIER, gu->gu_pc, NULL); dmi->dmi_value_sub = prop_subscribe(0, PROP_TAG_NAME("node", "value"), PROP_TAG_CALLBACK_INT, dmi_set_value, dmi, PROP_TAG_NAMED_ROOT, p, "node", PROP_TAG_COURIER, gu->gu_pc, NULL); }
/** * Popup an request to the user on behalf of connman */ static GVariant * agent_request_input(connman_service_t *cs, GVariant *req, GDBusMethodInvocation *inv) { TRACE(TRACE_INFO, "CONNMAN", "Requesting credentials for %s", cs->cs_path); TRACE(TRACE_DEBUG, "CONNMAN", "RequestInput: %s", g_variant_print(req, TRUE)); prop_t *p = prop_create_root(NULL); prop_set(p, "type", PROP_SET_STRING, "auth"); prop_set(p, "id", PROP_SET_STRING, cs->cs_path); prop_set(p, "source", PROP_SET_STRING, "Network"); GVariant *prev = g_variant_lookup_value(req, "PreviousPassphrase", NULL); if(prev) { prop_set(p, "reason", PROP_SET_STRING, "Password incorrect"); } else { prop_set(p, "reason", PROP_SET_STRING, "Password needed"); } GVariant *identity = g_variant_lookup_value(req, "Identity", NULL); cs->cs_input_req_want_identity = identity != NULL; prop_set(p, "disableUsername", PROP_SET_INT, !cs->cs_input_req_want_identity); prop_set(p, "disableDomain", PROP_SET_INT, 1); prop_t *r = prop_create(p, "eventSink"); cs->cs_input_req_sub = prop_subscribe(0, PROP_TAG_CALLBACK_EVENT, input_req_event, cs, PROP_TAG_NAMED_ROOT, r, "popup", PROP_TAG_COURIER, connman_courier, NULL); cs->cs_input_req_prop = p; /* Will show the popup */ if(prop_set_parent(p, prop_create(prop_get_global(), "popups"))) { /* popuproot is a zombie, this is an error */ abort(); } cs->cs_input_req_inv = inv; g_object_ref(G_OBJECT(inv)); return NULL; }
void playinfo_bind_url_to_prop(const char *url, prop_t *parent) { metadb_item_info_t mii; mip_get(url, &mii); metadb_item_prop_t *mip = malloc(sizeof(metadb_item_prop_t)); hts_mutex_lock(&mip_mutex); mip->mip_refcount = 2; // One per subscription created below mip->mip_destroy_sub = prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, metadb_item_prop_destroyed, mip, PROP_TAG_ROOT, parent, PROP_TAG_MUTEX, &mip_mutex, NULL); assert(mip->mip_destroy_sub != NULL); mip->mip_playcount = prop_create_r(parent, "playcount"); mip->mip_lastplayed = prop_create_r(parent, "lastplayed"); mip->mip_restartpos = prop_create_r(parent, "restartpos"); mip->mip_playcount_sub = prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE | PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, metadb_set_playcount, mip, PROP_TAG_ROOT, mip->mip_playcount, PROP_TAG_MUTEX, &mip_mutex, NULL); assert(mip->mip_playcount_sub != NULL); mip->mip_url = strdup(url); unsigned int hash = mystrhash(url) % MIP_HASHWIDTH; LIST_INSERT_HEAD(&mip_hash[hash], mip, mip_link); mip_set(mip, &mii); hts_mutex_unlock(&mip_mutex); }
static prop_sub_t * bookmark_add_prop(prop_t *parent, const char *name, const char *value, bookmark_t *bm, prop_callback_string_t *cb) { prop_t *p = prop_create(parent, name); prop_set_string(p, value); return prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_CALLBACK_STRING, cb, bm, PROP_TAG_ROOT, p, PROP_TAG_MUTEX, &bookmark_mutex, NULL); }
setting_t * settings_create_action(prop_t *parent, prop_t *title, prop_callback_t *cb, void *opaque, prop_courier_t *pc) { setting_t *s = setting_create_leaf(parent, title, "action", "action", 0); s->s_sub = prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_CALLBACK, cb, opaque, PROP_TAG_ROOT, s->s_val, PROP_TAG_COURIER, pc, NULL); return s; }