static void sound_nas_finish(ad_device_data *data) { sound_nas_data_t *snd = data; NAS_DEBUG("finishing NAS\n"); if (snd->aud) { NAS_DEBUG("closing 0x%x\n", (unsigned int)snd->aud); AuCloseServer(snd->aud); } snd->aud = NULL; NAS_DEBUG("audio-device finished.\n"); return; }
int nas_init(mme_config_t *mme_config_p) { NAS_DEBUG("Initializing NAS task interface\n"); #if !defined(DISABLE_USE_NAS) nas_log_init(0x3F); nas_network_initialize(mme_config_p); #endif if (itti_create_task(TASK_NAS_MME, &nas_intertask_interface, NULL) < 0) { NAS_ERROR("Create task failed"); NAS_DEBUG("Initializing NAS task interface: FAILED\n"); return -1; } NAS_DEBUG("Initializing NAS task interface: DONE\n"); return 0; }
static ad_device_data * sound_nas_create(Lisp_Object nas_options) { sound_nas_data_t *snd; char *server[6] = {NULL, NULL, NULL, NULL, NULL, NULL}; int i, server_cnt = 0; AuServer *aud = NULL; Lisp_Object opt_server = Qnil; /* parse options */ opt_server = Fplist_get(nas_options, intern(":server"), Qnil); if (!NILP(opt_server) && !STRINGP(opt_server) && !DEVICEP(opt_server)) { wrong_type_argument(Qstringp, opt_server); return NULL; } if (NILP(opt_server)) nas_setup_defaults(server, &server_cnt); else if (STRINGP(opt_server)) server[server_cnt++] = (char*)XSTRING_DATA(opt_server); #ifdef HAVE_X_WINDOWS else if (DEVICEP(opt_server) && DEVICE_X_P(XDEVICE(opt_server))) server[server_cnt++] = (char*)XSTRING_DATA( DEVICE_CONNECTION(XDEVICE(opt_server))); #endif NAS_DEBUG("trying %d connections\n", server_cnt); for (i = 0; i<server_cnt; i++) if ((aud = nas_try_connection(server[i]))) break; if (!aud) { NAS_DEBUG_C("cannot contact any NAS server\n"); warn_when_safe(Qnas, Qwarning, GETTEXT("No NAS servers in sight.\n")); return NULL; /* Could not contact NAS server */ } /* -- initialise -- */ snd = xnew_and_zero(sound_nas_data_t); snd->aud = aud; /* round up SOUND_MAX_AUDIO_FRAME_SIZE to multiple of NAS_FRAG_SIZE * divide by 3 first because of 2:1 split */ snd->proposed_buffer_size = (SOUND_MAX_AUDIO_FRAME_SIZE/3 + NAS_FRAG_SIZE-1) & ~(NAS_FRAG_SIZE-1); NAS_DEBUG_C("proposed buffer size: %u\n", snd->proposed_buffer_size); NAS_DEBUG_C("created: 0x%x\n", (unsigned int)snd); return snd; }
static void nas_setup_defaults(char **server, int *cnt) { int i; Lisp_Object tmp; /* considering some defaults */ NAS_DEBUG("trying to find some defaults\n"); #ifdef HAVE_X_WINDOWS /* check for the device connection of the currently active frame */ tmp = Fselected_device(Qnil); if (DEVICEP(tmp) && DEVICE_X_P(XDEVICE(tmp))) server[(*cnt)++] = (char*)XSTRING_DATA( DEVICE_CONNECTION(XDEVICE(tmp))); /* tbd: check for conn of the initial frame */ #endif /* try to look for $AUDIOSERVER */ if ((server[(*cnt)] = getenv("AUDIOSERVER"))) { /* only add the stuff, if not already in the try queue */ for (i=0; i < (*cnt); i++) if (strcmp(server[i], server[(*cnt)]) == 0) break; if (i == (*cnt)) (*cnt)++; } /* try to look for $DISPLAY */ if ((server[(*cnt)] = getenv("DISPLAY"))){ /* only add the stuff, if not already in the try queue */ for (i=0; i < (*cnt); i++) if (strcmp(server[i], server[(*cnt)]) == 0) break; if (i == (*cnt)) (*cnt)++; } /* oh, let's try localhost:0.0, if not already there of course */ for (i=0; i < (*cnt); i++) if (strcmp(server[i], "localhost:0.0") == 0) break; if (i == (*cnt)) server[(*cnt)++] = "localhost:0.0"; /* finally we try NULL, too */ server[(*cnt)++] = NULL; return; }
static void *nas_intertask_interface(void *args_p) { itti_mark_task_ready(TASK_NAS_MME); MSC_START_USE(); while(1) { MessageDef *received_message_p; next_message: itti_receive_msg(TASK_NAS_MME, &received_message_p); switch (ITTI_MSG_ID(received_message_p)) { case NAS_CONNECTION_ESTABLISHMENT_IND: { #if defined(DISABLE_USE_NAS) MessageDef *message_p; nas_attach_req_t *nas_req_p; s1ap_initial_ue_message_t *transparent; NAS_DEBUG("NAS abstraction: Generating NAS ATTACH REQ\n"); message_p = itti_alloc_new_message(TASK_NAS_MME, NAS_ATTACH_REQ); nas_req_p = &message_p->ittiMsg.nas_attach_req; transparent = &message_p->ittiMsg.nas_attach_req.transparent; nas_req_p->initial = INITIAL_REQUEST; sprintf(nas_req_p->imsi, "%14llu", 20834123456789ULL); memcpy(transparent, &received_message_p->ittiMsg.nas_conn_est_ind.transparent, sizeof(s1ap_initial_ue_message_t)); itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p); #else nas_establish_ind_t *nas_est_ind_p; nas_est_ind_p = &received_message_p->ittiMsg.nas_conn_est_ind.nas; nas_proc_establish_ind(nas_est_ind_p->UEid, nas_est_ind_p->tac, nas_est_ind_p->initialNasMsg.data, nas_est_ind_p->initialNasMsg.length); #endif } break; #if defined(DISABLE_USE_NAS) case NAS_ATTACH_ACCEPT: { itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, received_message_p); goto next_message; } break; case NAS_AUTHENTICATION_REQ: { MessageDef *message_p; nas_auth_resp_t *nas_resp_p; NAS_DEBUG("NAS abstraction: Generating NAS AUTHENTICATION RESPONSE\n"); message_p = itti_alloc_new_message(TASK_NAS_MME, NAS_AUTHENTICATION_RESP); nas_resp_p = &message_p->ittiMsg.nas_auth_resp; memcpy(nas_resp_p->imsi, received_message_p->ittiMsg.nas_auth_req.imsi, 16); itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p); } break; #else case NAS_UPLINK_DATA_IND: { nas_proc_ul_transfer_ind(NAS_UL_DATA_IND(received_message_p).UEid, NAS_UL_DATA_IND(received_message_p).nasMsg.data, NAS_UL_DATA_IND(received_message_p).nasMsg.length); } break; case NAS_DOWNLINK_DATA_CNF: { nas_proc_dl_transfer_cnf(NAS_DL_DATA_CNF(received_message_p).UEid); } break; case NAS_DOWNLINK_DATA_REJ: { nas_proc_dl_transfer_rej(NAS_DL_DATA_REJ(received_message_p).UEid); } break; case NAS_AUTHENTICATION_PARAM_RSP: { nas_proc_auth_param_res(&NAS_AUTHENTICATION_PARAM_RSP(received_message_p)); } break; case NAS_AUTHENTICATION_PARAM_FAIL: { nas_proc_auth_param_fail(&NAS_AUTHENTICATION_PARAM_FAIL(received_message_p)); } break; #endif case NAS_PDN_CONNECTIVITY_RSP: { nas_proc_pdn_connectivity_res(&NAS_PDN_CONNECTIVITY_RSP(received_message_p)); } break; case NAS_PDN_CONNECTIVITY_FAIL: { nas_proc_pdn_connectivity_fail(&NAS_PDN_CONNECTIVITY_FAIL(received_message_p)); } break; case TIMER_HAS_EXPIRED: { #if !defined(DISABLE_USE_NAS) /* Call the NAS timer api */ nas_timer_handle_signal_expiry(TIMER_HAS_EXPIRED(received_message_p).timer_id, TIMER_HAS_EXPIRED(received_message_p).arg); #endif } break; case S1AP_ENB_DEREGISTERED_IND: { #if !defined(DISABLE_USE_NAS) int i; for (i = 0; i < S1AP_ENB_DEREGISTERED_IND(received_message_p).nb_ue_to_deregister; i ++) { nas_proc_deregister_ue(S1AP_ENB_DEREGISTERED_IND(received_message_p).mme_ue_s1ap_id[i]); } #endif } break; case S1AP_DEREGISTER_UE_REQ: { #if !defined(DISABLE_USE_NAS) nas_proc_deregister_ue(S1AP_DEREGISTER_UE_REQ(received_message_p).mme_ue_s1ap_id); #endif } break; case TERMINATE_MESSAGE: { itti_exit_task(); } break; default: { NAS_DEBUG("Unkwnon message ID %d:%s from %s\n", ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p), ITTI_MSG_ORIGIN_NAME(received_message_p)); } break; } itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p); received_message_p = NULL; } return NULL; }
static int sound_nas_play(audio_job_t aj) { /* stream stuff */ Lisp_Media_Stream *ms; media_substream *mss; /* thread stuff */ media_thread_play_state mtp; /* device stuff */ Lisp_Object device; Lisp_Audio_Device *lad = NULL; sound_nas_data_t *snd = NULL; /* nas stuff */ AuElement elms[3]; AuStatus as; int bsize = 0; /* subthread stuff */ sound_nas_aj_data_t _snsd, *snsd = &_snsd; sxe_mse_volume_args _volargs, *volargs = &_volargs; sxe_mse_rerate_args _rrargs, *rrargs = &_rrargs; /* cache stuff */ int alloced_myself = 0; SOUND_UNPACK_MT(aj, device, ms, mss, lad, snd, snsd->mtap); /* refuse to do anything if the AuServer pointer is not set */ if (snd->aud == NULL) { NAS_DEBUG_C("b0rked connection, gute Nacht!\n"); return 0; } /* install error handlers before anything else */ AuSetErrorHandler(snd->aud, nas_error_handler); AuSetIOErrorHandler(snd->aud, nas_IOerror_handler); /* find physical output device */ snsd->dev = nas_find_device(snd->aud, snsd->mtap->channels); if (snsd->dev == AuNone || !(snsd->flow = AuCreateFlow(snd->aud, NULL))) { /* No physical output device found or flow creation failed. */ NAS_DEBUG_C("no physical devices for this stream\n"); return 0; } /* A system call interrupted with a SIGALRM or SIGIO comes back here */ if (SETJMP(nas_server_sig)) { NAS_CRITICAL("Caught the lethal signal.\n"); snd->aud = NULL; sound_nas_finish(snd); goto uhoh; } /* init the snsd */ snsd->samplerate = 0; snsd->framesize = (snsd->channels = snsd->mtap->channels) * sizeof(int16_t); snsd->msf = MEDIA_SAMPLE_FORMAT(sxe_msf_S16); snsd->coe_ch_cnt = 0; snsd->resolution = (snsd->mtap->samplerate * MTPSTATE_REACT_TIME) / 1000000; bsize = (snsd->resolution + NAS_FRAG_SIZE - 1) & ~(NAS_FRAG_SIZE-1); snsd->snd = snd; snsd->buffer_size = bsize; snsd->writepos = snsd->readpos = 0; snsd->overfill = snsd->underrun = 0; /* set up flow */ AuMakeElementImportClient(elms+0, snsd->mtap->samplerate, AuFormatLinearSigned16LSB, snsd->mtap->channels, AuTrue, bsize, bsize / 2, 0, NULL); snsd->gain = AuFixedPointFromFraction(1, 1); AuMakeElementMultiplyConstant(elms+1, 0, snsd->gain); AuMakeElementExportDevice(elms+2, 0, snsd->dev, snsd->mtap->samplerate, AuUnlimitedSamples, 0, NULL); AuSetElements(snd->aud, snsd->flow, AuTrue, 3, elms, &as); if (as != AuSuccess) { NAS_DEBUG_C("play(): AuSetElements failed\n"); return 0; } #if 0 /* atm we insist on having stereo access */ /* the channel effect */ ADD_MEDIA_SAMPLE_EFFECT( snsd->coe_chain, snsd->coe_ch_cnt, MEDIA_SAMPLE_EFFECT(sxe_mse_2ch_to_1ch), NULL); #endif /* the volume effect */ ADD_MEDIA_SAMPLE_EFFECT( snsd->coe_chain, snsd->coe_ch_cnt, MEDIA_SAMPLE_EFFECT(sxe_mse_volume), volargs); volargs->num_channels = snsd->channels; snsd->volargs = volargs; /* the rerate effect */ ADD_MEDIA_SAMPLE_EFFECT( snsd->coe_chain, snsd->coe_ch_cnt, MEDIA_SAMPLE_EFFECT(sxe_mse_rerate), rrargs); rrargs->num_channels = snsd->channels; rrargs->srcrate = rrargs->tgtrate = 1; snsd->rrargs = rrargs; AuRegisterEventHandler(snd->aud, AuEventHandlerIDMask | AuEventHandlerTypeMask, AuEventTypeElementNotify, snsd->flow, nas_event_handler, (AuPointer)aj); /* rewind the stream */ media_stream_meth(ms, rewind)(mss); /* play chunks of the stream */ SXE_MUTEX_LOCK(&aj->mtx); if (aj->buffer_alloc_size < SOUND_MAX_AUDIO_FRAME_SIZE) { alloced_myself = 1; aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE); aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE; } SXE_MUTEX_UNLOCK(&aj->mtx); snsd->mtp = MTPSTATE_STOP; snsd->volume = -1; audio_job_device_data(aj) = snsd; /* prefill the buffer */ NAS_DEBUG_S("prefill the buffer: %d\n", 4*bsize); if (!nas_fill(aj, 4*bsize)) goto uhoh; while (aj->play_state != MTPSTATE_STOP) { #if 0 if (aj->volume != snsd->volume) { AuElementParameters aep; NAS_DEBUG_S("Setting volume.\n"); snsd->volume = aj->volume; snsd->gain = AU_FIXED_POINT_SCALE*(snsd->volume)/127; aep.parameters[AuParmsMultiplyConstantConstant] = snsd->gain; aep.flow = snd->flow; aep.element_num = 1; aep.num_parameters = AuParmsMultiplyConstant; AuSetElementParameters(snd->aud, 1, &aep, &as); if (as != AuSuccess) { NAS_DEBUG_S("Setting volume failed.\n"); } } #endif #ifdef EF_USE_ASYNEQ /* events for me audio-job? */ if (audio_job_queue(aj)) { sound_nas_handle_aj_events(aj); } #endif SXE_MUTEX_LOCK(&aj->mtx); mtp = aj->play_state; SXE_MUTEX_UNLOCK(&aj->mtx); switch (mtp) { case MTPSTATE_RUN: if (snsd->mtp != mtp) { NAS_DEBUG("ah, gotta work again\n"); AuStartFlow(snd->aud, snsd->flow, &as); if (as != AuSuccess) { NAS_DEBUG_C("play(): " "AuStartFlow failed\n"); aj->play_state = MTPSTATE_STOP; } } nas_empty_event_queue(snsd); usleep(snsd->resolution); break; case MTPSTATE_PAUSE: if (snsd->mtp != mtp) { NAS_DEBUG("sleeping for %d\n", snsd->resolution); AuStopFlow(snd->aud, snsd->flow, &as); } usleep(snsd->resolution); break; case MTPSTATE_UNKNOWN: case MTPSTATE_STOP: case NUMBER_OF_MEDIA_THREAD_PLAY_STATES: default: NAS_DEBUG("ACK, quit\n"); AuStopFlow(snd->aud, snsd->flow, &as); SXE_MUTEX_LOCK(&aj->mtx); aj->play_state = MTPSTATE_STOP; SXE_MUTEX_UNLOCK(&aj->mtx); break; } snsd->mtp = mtp; } uhoh: /* -- Close and shutdown -- */ SXE_MUTEX_LOCK(&aj->mtx); if (alloced_myself && aj->buffer) { xfree(aj->buffer); } aj->buffer = NULL; aj->buffer_alloc_size = 0; SXE_MUTEX_UNLOCK(&aj->mtx); return 1; }