void ui_send_stats(session_t *sp, char *addr, uint32_t ssrc) { /* Send RAT specific statistics to the user interface... */ const rtcp_rr *rr; uint32_t fract_lost, my_ssrc, total_lost; double skew_rate; char *args, *mbes; struct s_source *src; uint32_t buffered, delay; pdb_entry_t *pdbe; session_validate(sp); if (!sp->ui_on) return; if (pdb_item_get(sp->pdb, ssrc, &pdbe) == FALSE) { debug_msg("pdb entry does not exist (0x%08x)\n", ssrc); return; } pdbe->last_ui_update = sp->cur_ts; if (pdbe->enc_fmt) { mbes = mbus_encode_str(pdbe->enc_fmt); args = (char *) xmalloc(strlen(mbes) + 12); sprintf(args, "\"%08x\" %s", pdbe->ssrc, mbes); xfree(mbes); } else { args = (char *) xmalloc(19); sprintf(args, "\"%08x\" unknown", pdbe->ssrc); } mbus_qmsg(sp->mbus_engine, addr, "rtp.source.codec", args, FALSE); xfree(args); src = source_get_by_ssrc(sp->active_sources, pdbe->ssrc); if (src) { buffered = timestamp_to_ms(source_get_audio_buffered(src)); delay = timestamp_to_ms(source_get_playout_delay(src)); skew_rate = source_get_skew_rate(src); } else { buffered = 0; delay = 0; skew_rate = 1.0; } mbus_qmsgf(sp->mbus_engine, addr, FALSE, "tool.rat.audio.buffered", "\"%08lx\" %ld", (unsigned long)pdbe->ssrc, buffered); mbus_qmsgf(sp->mbus_engine, addr, FALSE, "tool.rat.audio.delay", "\"%08lx\" %ld", (unsigned long)pdbe->ssrc, delay); mbus_qmsgf(sp->mbus_engine, addr, FALSE, "tool.rat.audio.skew", "\"%08lx\" %.5f", (unsigned long)pdbe->ssrc, skew_rate); mbus_qmsgf(sp->mbus_engine, addr, FALSE, "tool.rat.spike.events", "\"%08lx\" %ld", (unsigned long)pdbe->ssrc, pdbe->spike_events); mbus_qmsgf(sp->mbus_engine, addr, FALSE, "tool.rat.spike.toged", "\"%08lx\" %ld", (unsigned long)pdbe->ssrc, pdbe->spike_toged); my_ssrc = rtp_my_ssrc(sp->rtp_session[0]); rr = rtp_get_rr(sp->rtp_session[0], my_ssrc, pdbe->ssrc); if (rr != NULL) { fract_lost = (rr->fract_lost * 100) >> 8; total_lost = rr->total_lost; } else {
/** * The main entrance of bbswebd. * @return 0 on success, 1 on initialization error. */ int main(void) { fb_signal(SIGTERM, exit_handler); fb_signal(SIGUSR1, exit_handler); if (initialize() < 0) return EXIT_FAILURE; initialize_environment(INIT_CONV | INIT_DB | INIT_MDB); while (FCGI_Accept() >= 0) { if (!web_ctx_init()) return EXIT_FAILURE; const web_handler_t *h = _get_handler(); int code = BBS_ENOURL; if (h) { get_client_ip(); session_validate(); brc_reset(); if (session_get_id()) { if (h->status != ST_IDLE) set_user_status(h->status); session_set_idle(session_get_id(), fb_time()); if (h->status != ST_READING) session_set_board(0); } code = execute(h); } if (code > 0) web_respond(code); else check_bbserr(code); web_ctx_destroy(); } return 0; }
/* This function needs to be modified to return some indication of how well * or not we are doing. */ int audio_rw_process(session_t *spi, session_t *spo, struct s_mixer *ms) { uint32_t cushion_size, read_dur; struct s_cushion_struct *c; int trailing_silence, new_cushion, cushion_step, diff; const audio_format* ofmt; sample *bufp; session_validate(spi); session_validate(spo); c = spi->cushion; if ((read_dur = tx_read_audio(spi->tb)) <= 0) { return 0; } else { if (!spi->audio_device) { /* no device means no cushion */ return read_dur; } } xmemchk(); /* read_dur now reflects the amount of real time it took us to get * through the last cycle of processing. */ if (spo->lecture == TRUE && spo->auto_lecture == 0) { cushion_update(c, read_dur, CUSHION_MODE_LECTURE); } else { cushion_update(c, read_dur, CUSHION_MODE_CONFERENCE); } /* Following code will try to achieve new cushion size without * messing up the audio... * First case is when we are in trouble and the output has gone dry. * In this case we write out a complete new cushion with the desired * size. We do not care how much of it is going to be real audio and * how much silence so long as the silence is at the head of the new * cushion. If the silence was at the end we would be creating * another silence gap... */ cushion_size = cushion_get_size(c); ofmt = audio_get_ofmt(spi->audio_device); if (cushion_size < read_dur) { debug_msg("catch up! read_dur(%d) > cushion_size(%d)\n", read_dur, cushion_size); /* Use a step for the cushion to keep things nicely rounded */ /* in the mixing. Round it up. */ new_cushion = cushion_use_estimate(c); assert(new_cushion >= 0 && new_cushion < 100000); /* The mix routine also needs to know for how long the */ /* output went dry so that it can adjust the time. */ mix_new_cushion(ms, cushion_size, new_cushion, (read_dur - cushion_size), &bufp); audio_device_write(spo, bufp, new_cushion); /* We've blocked for this long for whatever reason */ cushion_size = new_cushion; } else { trailing_silence = mix_get_audio(ms, read_dur * ofmt->channels, &bufp); cushion_step = cushion_get_step(c); diff = 0; if (trailing_silence > cushion_step) { /* Check whether we need to adjust the cushion */ diff = cushion_diff_estimate_size(c); if (abs(diff) < cushion_step) { diff = 0; } } /* If diff is less than zero then we must decrease the */ /* cushion so loose some of the trailing silence. */ if (diff < 0 && mix_active(ms) == FALSE && source_list_source_count(spi->active_sources) == 0) { /* Only decrease cushion if not playing anything out */ uint32_t old_cushion; old_cushion = cushion_get_size(c); if (read_dur > (unsigned)cushion_step) { cushion_step_down(c); if (cushion_get_size(c) != old_cushion) { debug_msg("Decreasing cushion\n"); read_dur -= cushion_step; } } } assert(read_dur < 0x7fffffff); audio_device_write(spo, bufp, read_dur); /* * If diff is greater than zero then we must increase the * cushion so increase the amount of trailing silence. */ if (diff > 0) { assert(cushion_step > 0); audio_device_write(spo, zero_buf, cushion_step); cushion_step_up(c); debug_msg("Increasing cushion.\n"); } } return (read_dur); }