static void systest_latency_test(void) { const char *ref_wav_paths[] = { add_path(res_path, WAV_TOCK8_PATH), ALT_PATH1 WAV_TOCK8_PATH }; pj_str_t rec_wav_file; pjsua_player_id play_id = PJSUA_INVALID_ID; pjsua_conf_port_id play_slot = PJSUA_INVALID_ID; pjsua_recorder_id rec_id = PJSUA_INVALID_ID; pjsua_conf_port_id rec_slot = PJSUA_INVALID_ID; pj_pool_t *pool = NULL; pjmedia_port *wav_port = NULL; unsigned lat_sum=0, lat_cnt=0, lat_min=0, lat_max=0; enum gui_key key; test_item_t *ti; const char *title = "Audio Latency Test"; pj_status_t status; ti = systest_alloc_test_item(title); if (!ti) return; key = gui_msgbox(title, "This test will try to find the audio device's " "latency. We will play a special WAV file to the " "speaker for ten seconds, then at the end " "calculate the latency. Please don't do anything " "until the test is done.", WITH_OKCANCEL); if (key != KEY_OK) { ti->skipped = PJ_TRUE; return; } key = gui_msgbox(title, "For this test to work, we must be able to capture " "the audio played in the speaker (the echo), and only" " that audio (i.e. you must be in relatively quiet " "place to run this test). " "Press OK to start, or CANCEL to skip.", WITH_OKCANCEL); if (key != KEY_OK) { ti->skipped = PJ_TRUE; return; } PJ_LOG(3,(THIS_FILE, "Running %s", title)); status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths, &play_id); if (status != PJ_SUCCESS) goto on_return; play_slot = pjsua_player_get_conf_port(play_id); rec_wav_file = pj_str(add_path(doc_path, WAV_LATENCY_OUT_PATH)); status = pjsua_recorder_create(&rec_wav_file, 0, NULL, -1, 0, &rec_id); if (status != PJ_SUCCESS) goto on_return; rec_slot = pjsua_recorder_get_conf_port(rec_id); /* Setup the test */ //status = pjsua_conf_connect(0, 0); status = pjsua_conf_connect(play_slot, 0); status = pjsua_conf_connect(0, rec_slot); status = pjsua_conf_connect(play_slot, rec_slot); /* We're running */ PJ_LOG(3,(THIS_FILE, "Please wait while test is running (~10 sec)")); gui_sleep(10); /* Done with the test */ //status = pjsua_conf_disconnect(0, 0); status = pjsua_conf_disconnect(play_slot, rec_slot); status = pjsua_conf_disconnect(0, rec_slot); status = pjsua_conf_disconnect(play_slot, 0); pjsua_recorder_destroy(rec_id); rec_id = PJSUA_INVALID_ID; pjsua_player_destroy(play_id); play_id = PJSUA_INVALID_ID; /* Confirm that echo is heard */ gui_msgbox(title, "Test is done. Now we need to confirm that we indeed " "captured the echo. We will play the captured audio " "and please confirm that you can hear the 'tock' echo.", WITH_OK); status = pjsua_player_create(&rec_wav_file, 0, &play_id); if (status != PJ_SUCCESS) goto on_return; play_slot = pjsua_player_get_conf_port(play_id); status = pjsua_conf_connect(play_slot, 0); if (status != PJ_SUCCESS) goto on_return; key = gui_msgbox(title, "The captured audio is being played back now. " "Can you hear the 'tock' echo?", WITH_YESNO); pjsua_player_destroy(play_id); play_id = PJSUA_INVALID_ID; if (key != KEY_YES) goto on_return; /* Now analyze the latency */ pool = pjsua_pool_create("latency", 512, 512); status = pjmedia_wav_player_port_create(pool, rec_wav_file.ptr, 0, 0, 0, &wav_port); if (status != PJ_SUCCESS) goto on_return; status = calculate_latency(pool, wav_port, &lat_sum, &lat_cnt, &lat_min, &lat_max); if (status != PJ_SUCCESS) goto on_return; on_return: if (wav_port) pjmedia_port_destroy(wav_port); if (pool) pj_pool_release(pool); if (play_id != PJSUA_INVALID_ID) pjsua_player_destroy(play_id); if (rec_id != PJSUA_INVALID_ID) pjsua_recorder_destroy(rec_id); if (status != PJ_SUCCESS) { systest_perror("Sorry we encountered an error: ", status); ti->success = PJ_FALSE; pj_strerror(status, ti->reason, sizeof(ti->reason)); } else if (key != KEY_YES) { ti->success = PJ_FALSE; if (!ti->success) { pj_ansi_strcpy(ti->reason, USER_ERROR); } } else { char msg[200]; pj_size_t msglen; pj_ansi_snprintf(msg, sizeof(msg), "The sound device latency:\r\n" " Min=%u, Max=%u, Avg=%u\r\n", lat_min, lat_max, lat_sum/lat_cnt); msglen = strlen(msg); if (lat_sum/lat_cnt > 500) { pj_ansi_snprintf(msg+msglen, sizeof(msg)-msglen, "The latency is huge!\r\n"); msglen = strlen(msg); } else if (lat_sum/lat_cnt > 200) { pj_ansi_snprintf(msg+msglen, sizeof(msg)-msglen, "The latency is quite high\r\n"); msglen = strlen(msg); } key = gui_msgbox(title, msg, WITH_OK); ti->success = PJ_TRUE; pj_ansi_strncpy(ti->reason, msg, sizeof(ti->reason)); ti->reason[sizeof(ti->reason)-1] = '\0'; } }
int dialog_end(int* rombrowsing){ guievent_t ev; field_t *field; dirty_t dirty; int i, pad, pad2, exit=0, delay=0; int up=0, down=0, left=0, right=0; int loopcount=0; gui_setclip(0,0,gui.w,gui.h); gui_cls(); dialog->pos = 0; dialog->title_x = (gui.w-font_textwidth(dfont,dialog->title))/2; dialog->status_x = (gui.w-font_textwidth(dfont,dialog->status))/2; dialog->field_h = dfont->height; dialog->title_h = dfont->height+8; dialog->status_h = dfont->height+8; dialog->visible_count = (gui.h-dialog->title_h-dialog->status_h)/dialog->field_h; if(dialog->visible_count > dialog->field_count) dialog->visible_count = dialog->field_count; dialog->client_h = dialog->visible_count * dialog->field_h; dialog->title_h = (gui.h -dialog->client_h )/2; dialog->status_h = gui.h - dialog->title_h - dialog->client_h; if(rombrowsing==1){ dialog->selected = LoadLastSelectedRomPos(); if(dialog->selected >= dialog->pos+dialog->visible_count) { dialog->pos = dialog->selected-dialog->visible_count+1; } } pad = dpad; pad2 = dpad << 1; for(i=0; i<dialog->field_count; i++){ int prompt_w=0, body_w=0; field = &(dialog->fields[i]); prompt_w = field->prompt_w; if(prompt_w) prompt_w += pad2; if(prompt_w > dialog->prompt_w) dialog->prompt_w = prompt_w; body_w = field->body_w; if(body_w) body_w += pad2; if(body_w > dialog->body_w) dialog->body_w = body_w; if(dialog->selected==i && !(field->flags & FIELD_SELECTABLE)) dialog->selected++; } if(dialog->selected == dialog->field_count) dialog->selected = -1; if((dialog->prompt_w + dialog->body_w) > gui.w){ if(dialog->prompt_w>gui.w) dialog->prompt_w = gui.w; dialog->body_w = gui.w-dialog->prompt_w; } dialog->prompt_x = (gui.w - dialog->prompt_w - dialog->body_w)/2; dialog->body_x = dialog->prompt_x + dialog->prompt_w; dirty.update=0; dirty.field_start = 0; dirty.field_count = dialog->visible_count; dirty.title = 1; dirty.status = 1; dialog_drawdirty(&dirty); dirty.update = gui_update(); while(!exit){ field = &(dialog->fields[dialog->selected]); if(gui_pollevent(&ev)){ switch(ev.key){ case GUI_UP: up = ev.state; break; case GUI_DOWN: down = ev.state; break; case GUI_LEFT: left = ev.state; break; case GUI_RIGHT: right = ev.state; break; case GUI_SELECT: if(ev.state && field->type == FIELD_TEXT) exit = dialog->selected+1; break; case GUI_BACK: if(ev.state) exit = -1; break; } delay = ev.state ? -1 : 0; } if(delay>0){ delay--; } else { if(delay<0) delay = 4; if(dirty.update == GUI_FLIP) dialog_drawdirty(&dirty); if(up){ int s = dialog->selected; while(--s>=0 && !(dialog->fields[s].flags & FIELD_SELECTABLE)); if(s>=0){ if(s < dialog->pos){ dialog->pos = s; if(dirty.update){ dirty.field_start = 0; dirty.field_count = dialog->visible_count; dirty.title = 1; dirty.status = 1; } } else if(dirty.update){ dirty.field_start = s-dialog->pos; dirty.field_count = dialog->selected-s+1; dirty.title = 0; dirty.status = 0; } dialog->selected = s; } else if(s<0){ /* LOOP */ dialog->pos = dialog->field_count-dialog->visible_count; s = dialog->field_count-1; loopcount=0; checkloop_up: /*prevents the selection of a non-selectable field when looping the selection*/ if(!(dialog->fields[s].flags & FIELD_SELECTABLE)){ s--; loopcount++; if(loopcount < dialog->visible_count) goto checkloop_up; /*set a limited number of loops, equal to the visible number of lines, to prevent an infinite loop when all fields are non-selectable*/ } if(dirty.update){ dirty.field_start = 0; dirty.field_count = dialog->visible_count; dirty.title = 1; dirty.status = 1; } dialog->selected = s; } } else if(down) { int s = dialog->selected; while(++s<=(dialog->field_count-1) && !(dialog->fields[s].flags & FIELD_SELECTABLE)); if(s<dialog->field_count){ if(s >= dialog->pos+dialog->visible_count) { dialog->pos = s-dialog->visible_count+1; if(dirty.update){ dirty.field_start = 0; dirty.field_count = dialog->visible_count; dirty.title = 1; dirty.status = 1; } } else if(dirty.update){ dirty.field_start = dialog->selected-dialog->pos; dirty.field_count = s-dialog->selected+1; dirty.title = 0; dirty.status = 0; } dialog->selected = s; } else if(s>=dialog->field_count){ /* LOOP */ dialog->pos = 0; s = 0; loopcount=0; checkloop_down: /*prevents the selection of a non-selectable field when looping the selection*/ if(!(dialog->fields[s].flags & FIELD_SELECTABLE)){ s++; loopcount++; if(loopcount < dialog->visible_count) goto checkloop_down; /*set a limited number of loops, equal to the visible number of lines, to prevent an infinite loop when all fields are non-selectable*/ } if(dirty.update){ dirty.field_start = 0; dirty.field_count = dialog->visible_count; dirty.title = 1; dirty.status = 1; } dialog->selected = s; } } else if(dialog->field_count > dialog->visible_count && field->type == FIELD_TEXT){ /* FAST SCROLLING */ if(left){ int s = dialog->selected; int p = dialog->pos; if (p <= 0 && s <= 0){ p = dialog->field_count-dialog->visible_count; s = dialog->field_count-(dialog->visible_count-dialog->selected); } else { p = dialog->selected-dialog->visible_count; s = dialog->selected-dialog->visible_count; } if (p < 0){ p = 0; } if (s < 0){ s = 0; } if(dirty.update){ dirty.field_start = 0; dirty.field_count = dialog->visible_count; dirty.title = 1; dirty.status = 1; } dialog->pos = p; dialog->selected = s; } else if(right){ int s = dialog->selected; int p = dialog->pos; if (p >= dialog->field_count-dialog->visible_count && s >= dialog->field_count-1){ p = 0; s = (dialog->selected+dialog->visible_count)-dialog->field_count; } else { p = dialog->selected+1; s = dialog->selected+dialog->visible_count; } if (p > (dialog->field_count-dialog->visible_count)){ p = dialog->field_count-dialog->visible_count; } if (s > dialog->field_count-1){ s = dialog->field_count-1; } if(dirty.update){ dirty.field_start = 0; dirty.field_count = dialog->visible_count; dirty.title = 1; dirty.status = 1; } dialog->pos = p; dialog->selected = s; } } else if(field->type == FIELD_OPTION){ if(left){ (*field->selected)--; if(*field->selected < 0) *field->selected = field->count-1; field->body = field->options[*field->selected]; if(dirty.update){ dirty.field_start = dialog->selected-dialog->pos; dirty.field_count = 1; dirty.title = 0; dirty.status = 0; } } else if(right){ (*field->selected)++; if(*field->selected >= field->count) *field->selected = 0; field->body = field->options[*field->selected]; if(dirty.update){ dirty.field_start = dialog->selected-dialog->pos; dirty.field_count = 1; dirty.title = 0; dirty.status = 0; } } } dialog_drawdirty(&dirty); dirty.update = gui_update(); #if defined(DINGOO_OPENDINGUX) dialog_drawdirty(&dirty); /*Fix for flickering menu when using double buffer*/ dirty.update = gui_update(); /*Paints the menu 2 times to prevent flickering*/ #endif /*DINGOO_OPENDINGUX*/ } gui_sleep(50000); } if(exit==-1) exit = 0; if(rombrowsing==1){ if(exit>=1){ SaveLastSelectedRomPos(dialog->selected); } } free(dialog); dialog = NULL; return exit; }