void prop_set_from_gvariant(GVariant *v, prop_t *p) { const GVariantType *T = g_variant_get_type(v); if(g_variant_type_equal(T, G_VARIANT_TYPE_BOOLEAN)) { prop_set_int(p, g_variant_get_boolean(v)); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_BYTE)) { prop_set_int(p, g_variant_get_byte(v)); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_INT16)) { prop_set_int(p, g_variant_get_int16(v)); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_UINT16)) { prop_set_int(p, g_variant_get_uint16(v)); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_INT32)) { prop_set_int(p, g_variant_get_int32(v)); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_UINT32)) { prop_set_int(p, g_variant_get_uint32(v)); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_INT64)) { int64_t val = g_variant_get_int64(v); if(val <= INT_MAX) prop_set_int(p, val); else prop_set_float(p, val); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_UINT64)) { uint64_t val = g_variant_get_uint64(v); if(val <= INT_MAX) prop_set_int(p, val); else prop_set_float(p, val); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_STRING) || g_variant_type_equal(T, G_VARIANT_TYPE_OBJECT_PATH) || g_variant_type_equal(T, G_VARIANT_TYPE_SIGNATURE)) { const gchar *val = g_variant_get_string(v, NULL); prop_set_string(p, val); } else if(g_variant_type_equal(T, G_VARIANT_TYPE_VARDICT)) { prop_void_childs(p); prop_set_from_vardict(v, p); } else if(g_variant_type_is_array(T)) { int num = g_variant_n_children(v); prop_destroy_childs(p); for(int i = 0; i < num; i++) { prop_set_from_gvariant(g_variant_get_child_value(v, i), prop_create(p, NULL)); } } else { fprintf(stderr, "%s(): can't deal with type %s\n", __FUNCTION__, g_variant_get_type_string(v)); } }
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 video_seek(rtmp_t *r, media_pipe_t *mp, media_buf_t **mbp, int64_t pos, const char *txt) { if(pos < 0) pos = 0; TRACE(TRACE_DEBUG, "Video", "seek %s to %.2f", txt, pos / 1000000.0); RTMP_SendSeek(r->r, pos / 1000); r->seekpos_video = pos; r->seekpos_audio = pos; mp->mp_video.mq_seektarget = pos; mp->mp_audio.mq_seektarget = pos; mp_flush(mp); if(mbp != NULL && *mbp != NULL) { media_buf_free_unlocked(mp, *mbp); *mbp = NULL; } prop_set_float(prop_create(mp->mp_prop_root, "seektime"), pos / 1000000.0); }
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 int64_t video_seek(rtmp_t *r, media_pipe_t *mp, media_buf_t **mbp, int64_t pos, int backward, const char *txt) { if(pos < 0) pos = 0; TRACE(TRACE_DEBUG, "Video", "seek %s to %.2f", txt, pos / 1000000.0); RTMP_SendSeek(r->r, pos / 1000); r->seekpos = pos; mp->mp_video.mq_seektarget = pos; mp->mp_audio.mq_seektarget = pos; mp_flush(mp, 0); if(mbp != NULL && *mbp != NULL) { media_buf_free(*mbp); *mbp = NULL; } prop_set_float(prop_create(mp->mp_prop_root, "seektime"), pos / 1000000.0); r->lastsubpts = AV_NOPTS_VALUE; return pos; }
static void mip_set(metadb_item_prop_t *mip, const metadb_item_info_t *mii) { prop_set_int_ex(mip->mip_playcount, mip->mip_playcount_sub, mii->mii_playcount); prop_set_int(mip->mip_lastplayed, mii->mii_lastplayed); prop_set_float(mip->mip_restartpos, mii->mii_restartpos / 1000.0); }
static void cpu_monitor_do(void) { kern_return_t r; processor_info_t pinfo; mach_msg_type_number_t msg_count; unsigned int cpu_count_temp; char buf[100]; r = host_processor_info(mach_host_self (), PROCESSOR_CPU_LOAD_INFO, &cpu_count_temp, (processor_info_array_t *)&pinfo, &msg_count); if(r != KERN_SUCCESS) return; if(cpu_count != cpu_count_temp) { vm_deallocate(mach_task_self(), (vm_address_t)pinfo, (vm_size_t)sizeof(*pinfo) * msg_count); return; } int i; for(i = 0; i < cpu_count; i++) { if(p_cpu[i] == NULL) { p_cpu[i] = prop_create(p_cpuroot, NULL); snprintf(buf, sizeof(buf), "CPU%d", i); prop_set_string(prop_create(p_cpu[i], "name"), buf); p_load[i] = prop_create(p_cpu[i], "load"); } processor_info_t pi = pinfo + (CPU_STATE_MAX * i); unsigned int total = (pi[CPU_STATE_USER] + pi[CPU_STATE_SYSTEM] + pi[CPU_STATE_NICE] + pi[CPU_STATE_IDLE]); unsigned int idle = pi[CPU_STATE_IDLE]; unsigned int di = idle - last_idle[i]; unsigned int dt = total - last_total[i]; last_idle[i] = idle; last_total[i] = total; prop_set_float(p_load[i], 1.0 - ((float)di / (float)dt)); } vm_deallocate(mach_task_self(), (vm_address_t)pinfo, (vm_size_t)sizeof(*pinfo) * msg_count); }
static int handle_metadata0(rtmp_t *r, AMFObject *obj, media_pipe_t *mp, char *errstr, size_t errlen) { AVal metastring; AMFObjectProperty prop; prop_t *m = mp->mp_prop_metadata; AMFProp_GetString(AMF_GetProp(obj, NULL, 0), &metastring); if(!AVMATCH(&metastring, &av_onMetaData)) { snprintf(errstr, errlen, "No metadata in metadata packet"); return -1; } if(RTMP_FindFirstMatchingProperty(obj, &av_duration, &prop) && prop.p_type == AMF_NUMBER && prop.p_vu.p_number > 0) { prop_set_float(prop_create(m, "duration"), prop.p_vu.p_number); r->total_duration = prop.p_vu.p_number * 1000; mp_set_duration(mp, r->total_duration * 1000LL); mp_set_clr_flags(mp, MP_CAN_SEEK, 0); if(r->ss == NULL && !(r->va->flags & BACKEND_VIDEO_NO_SUBTITLE_SCAN)) r->ss = sub_scanner_create(r->url, mp->mp_prop_subtitle_tracks, r->va, 0); } else { r->total_duration = 0; mp_set_duration(mp, AV_NOPTS_VALUE); mp_set_clr_flags(mp, 0, MP_CAN_SEEK); } if((RTMP_FindFirstMatchingProperty(obj, &av_videoframerate, &prop) && RTMP_FindFirstMatchingProperty(obj, &av_framerate, &prop)) && prop.p_type == AMF_NUMBER) { r->vframeduration = 1000000.0 / prop.p_vu.p_number; mp->mp_framerate.num = 1000000; mp->mp_framerate.den = prop.p_vu.p_number; } r->width = r->height = 0; if(RTMP_FindFirstMatchingProperty(obj, &av_width, &prop) && prop.p_type == AMF_NUMBER) r->width = prop.p_vu.p_number; if(RTMP_FindFirstMatchingProperty(obj, &av_height, &prop) && prop.p_type == AMF_NUMBER) r->height = prop.p_vu.p_number; if(r->width && r->height) TRACE(TRACE_DEBUG, "RTMP", "Video size %d x %d", r->width, r->height); return 0; }
static int handle_metadata0(rtmp_t *r, AMFObject *obj, media_pipe_t *mp, char *errstr, size_t errlen) { AVal metastring; AMFObjectProperty prop; prop_t *m = mp->mp_prop_metadata; AMFProp_GetString(AMF_GetProp(obj, NULL, 0), &metastring); if(!AVMATCH(&metastring, &av_onMetaData)) { snprintf(errstr, errlen, "No metadata in metadata packet"); return -1; } if(!RTMP_FindFirstMatchingProperty(obj, &av_duration, &prop) || prop.p_type != AMF_NUMBER) { snprintf(errstr, errlen, "Unable to parse total duration"); return -1; } prop_set_float(prop_create(m, "duration"), prop.p_vu.p_number); r->duration = prop.p_vu.p_number; if(!RTMP_FindFirstMatchingProperty(obj, &av_videoframerate, &prop) || prop.p_type != AMF_NUMBER) { if(!RTMP_FindFirstMatchingProperty(obj, &av_framerate, &prop) || prop.p_type != AMF_NUMBER) { snprintf(errstr, errlen, "Unable to parse video framerate"); return -1; } } r->vframeduration = 1000000.0 / prop.p_vu.p_number; r->width = r->height = 0; if(RTMP_FindFirstMatchingProperty(obj, &av_width, &prop) && prop.p_type == AMF_NUMBER) r->width = prop.p_vu.p_number; if(RTMP_FindFirstMatchingProperty(obj, &av_height, &prop) && prop.p_type == AMF_NUMBER) r->height = prop.p_vu.p_number; if(r->width && r->height) TRACE(TRACE_DEBUG, "RTMP", "Video size %d x %d", r->width, r->height); return 0; }
void js_prop_set_from_jsval(JSContext *cx, prop_t *p, jsval value) { JSBool b; if(JSVAL_IS_INT(value)) { prop_set_int(p, JSVAL_TO_INT(value)); } else if(JSVAL_IS_BOOLEAN(value)) { prop_set_int(p, JSVAL_TO_BOOLEAN(value)); } else if(JSVAL_IS_NULL(value) || JSVAL_IS_VOID(value)) { prop_set_void(p); } else if(JSVAL_IS_DOUBLE(value)) { double d; if(JS_ValueToNumber(cx, value, &d)) prop_set_float(p, d); } else if(JS_HasInstance(cx, RichText, value, &b) && b) { JSObject *o = JSVAL_TO_OBJECT(value); jsval v2; if(!JS_EnterLocalRootScope(cx)) return; if(!JS_GetProperty(cx, o, "text", &v2)) { JS_LeaveLocalRootScope(cx); return; } prop_set_string_ex(p, NULL, JS_GetStringBytes(JS_ValueToString(cx, v2)), PROP_STR_RICH); JS_LeaveLocalRootScope(cx); } else if(JSVAL_IS_STRING(value)) { js_prop_from_str(cx, p, value); } else if(JSVAL_IS_OBJECT(value)) { JSObject *obj = JSVAL_TO_OBJECT(value); JSClass *c = JS_GetClass(cx, obj); if(!strcmp(c->name, "XML")) // Treat some classes special js_prop_from_str(cx, p, value); else js_prop_from_object(cx, obj, p); } else { prop_set_void(p); } }
void js_prop_set_from_jsval(JSContext *cx, prop_t *p, jsval value, int recurse) { JSBool b; if(JSVAL_IS_INT(value)) { prop_set_int(p, JSVAL_TO_INT(value)); } else if(JSVAL_IS_BOOLEAN(value)) { prop_set_int(p, JSVAL_TO_BOOLEAN(value)); } else if(JSVAL_IS_DOUBLE(value)) { double d; if(JS_ValueToNumber(cx, value, &d)) prop_set_float(p, d); } else if(JS_HasInstance(cx, RichText, value, &b) && b) { JSObject *o = JSVAL_TO_OBJECT(value); jsval v2; if(!JS_EnterLocalRootScope(cx)) return; if(!JS_GetProperty(cx, o, "text", &v2)) { JS_LeaveLocalRootScope(cx); return; } prop_set_string_ex(p, NULL, JS_GetStringBytes(JS_ValueToString(cx, v2)), PROP_STR_RICH); JS_LeaveLocalRootScope(cx); } else if(JSVAL_IS_VOID(value) || JSVAL_IS_NULL(value)) { prop_set_void(p); } else if(recurse && JSVAL_IS_OBJECT(value)) { js_prop_from_object(cx, JSVAL_TO_OBJECT(value), p, recurse); } else { prop_set_string(p, JS_GetStringBytes(JS_ValueToString(cx, value))); } }
static int gmefile_scandir(fa_dir_t *fd, const char *url, char *errbuf, size_t errlen) { char *p, *fpath = mystrdupa(url); char name[32]; char turl[URL_MAX]; int tracks, i; fa_dir_entry_t *fde; const char *title; Music_Emu *emu; gme_info_t *info; gme_err_t err; if((p = strrchr(fpath, '/')) == NULL) { snprintf(errbuf, errlen, "Invalid filename"); return -1; } *p = 0; buf_t *b; if((b = fa_load(fpath, NULL, errbuf, errlen, NULL, 0, NULL, NULL)) == NULL) return -1; err = gme_open_data(b->b_ptr, b->b_size, &emu, gme_info_only); buf_release(b); if(err != NULL) return 0; tracks = gme_track_count(emu); for(i = 0; i < tracks; i++) { snprintf(turl, sizeof(turl), "gmeplayer:%s/%d", fpath, i + 1); err = gme_track_info(emu, &info, i); if(err == NULL && info->song[0]) { title = info->song; } else { snprintf(name, sizeof(name), "Track %02d", i + 1); title = name; } fde = fa_dir_add(fd, turl, title, CONTENT_AUDIO); fde->fde_probestatus = FDE_PROBE_DEEP; fde->fde_metadata = prop_create_root("metadata"); prop_set_string(prop_create(fde->fde_metadata, "title"), title); if(err == NULL) { if(info->game[0]) prop_set_string(prop_create(fde->fde_metadata, "album"), info->game); if(info->author[0]) prop_set_string(prop_create(fde->fde_metadata, "artist"), info->author); prop_set_float(prop_create(fde->fde_metadata, "duration"), info->play_length / 1000.0); gme_free_info(info); } } gme_delete(emu); return 0; }
media_pipe_t * mp_create(const char *name, int flags) { media_pipe_t *mp; prop_t *p; mp = calloc(1, sizeof(media_pipe_t)); mp->mp_cancellable = cancellable_create(); mp->mp_vol_ui = 1.0f; mp->mp_satisfied = -1; mp->mp_epoch = 1; mp->mp_mb_pool = pool_create("packet headers", sizeof(media_buf_t), POOL_ZERO_MEM); mp->mp_flags = flags; hts_mutex_lock(&media_mutex); LIST_INSERT_HEAD(&media_pipelines, mp, mp_global_link); num_media_pipelines++; hts_mutex_unlock(&media_mutex); TAILQ_INIT(&mp->mp_eq); atomic_set(&mp->mp_refcount, 1); mp->mp_buffer_limit = 1 * 1024 * 1024; mp->mp_name = name; hts_mutex_init(&mp->mp_mutex); hts_mutex_init(&mp->mp_clock_mutex); hts_mutex_init(&mp->mp_overlay_mutex); TAILQ_INIT(&mp->mp_overlay_queue); TAILQ_INIT(&mp->mp_spu_queue); hts_cond_init(&mp->mp_backpressure, &mp->mp_mutex); mp->mp_prop_root = prop_create(media_prop_sources, NULL); mp->mp_prop_metadata = prop_create(mp->mp_prop_root, "metadata"); mp->mp_prop_primary = prop_create(mp->mp_prop_root, "primary"); mp->mp_prop_io = prop_create(mp->mp_prop_root, "io"); mp->mp_prop_notifications = prop_create(mp->mp_prop_root, "notifications"); mp->mp_prop_url = prop_create(mp->mp_prop_root, "url"); mp->mp_setting_root = prop_create(mp->mp_prop_root, "settings"); //-------------------------------------------------- // Video mp->mp_prop_video = prop_create(mp->mp_prop_root, "video"); mp->mp_setting_video_root = prop_create(mp->mp_prop_video, "settings"); mq_init(&mp->mp_video, mp->mp_prop_video, &mp->mp_mutex, mp); //-------------------------------------------------- // Audio mp->mp_prop_audio = prop_create(mp->mp_prop_root, "audio"); mp->mp_setting_audio_root = prop_create(mp->mp_prop_audio, "settings"); mq_init(&mp->mp_audio, mp->mp_prop_audio, &mp->mp_mutex, mp); mp->mp_prop_audio_track_current = prop_create(mp->mp_prop_audio, "current"); mp->mp_prop_audio_track_current_manual = prop_create(mp->mp_prop_audio, "manual"); mp->mp_prop_audio_tracks = prop_create(mp->mp_prop_metadata, "audiostreams"); prop_linkselected_create(mp->mp_prop_audio_tracks, mp->mp_prop_audio, "active", NULL); prop_set_string(mp->mp_prop_audio_track_current, "audio:off"); mp_track_mgr_init(mp, &mp->mp_audio_track_mgr, mp->mp_prop_audio_tracks, MEDIA_TRACK_MANAGER_AUDIO, mp->mp_prop_audio_track_current, prop_create(mp->mp_prop_audio, "sorted")); //-------------------------------------------------- // Subtitles p = prop_create(mp->mp_prop_root, "subtitle"); mp->mp_setting_subtitle_root = prop_create(p, "settings"); mp->mp_prop_subtitle_track_current = prop_create(p, "current"); mp->mp_prop_subtitle_track_current_manual = prop_create(p, "manual"); mp->mp_prop_subtitle_tracks = prop_create(mp->mp_prop_metadata, "subtitlestreams"); prop_linkselected_create(mp->mp_prop_subtitle_tracks, p, "active", NULL); prop_set_string(mp->mp_prop_subtitle_track_current, "sub:off"); mp_add_track_off(mp->mp_prop_subtitle_tracks, "sub:off"); mp_track_mgr_init(mp, &mp->mp_subtitle_track_mgr, mp->mp_prop_subtitle_tracks, MEDIA_TRACK_MANAGER_SUBTITLES, mp->mp_prop_subtitle_track_current, prop_create(p, "sorted")); //-------------------------------------------------- // Buffer p = prop_create(mp->mp_prop_root, "buffer"); mp->mp_prop_buffer_current = prop_create(p, "current"); prop_set_int(mp->mp_prop_buffer_current, 0); mp->mp_prop_buffer_limit = prop_create(p, "limit"); prop_set_int(mp->mp_prop_buffer_limit, mp->mp_buffer_limit); mp->mp_prop_buffer_delay = prop_create(p, "delay"); // mp->mp_prop_playstatus = prop_create(mp->mp_prop_root, "playstatus"); mp->mp_prop_pausereason = prop_create(mp->mp_prop_root, "pausereason"); mp->mp_prop_currenttime = prop_create(mp->mp_prop_root, "currenttime"); mp->mp_prop_fps = prop_create(mp->mp_prop_root, "fps"); prop_set_float_clipping_range(mp->mp_prop_currenttime, 0, 10e6); mp->mp_prop_avdelta = prop_create(mp->mp_prop_root, "avdelta"); prop_set_float(mp->mp_prop_avdelta, 0); mp->mp_prop_svdelta = prop_create(mp->mp_prop_root, "svdelta"); prop_set_float(mp->mp_prop_svdelta, 0); mp->mp_prop_shuffle = prop_create(mp->mp_prop_root, "shuffle"); prop_set_int(mp->mp_prop_shuffle, 0); mp->mp_prop_repeat = prop_create(mp->mp_prop_root, "repeat"); prop_set_int(mp->mp_prop_repeat, 0); mp->mp_prop_avdiff = prop_create(mp->mp_prop_root, "avdiff"); mp->mp_prop_avdiff_error= prop_create(mp->mp_prop_root, "avdiffError"); mp->mp_prop_canSkipBackward = prop_create(mp->mp_prop_root, "canSkipBackward"); mp->mp_prop_canSkipForward = prop_create(mp->mp_prop_root, "canSkipForward"); mp->mp_prop_canSeek = prop_create(mp->mp_prop_root, "canSeek"); mp->mp_prop_canPause = prop_create(mp->mp_prop_root, "canPause"); mp->mp_prop_canEject = prop_create(mp->mp_prop_root, "canEject"); mp->mp_prop_canShuffle = prop_create(mp->mp_prop_root, "canShuffle"); mp->mp_prop_canRepeat = prop_create(mp->mp_prop_root, "canRepeat"); prop_set_int(prop_create(mp->mp_prop_root, "canStop"), 1); mp->mp_prop_ctrl = prop_create(mp->mp_prop_root, "ctrl"); mp->mp_prop_model = prop_create(mp->mp_prop_root, "model"); mp->mp_sub_currenttime = prop_subscribe(PROP_SUB_NO_INITIAL_UPDATE, PROP_TAG_CALLBACK, mp_seek_by_propchange, mp, PROP_TAG_LOCKMGR, mp_lockmgr, PROP_TAG_MUTEX, mp, PROP_TAG_ROOT, mp->mp_prop_currenttime, NULL); mp->mp_sub_eventsink = prop_subscribe(0, PROP_TAG_NAME("media", "eventSink"), PROP_TAG_CALLBACK_EVENT, media_eventsink, mp, PROP_TAG_LOCKMGR, mp_lockmgr, PROP_TAG_MUTEX, mp, PROP_TAG_NAMED_ROOT, mp->mp_prop_root, "media", NULL); if(media_pipe_init_extra != NULL) media_pipe_init_extra(mp); return mp; }
static int cpu_monitor_do(void) { int ret = 0, id; char data[1000]; uint64_t v1, v2, v3, v4, v5, v6, v7, di, tot, dt; char buf[100]; char s1[22]; FILE *f; f = fopen("/proc/stat", "r"); if(f == NULL) return 0; while(fgets(data, sizeof(data), f) != NULL) { if(sscanf(data, "%20s %"PRId64" %"PRId64" %"PRId64" " "%"PRId64" %"PRId64" %"PRId64" %"PRId64, s1, &v1, &v2, &v3, &v4, &v5, &v6, &v7) != 8) continue; if(strncmp(s1, "cpu", 3)) continue; tot = v1+v2+v3+v4+v5+v6+v7; if(!strcmp(s1, "cpu")) { id = 16; } else { id = atoi(s1 + 3); if(id < 0 || id > 16) continue; } if(isvalid) { di = v4 - last_idle[id]; dt = tot - last_tot[id]; if(id < 16) { if(p_cpu[id] == NULL) { p_cpu[id] = prop_create(p_cpuroot, NULL); snprintf(buf, sizeof(buf), "CPU%d", id); prop_set_string(prop_create(p_cpu[id], "name"), buf); p_load[id] = prop_create(p_cpu[id], "load"); } float v = 1.0 - ((float)di / (float)dt); if(v < 0) v = 0; else if(v > 1) v = 1; prop_set_float(p_load[id], v); } } last_idle[id] = v4; last_tot[id] = tot; } isvalid = 1; prop_set_int(prop_create(prop_create(p_sys, "cpuinfo"), "available"), 1); fclose(f); return ret; }