int audio_device_reconfigure(session_t *sp) { audio_config prev_config, *curr_config, *new_config; audio_port_t iport = 0, oport = 0; int change_req; assert(sp->new_config != NULL); new_config = sp->new_config; change_req = FALSE; if (new_config->device == 0) { /* No request to change audio device */ new_config->device = sp->audio_device; } else if (new_config->device != sp->audio_device) { /* Request to change device */ change_req = TRUE; debug_msg("Change device requested.\n"); } if (sp->audio_device) { iport = audio_get_iport(sp->audio_device); oport = audio_get_oport(sp->audio_device); } if (new_config->primary == 0) { /* No request to change primary encoding */ new_config->primary = codec_get_by_payload(sp->encodings[0]); } else if (codec_audio_formats_compatible(new_config->primary, codec_get_by_payload(sp->encodings[0])) == FALSE) { /* Request to change primary and format incompatible so * device needs rejigging */ change_req = TRUE; debug_msg("Change primary requested.\n"); } else { /* Request to change primary to compatible coding. */ sp->encodings[0] = codec_get_payload(new_config->primary); } if (new_config->render_3d == -1) { /* No request to change 3d rendering */ new_config->render_3d = sp->render_3d; } else if (new_config->render_3d != sp->render_3d) { change_req = TRUE; debug_msg("Change 3d rendering enabled requested.\n"); } if (change_req) { /* Store current config in case it reconfig attempt fails */ prev_config.device = sp->audio_device; prev_config.primary = codec_get_by_payload(sp->encodings[0]); prev_config.render_3d = sp->render_3d; if (sp->audio_device) { audio_device_release(sp, sp->audio_device); } if (audio_device_attempt_config(sp, new_config)) { /* New config acceptable */ curr_config = new_config; } else if (audio_device_attempt_config(sp, &prev_config)) { /* else attempt to fallback to previous config */ curr_config = &prev_config; debug_msg("Fellback to old dev config\n"); } else { /* Fallback to guaranteed config - something * went badly wrong */ ac_destroy(&new_config); audio_device_get_safe_config(&new_config); assert(new_config); if (audio_device_attempt_config(sp, new_config) == FALSE) { /* should never get here */ abort(); } curr_config = new_config; debug_msg("Fell back to safe config\n"); } debug_msg("0x%08x 0x%08x\n", prev_config.device, curr_config->device); if (prev_config.device == curr_config->device) { debug_msg("Restoring ports\n"); audio_set_iport(curr_config->device, iport); audio_set_oport(curr_config->device, oport); } else { const audio_port_details_t *papd; /* Ports will be squiffy */ papd = audio_get_iport_details(curr_config->device, 0); audio_set_iport(curr_config->device, papd->port); papd = audio_get_oport_details(curr_config->device, 0); audio_set_oport(curr_config->device, papd->port); } audio_loopback(curr_config->device, sp->loopback_gain); sp->audio_device = curr_config->device; sp->encodings[0] = codec_get_payload(curr_config->primary); /* If using redundancy check it is still relevent */ if (sp->num_encodings > 1 && !codec_audio_formats_compatible(curr_config->primary, codec_get_by_payload(sp->encodings[1]))) { const cc_details_t *ccd; channel_encoder_destroy(&sp->channel_coder); ccd = channel_get_null_coder(); channel_encoder_create(ccd->descriptor, &sp->channel_coder); sp->num_encodings = 1; } sp->render_3d = curr_config->render_3d; } else { debug_msg("audio device reconfigure - nothing to do.\n"); if (tx_is_sending(sp->tb)) { tx_stop(sp->tb); tx_start(sp->tb); } } tx_igain_update(sp->tb); ac_destroy(&sp->new_config); return change_req; }
void settings_save(session_t *sp) { /* FIXME: This needs to be updated for the transcoder */ const codec_format_t *pri_cf; const audio_port_details_t *iapd = NULL; const audio_port_details_t *oapd = NULL; const audio_format *af = NULL; const repair_details_t *repair = NULL; const converter_details_t *converter = NULL; const audio_device_details_t *add = NULL; const cc_details_t *ccd = NULL; codec_id_t pri_id; int cc_len; char *cc_param; int i; uint16_t j,n; uint32_t my_ssrc; pri_id = codec_get_by_payload(sp->encodings[0]); pri_cf = codec_get_format(pri_id); cc_len = 3 * (CODEC_LONG_NAME_LEN + 4) + 1; cc_param = (char*) xmalloc(cc_len); channel_encoder_get_parameters(sp->channel_coder, cc_param, cc_len); ccd = channel_get_coder_identity(sp->channel_coder); n = (uint16_t)converter_get_count(); for (j = 0; j < n; j++) { converter = converter_get_details(j); if (sp->converter == converter->id) { break; } } n = repair_get_count(); for (j = 0; j < n; j++) { repair = repair_get_details(j); if (sp->repair == repair->id) { break; } } n = (int)audio_get_device_count(); for (i = 0; i < n; i++) { add = audio_get_device_details(i); if (sp->audio_device == add->descriptor) { break; } } af = audio_get_ifmt(sp->audio_device); for(i = 0; i < audio_get_iport_count(sp->audio_device); i++) { iapd = audio_get_iport_details(sp->audio_device, i); if (iapd->port == audio_get_iport(sp->audio_device)) { break; } } for(i = 0; i < audio_get_oport_count(sp->audio_device); i++) { oapd = audio_get_oport_details(sp->audio_device, i); if (oapd->port == audio_get_oport(sp->audio_device)) { break; } } save_init_rtp(); my_ssrc = rtp_my_ssrc(sp->rtp_session[0]); setting_save_str("rtpName", rtp_get_sdes(sp->rtp_session[0], my_ssrc, RTCP_SDES_NAME)); setting_save_str("rtpEmail", rtp_get_sdes(sp->rtp_session[0], my_ssrc, RTCP_SDES_EMAIL)); setting_save_str("rtpPhone", rtp_get_sdes(sp->rtp_session[0], my_ssrc, RTCP_SDES_PHONE)); setting_save_str("rtpLoc", rtp_get_sdes(sp->rtp_session[0], my_ssrc, RTCP_SDES_LOC)); setting_save_str("rtpNote", rtp_get_sdes(sp->rtp_session[0], my_ssrc, RTCP_SDES_NOTE)); save_done_rtp(); save_init_rat(); setting_save_str("audioTool", rtp_get_sdes(sp->rtp_session[0], my_ssrc, RTCP_SDES_TOOL)); setting_save_str("audioDevice", add->name); setting_save_int("audioFrequency", af->sample_rate); setting_save_int("audioChannelsIn", af->channels); /* If we save a dynamically mapped codec we crash when we reload on startup */ if (pri_cf->default_pt != CODEC_PAYLOAD_DYNAMIC) { setting_save_str("audioPrimary", pri_cf->short_name); } setting_save_int("audioUnits", channel_encoder_get_units_per_packet(sp->channel_coder)); /* Don't save the layered channel coder - you need to start it */ /* from the command line anyway */ if (strcmp(ccd->name, "Layering") == 0) { setting_save_str("audioChannelCoding", "Vanilla"); } else { setting_save_str("audioChannelCoding", ccd->name); } setting_save_str("audioChannelParameters", cc_param); setting_save_str("audioRepair", repair->name); setting_save_str("audioAutoConvert", converter->name); setting_save_int("audioLimitPlayout", sp->limit_playout); setting_save_int("audioMinPlayout", sp->min_playout); setting_save_int("audioMaxPlayout", sp->max_playout); setting_save_int("audioLecture", sp->lecture); setting_save_int("audio3dRendering", sp->render_3d); setting_save_int("audioAGC", sp->agc_on); setting_save_int("audioLoopback", sp->loopback_gain); setting_save_int("audioEchoSuppress", sp->echo_suppress); setting_save_int("audioOutputGain", audio_get_ogain(sp->audio_device)); setting_save_int("audioInputGain", audio_get_igain(sp->audio_device)); setting_save_str("audioOutputPort", oapd->name); setting_save_str("audioInputPort", iapd->name); setting_save_int("audioPowermeters", sp->meter); setting_save_str("audioSilence", sd_name(sp->silence_detection)); setting_save_int("audioSilenceManualThresh", sp->manual_sd_thresh); /* We do not save audioOutputMute and audioInputMute by default, but should */ /* recognize them when reloading. */ save_done_rat(); xfree(cc_param); }