From c7b6327cfa9f26d1632e9ac42d0c3d63468731a1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 7 Mar 2013 14:46:42 -0600 Subject: [PATCH 001/113] FS-5149 --resolve --- .../mod_conference/mod_conference.c | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index f967a92127..882d607661 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -434,6 +434,7 @@ struct conference_member { switch_ivr_dmachine_t *dmachine; conference_cdr_node_t *cdr_node; char *kicked_sound; + switch_queue_t *dtmf_queue; }; /* Record Node */ @@ -1394,6 +1395,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe member->energy_level = conference->energy_level; member->score_iir = 0; member->verbose_events = conference->verbose_events; + switch_queue_create(&member->dtmf_queue, 100, member->pool); conference->members = member; switch_set_flag_locked(member, MFLAG_INTREE); switch_mutex_unlock(conference->member_mutex); @@ -3124,9 +3126,18 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v } else if (member->dmachine) { switch_ivr_dmachine_ping(member->dmachine, NULL); } - - - + + if (switch_queue_size(member->dtmf_queue)) { + switch_dtmf_t *dt; + void *pop; + + if (switch_queue_trypop(member->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) { + dt = (switch_dtmf_t *) pop; + switch_core_session_send_dtmf(member->session, dt); + free(dt); + } + } + if (switch_test_flag(read_frame, SFF_CNG)) { if (member->conference->agc_level) { member->nt_tally++; @@ -3353,6 +3364,16 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v } + if (switch_queue_size(member->dtmf_queue)) { + switch_dtmf_t *dt; + void *pop; + + while (switch_queue_trypop(member->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) { + dt = (switch_dtmf_t *) pop; + free(dt); + } + } + switch_resample_destroy(&member->read_resampler); switch_clear_flag_locked(member, MFLAG_ITHREAD); @@ -4105,11 +4126,13 @@ static void conference_send_all_dtmf(conference_member_t *member, conference_obj if (imember->session) { const char *p; for (p = dtmf; p && *p; p++) { - switch_dtmf_t digit = { *p, SWITCH_DEFAULT_DTMF_DURATION }; - lock_member(imember); + switch_dtmf_t *dt, digit = { *p, SWITCH_DEFAULT_DTMF_DURATION }; + + switch_zmalloc(dt, sizeof(*dt)); + *dt = digit; + printf("QQQQ %c\n", dt->digit); + switch_queue_push(member->dtmf_queue, dt); switch_core_session_kill_channel(imember->session, SWITCH_SIG_BREAK); - switch_core_session_send_dtmf(imember->session, &digit); - unlock_member(imember); } } } @@ -4882,12 +4905,19 @@ static switch_status_t conf_api_sub_dtmf(conference_member_t *member, switch_str if (zstr(dtmf)) { stream->write_function(stream, "Invalid input!\n"); return SWITCH_STATUS_GENERR; - } + } else { + char *p; - lock_member(member); - switch_core_session_kill_channel(member->session, SWITCH_SIG_BREAK); - switch_core_session_send_dtmf_string(member->session, (char *) data); - unlock_member(member); + for(p = dtmf; p && *p; p++) { + switch_dtmf_t *dt, digit = { *p, SWITCH_DEFAULT_DTMF_DURATION }; + + switch_zmalloc(dt, sizeof(*dt)); + *dt = digit; + + switch_queue_push(member->dtmf_queue, dt); + switch_core_session_kill_channel(member->session, SWITCH_SIG_BREAK); + } + } if (stream != NULL) { stream->write_function(stream, "OK sent %s to %u\n", (char *) data, member->id); From e8ecf7c887fb43ae2c0977ee820e5217f8199650 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 7 Mar 2013 16:21:37 -0600 Subject: [PATCH 002/113] FS-4846 --resolve --- src/include/switch_core.h | 1 + src/switch_core.c | 10 ++++++++++ src/switch_loadable_module.c | 7 ++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3383b67bc0..78b3827aa9 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2396,6 +2396,7 @@ SWITCH_DECLARE(void) switch_cache_db_flush_handles(void); SWITCH_DECLARE(const char *) switch_core_banner(void); SWITCH_DECLARE(switch_bool_t) switch_core_session_in_thread(switch_core_session_t *session); SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number); +SWITCH_DECLARE(uint32_t) switch_default_rate(const char *name, uint32_t number); /*! \brief Add user registration diff --git a/src/switch_core.c b/src/switch_core.c index 2ead117121..60e133c730 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1720,6 +1720,16 @@ SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number) return 20; } +SWITCH_DECLARE(uint32_t) switch_default_rate(const char *name, uint32_t number) +{ + + if (!strcasecmp(name, "opus")) { + return 48000; + } + + return 8000; +} + static uint32_t d_30 = 30; static void switch_load_core_config(const char *file) diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 02a9e6792b..c1b37abbd1 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -2165,7 +2165,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ } if (orate == 0) { - orate = 8000; + orate = switch_default_rate(name, 0); } switch_copy_string(jbuf, prefs[j], sizeof(jbuf)); @@ -2176,7 +2176,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ } if (jrate == 0) { - jrate = 8000; + jrate = switch_default_rate(jname, 0); } if (!strcasecmp(name, jname) && ointerval == jinterval && orate == jrate) { @@ -2188,6 +2188,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ /* If no specific codec interval is requested opt for the default above all else because lots of stuff assumes it */ for (imp = codec_interface->implementations; imp; imp = imp->next) { uint32_t default_ptime = switch_default_ptime(imp->iananame, imp->ianacode); + uint32_t default_rate = switch_default_rate(imp->iananame, imp->ianacode); if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { @@ -2196,7 +2197,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ continue; } - if (((!rate && (uint32_t) imp->samples_per_second != 8000) || (rate && (uint32_t) imp->samples_per_second != rate))) { + if (((!rate && (uint32_t) imp->samples_per_second != default_rate) || (rate && (uint32_t) imp->samples_per_second != rate))) { continue; } From eee1755c4207637a2d02c9a7138f26d5d2cf7617 Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Thu, 7 Mar 2013 19:04:32 -0600 Subject: [PATCH 003/113] printf no bueno --- src/mod/applications/mod_conference/mod_conference.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 882d607661..95e4fcc978 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -4130,7 +4130,6 @@ static void conference_send_all_dtmf(conference_member_t *member, conference_obj switch_zmalloc(dt, sizeof(*dt)); *dt = digit; - printf("QQQQ %c\n", dt->digit); switch_queue_push(member->dtmf_queue, dt); switch_core_session_kill_channel(imember->session, SWITCH_SIG_BREAK); } From 3034de6e7977e794d401f9abad88156d2c5ef4e0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 8 Mar 2013 08:24:44 -0600 Subject: [PATCH 004/113] FS-5155 --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3be6ab2492..7b0a767350 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5177,7 +5177,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase); - if (status == 491 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) { + if (status == 491 && (sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)||switch_channel_test_flag(channel, CF_PROXY_MODE))) { nua_respond(other_tech_pvt->nh, SIP_491_REQUEST_PENDING, TAG_END()); switch_core_session_rwunlock(other_session); goto end; From 5f876497bcbe066e97d93a562a834231c093a29f Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 8 Mar 2013 15:15:07 -0500 Subject: [PATCH 005/113] freetdm: - Added ftdm_usage command to check if a channel has calls (ie, is busy) - Refactored ftdm CLI management to allow standalone APIs to be registered - Minor logging changes here and there --- libs/freetdm/mod_freetdm/mod_freetdm.c | 114 ++++++++++++++++++++----- libs/freetdm/src/ftdm_config.c | 2 +- libs/freetdm/src/ftdm_io.c | 1 + 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 2b0517dd79..a7346fdb2e 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -5187,36 +5187,96 @@ end: return SWITCH_STATUS_SUCCESS; } +SWITCH_STANDARD_API(ftdm_api_exec_usage) +{ + char *mycmd = NULL, *argv[10] = { 0 }; + int argc = 0; + uint32_t chan_id = 0; + ftdm_channel_t *chan = NULL; + ftdm_span_t *span = NULL; + uint32_t tokencnt = 0; + /*ftdm_cli_entry_t *entry = NULL;*/ + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (!argc) { + stream->write_function(stream, "-ERR invalid args\n"); + goto end; + } + + if (argc < 2) { + stream->write_function(stream, "-ERR invalid args\n"); + goto end; + } + + ftdm_span_find_by_name(argv[0], &span); + chan_id = atoi(argv[1]); + if (!span) { + stream->write_function(stream, "-ERR invalid span\n"); + goto end; + } + + if (chan_id <= 0) { + stream->write_function(stream, "-ERR invalid channel\n"); + goto end; + } + + if (chan_id > ftdm_span_get_chan_count(span)) { + stream->write_function(stream, "-ERR invalid channel\n"); + goto end; + } + + chan = ftdm_span_get_channel(span, chan_id); + if (!chan) { + stream->write_function(stream, "-ERR channel not configured\n"); + goto end; + } + + tokencnt = ftdm_channel_get_token_count(chan); + stream->write_function(stream, "%d", tokencnt); + +end: + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + struct ftdm_cli_entry { const char *name; const char *args; const char *complete; + const char *desc; ftdm_cli_function_t execute; + switch_api_function_t execute_api; }; static ftdm_cli_entry_t ftdm_cli_options[] = { - { "list", "", "", ftdm_cmd_list }, - { "start", "", "", ftdm_cmd_start_stop }, - { "stop", "", "", ftdm_cmd_start_stop }, - { "reset", " []", "", ftdm_cmd_reset }, - { "alarms", " ", "", ftdm_cmd_alarms }, - { "dump", " []", "", ftdm_cmd_dump }, - { "sigstatus", "get|set [] []", "::[set:get", ftdm_cmd_sigstatus }, - { "trace", " []", "", ftdm_cmd_trace }, - { "notrace", " []", "", ftdm_cmd_notrace }, - { "gains", " []", "", ftdm_cmd_gains }, - { "dtmf", "on|off []", "::[on:off", ftdm_cmd_dtmf }, - { "queuesize", " []", "", ftdm_cmd_queuesize }, - { "iostats", "enable|disable|flush|print ", "::[enable:disable:flush:print", ftdm_cmd_iostats }, - { "ioread", " [num_times] [interval]", "", ftdm_cmd_ioread }, + { "list", "", "", NULL, ftdm_cmd_list, NULL }, + { "start", "", "", NULL, ftdm_cmd_start_stop, NULL }, + { "stop", "", "", NULL, ftdm_cmd_start_stop, NULL }, + { "reset", " []", "", NULL, ftdm_cmd_reset, NULL }, + { "alarms", " ", "", NULL, ftdm_cmd_alarms, NULL }, + { "dump", " []", "", NULL, ftdm_cmd_dump, NULL }, + { "sigstatus", "get|set [] []", "::[set:get", NULL, ftdm_cmd_sigstatus, NULL }, + { "trace", " []", "", NULL, ftdm_cmd_trace, NULL }, + { "notrace", " []", "", NULL, ftdm_cmd_notrace, NULL }, + { "gains", " []", "", NULL, ftdm_cmd_gains, NULL }, + { "dtmf", "on|off []", "::[on:off", NULL, ftdm_cmd_dtmf, NULL }, + { "queuesize", " []", "", NULL, ftdm_cmd_queuesize, NULL }, + { "iostats", "enable|disable|flush|print ", "::[enable:disable:flush:print", NULL, ftdm_cmd_iostats, NULL }, + { "ioread", " [num_times] [interval]", "", NULL, ftdm_cmd_ioread, NULL }, + + /* Stand-alone commands (not part of the generic ftdm API */ + { "ftdm_usage", " ", "", "Return channel call count", NULL, ftdm_api_exec_usage }, /* Fake handlers as they are handled within freetdm library, * we should provide a way inside freetdm to query for completions from signaling modules */ - { "core state", "[!]", "", NULL }, - { "core flag", "[!] [] []", "", NULL }, - { "core spanflag", "[!] []", "", NULL }, - { "core calls", "", "", NULL }, + { "core state", "[!]", "", NULL, NULL, NULL }, + { "core flag", "[!] [] []", "", NULL, NULL, NULL }, + { "core spanflag", "[!] []", "", NULL, NULL, NULL }, + { "core calls", "", "", NULL, NULL, NULL }, }; static void print_usage(switch_stream_handle_t *stream, ftdm_cli_entry_t *cli) @@ -5233,12 +5293,15 @@ static void print_full_usage(switch_stream_handle_t *stream) stream->write_function(stream, "--------------------------------------------------------------------------------\n"); for (i = 0 ; i < ftdm_array_len(ftdm_cli_options); i++) { entry = &ftdm_cli_options[i]; + if (entry->execute_api) { + continue; + } stream->write_function(stream, "ftdm %s %s\n", entry->name, entry->args); } stream->write_function(stream, "--------------------------------------------------------------------------------\n"); } -SWITCH_STANDARD_API(ft_function) +SWITCH_STANDARD_API(ftdm_api_exec) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; @@ -5379,12 +5442,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load) freetdm_endpoint_interface->io_routines = &freetdm_io_routines; freetdm_endpoint_interface->state_handler = &freetdm_state_handlers; - SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ft_function, " "); + SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ftdm_api_exec, " "); for (i = 0 ; i < ftdm_array_len(ftdm_cli_options); i++) { char complete_cli[512]; entry = &ftdm_cli_options[i]; - snprintf(complete_cli, sizeof(complete_cli), "add ftdm %s %s", entry->name, entry->complete); - switch_console_set_complete(complete_cli); + if (entry->execute_api) { + /* This is a stand-alone API */ + SWITCH_ADD_API(commands_api_interface, entry->name, entry->desc, ftdm_api_exec_usage, entry->args); + snprintf(complete_cli, sizeof(complete_cli), "add %s %s", entry->name, entry->complete); + switch_console_set_complete(complete_cli); + } else { + snprintf(complete_cli, sizeof(complete_cli), "add ftdm %s %s", entry->name, entry->complete); + switch_console_set_complete(complete_cli); + } } SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE); diff --git a/libs/freetdm/src/ftdm_config.c b/libs/freetdm/src/ftdm_config.c index 42b93cd78e..1564a0424b 100644 --- a/libs/freetdm/src/ftdm_config.c +++ b/libs/freetdm/src/ftdm_config.c @@ -77,7 +77,7 @@ int ftdm_config_open_file(ftdm_config_t *cfg, const char *file_path) memset(cfg, 0, sizeof(*cfg)); cfg->lockto = -1; - ftdm_log(FTDM_LOG_DEBUG, "Configuration file is %s.\n", path); + ftdm_log(FTDM_LOG_DEBUG, "Configuration file is %s\n", path); f = fopen(path, "r"); if (!f) { diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1c1b4b9045..26ca79adea 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -5116,6 +5116,7 @@ static ftdm_status_t load_config(void) sprintf(chan_config.group_name, "__default"); if (!ftdm_config_open_file(&cfg, cfg_name)) { + ftdm_log(FTDM_LOG_ERROR, "Failed to open configuration file %s\n", cfg_name); return FTDM_FAIL; } From 7a29ef95860ea73a7b6e3a98e9bdf392a2c54bb6 Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Fri, 8 Mar 2013 14:59:19 -0600 Subject: [PATCH 006/113] update changelog Thanks to Niek Vlessert for assisting with this --- docs/ChangeLog | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/ChangeLog b/docs/ChangeLog index 6921a3133c..abf98ae50c 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -1,7 +1,30 @@ -freeswitch (1.2.5.2) - Maintenance release/bug fixes -freeswitch (1.2.5.1) - Maintenance release/bug fixes +freeswitch (1.2.7) + change fs_encode to support raw files to wav or to other raw + check for vm caller id info later so if its transfered it gets the updated details +freeswitch (1.2.6) + core_sqldb: sql tuning by changing 2 Indices + freeswitch-core: database corruption handling + freeswitch-core: use system time as reference for FS uptime, instead of monotonic + freeswitch-core: hide sensitive dtmfs + freeswitch-core: record g729 calls to g729 wav files, playback g729 wav files + freeswitch-core: STUN: XOR_MAPPED_ADDRESS attribute not handled + freeswitch-core: option to record session when bridged only + mod_callcenter: simple periodic announcement + mod_callcenter: New members joining queue don't ring agents when max-wait-time-with-no-agent-time-reached is 0 + mod_curl: add curl content-type option + mod_curl: adding ability to transmit a file using CURL from API or dialplan app + mod_directory: option to search by first and last name + mod_dptools: add option to allow any key to terminate playback or record + mod_event_socket: enable dual-stack (IPv4/IPv6) listening in mod_event_socket on Windows + mod_lcr: Add 'round-robin' feature to carrer gateways + mod_local_stream: add an event (or filter) for mod_localstream PLAYBACK_START and PLAYBACK_STOP + mod_nibblebill: fix mod_nibblebill to use pgsql in core + mod_sofia: pass User-to-User header to variable-space + mod_sofia: option for freeswitch to trust users authed by proxy + mod_spandsp: Spandsp directory for making modem links + mod_voicemail: added voicemail call paging + build: building works on Visual Studio 2012 + config: updating mod_cidlookup default configuration to use OpenCNAM as an example freeswitch (1.2.5) mod_lua: Enable mod_lua to use native pgsql dbh support (r:2cea7f0f) mod_sofia: Add att_xfer_destination_number variable to indicate the original destination number of the attended transfer leg on REFER for semi-attended transfer scenarios. (r:893cd7be) From 1d289b3617dafde2b02ae9128d565bff0a8bf064 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sat, 9 Mar 2013 22:19:47 +0800 Subject: [PATCH 007/113] Chnaged T.30 x-rex, y-res, width vetting to be more rigorous. Various little tweaks to spandsp --- libs/spandsp/src/ademco_contactid.c | 72 +++- libs/spandsp/src/adsi.c | 34 +- libs/spandsp/src/async.c | 122 +++--- libs/spandsp/src/dtmf.c | 26 +- libs/spandsp/src/fsk.c | 2 +- libs/spandsp/src/spandsp/async.h | 84 +++-- libs/spandsp/src/spandsp/dtmf.h | 8 +- libs/spandsp/src/spandsp/private/async.h | 6 +- libs/spandsp/src/spandsp/private/dtmf.h | 4 + .../spandsp/src/spandsp/private/t38_gateway.h | 4 + libs/spandsp/src/spandsp/private/v22bis.h | 4 +- libs/spandsp/src/spandsp/saturated.h | 14 +- libs/spandsp/src/spandsp/v18.h | 10 + libs/spandsp/src/spandsp/v42.h | 4 +- libs/spandsp/src/t30.c | 351 ++++++++++-------- libs/spandsp/src/v18.c | 66 ++-- libs/spandsp/src/v42.c | 6 +- 17 files changed, 498 insertions(+), 319 deletions(-) diff --git a/libs/spandsp/src/ademco_contactid.c b/libs/spandsp/src/ademco_contactid.c index 39ce670bde..6862567184 100644 --- a/libs/spandsp/src/ademco_contactid.c +++ b/libs/spandsp/src/ademco_contactid.c @@ -84,7 +84,7 @@ Receiver now waits Sender waits 250-300ms after end of 2300Hz tone -Send ACCT MT QXYZ GG CCC +Send ACCT MT QXYZ GG CCC S ACCT = 4 digit account code (0-9, B-F) MT = 2 digit message type (18 preferred, 98 optional) @@ -124,6 +124,74 @@ If kissoff doesn't start within 1.25s of the end of the DTMF, repeat the DTMF me Receiver sends 750-1000ms of 1400Hz as the kissoff tone Sender shall make 4 attempts before giving up. One successful kissoff resets the attempt counter + + +Ademco Express 4/1 + + ACCT MT C + +ACCT = 4 digit account code (0-9, B-F) +MT = 2 digit message type (17) +C = alarm code +S = 1 digit hex checksum + +Ademco Express 4/2 + + ACCT MT C Z S + +ACCT = 4 digit account code (0-9, B-F) +MT = 2 digit message type (27) +C = 1 digit alarm code +Z = 1 digit zone or user number +S = 1 digit hex checksum + +Ademco High speed + + ACCT MT PPPPPPPP X S + +ACCT = 4 digit account code (0-9, B-F) +MT = 2 digit message type (55) +PPPPPPPP = 8 digit status of each zone +X = 1 digit type of information in the PPPPPPPP field +S = 1 digit hex checksum + +Each P digit contains one of the following values: + 1 new alarm + 2 new opening + 3 new restore + 4 new closing + 5 normal + 6 outstanding +The X field contains one of the following values: + 0 AlarmNet messages + 1 ambush or duress + 2 opening by user (the first P field contains the user number) + 3 bypass (the P fields indicate which zones are bypassed) + 4 closing by user (the first P field contain the user number) + 5 trouble (the P fields contain which zones are in trouble) + 6 system trouble + 7 normal message (the P fields indicate zone status) + 8 low battery (the P fields indicate zone status) + 9 test (the P fields indicate zone status) + +Ademco Super fast + + ACCT MT PPPPPPPP X S + +ACCT = 4 digit account code (0-9, B-F) +MT = 2 digit message type (56) + +There are versions somewhat like the above, with 8, 16 or 24 'P' digits, +and no message type + ACCT PPPPPPPP X + ACCT PPPPPPPPPPPPPPPP X + ACCT PPPPPPPPPPPPPPPPPPPPPPPP X + +ACCT = 4 digit account code (0-9, B-F) +PPPPPPPP = 8, 16 or 24 digit status of each zone +X = 1 digit status of the communicator +S = 1 digit hex checksum + */ struct ademco_code_s @@ -1040,7 +1108,7 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade s->step = 0; s->remaining_samples = ms_to_samples(100); - dtmf_tx_init(&s->dtmf); + dtmf_tx_init(&s->dtmf, NULL, NULL); /* The specified timing is 50-60ms on, 50-60ms off */ dtmf_tx_set_timing(&s->dtmf, 55, 55); return s; diff --git a/libs/spandsp/src/adsi.c b/libs/spandsp/src/adsi.c index 54d4137682..647bf371ab 100644 --- a/libs/spandsp/src/adsi.c +++ b/libs/spandsp/src/adsi.c @@ -373,19 +373,19 @@ static void start_tx(adsi_tx_state_t *s) switch (s->standard) { case ADSI_STANDARD_CLASS: - fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_BELL202], adsi_tx_get_bit, s); + fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_BELL202], adsi_tx_get_bit, s); break; case ADSI_STANDARD_CLIP: case ADSI_STANDARD_ACLIP: case ADSI_STANDARD_JCLIP: - fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_V23CH1], adsi_tx_get_bit, s); + fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V23CH1], adsi_tx_get_bit, s); break; case ADSI_STANDARD_CLIP_DTMF: - dtmf_tx_init(&(s->dtmftx)); + dtmf_tx_init(&s->dtmftx, NULL, NULL); break; case ADSI_STANDARD_TDD: - fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx)); - async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, adsi_tdd_get_async_byte, s); + fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &s->asynctx); + async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, adsi_tdd_get_async_byte, s); /* Schedule an explicit shift at the start of baudot transmission */ s->baudot_shift = 2; break; @@ -403,10 +403,10 @@ SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len) s->in_progress -= len; if (s->in_progress <= 0) s->msg_len = 0; - dtmf_rx(&(s->dtmfrx), amp, len); + dtmf_rx(&s->dtmfrx, amp, len); break; default: - fsk_rx(&(s->fskrx), amp, len); + fsk_rx(&s->fskrx, amp, len); break; } return 0; @@ -435,20 +435,20 @@ SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s, switch (standard) { case ADSI_STANDARD_CLASS: - fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s); + fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s); break; case ADSI_STANDARD_CLIP: case ADSI_STANDARD_ACLIP: case ADSI_STANDARD_JCLIP: - fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_V23CH1], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s); + fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V23CH1], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s); break; case ADSI_STANDARD_CLIP_DTMF: - dtmf_rx_init(&(s->dtmfrx), adsi_rx_dtmf, s); + dtmf_rx_init(&s->dtmfrx, adsi_rx_dtmf, s); break; case ADSI_STANDARD_TDD: /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and ride over the fraction. */ - fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, adsi_tdd_put_async_byte, s); + fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, adsi_tdd_put_async_byte, s); break; } s->standard = standard; @@ -475,19 +475,19 @@ SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len) int len; int lenx; - len = tone_gen(&(s->alert_tone_gen), amp, max_len); + len = tone_gen(&s->alert_tone_gen, amp, max_len); if (s->tx_signal_on) { switch (s->standard) { case ADSI_STANDARD_CLIP_DTMF: if (len < max_len) - len += dtmf_tx(&(s->dtmftx), amp, max_len - len); + len += dtmf_tx(&s->dtmftx, amp, max_len - len); break; default: if (len < max_len) { - if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0) + if ((lenx = fsk_tx(&s->fsktx, amp + len, max_len - len)) <= 0) s->tx_signal_on = FALSE; len += lenx; } @@ -500,7 +500,7 @@ SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len) SPAN_DECLARE(void) adsi_tx_send_alert_tone(adsi_tx_state_t *s) { - tone_gen_init(&(s->alert_tone_gen), &(s->alert_tone_desc)); + tone_gen_init(&s->alert_tone_gen, &s->alert_tone_desc); } /*- End of function --------------------------------------------------------*/ @@ -583,7 +583,7 @@ SPAN_DECLARE(int) adsi_tx_put_message(adsi_tx_state_t *s, const uint8_t *msg, in case ADSI_STANDARD_CLIP_DTMF: if (len >= 128) return -1; - len -= (int) dtmf_tx_put(&(s->dtmftx), (char *) msg, len); + len -= (int) dtmf_tx_put(&s->dtmftx, (char *) msg, len); break; case ADSI_STANDARD_JCLIP: if (len > 128 - 9) @@ -662,7 +662,7 @@ SPAN_DECLARE(adsi_tx_state_t *) adsi_tx_init(adsi_tx_state_t *s, int standard) return NULL; } memset(s, 0, sizeof(*s)); - tone_gen_descriptor_init(&(s->alert_tone_desc), + tone_gen_descriptor_init(&s->alert_tone_desc, 2130, -13, 2750, diff --git a/libs/spandsp/src/async.c b/libs/spandsp/src/async.c index 1bfa65d910..49e25fde23 100644 --- a/libs/spandsp/src/async.c +++ b/libs/spandsp/src/async.c @@ -35,6 +35,7 @@ #include #include "spandsp/telephony.h" +#include "spandsp/bit_operations.h" #include "spandsp/async.h" #include "spandsp/private/async.h" @@ -75,55 +76,13 @@ SPAN_DECLARE(const char *) signal_status_to_str(int status) return "Link disconnected"; case SIG_STATUS_LINK_ERROR: return "Link error"; + case SIG_STATUS_LINK_IDLE: + return "Link idle"; } return "???"; } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s, - int data_bits, - int parity, - int stop_bits, - int use_v14, - put_byte_func_t put_byte, - void *user_data) -{ - if (s == NULL) - { - if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL) - return NULL; - } - s->data_bits = data_bits; - s->parity = parity; - s->stop_bits = stop_bits; - s->use_v14 = use_v14; - - s->put_byte = put_byte; - s->user_data = user_data; - - s->byte_in_progress = 0; - s->bitpos = 0; - s->parity_bit = 0; - - s->parity_errors = 0; - s->framing_errors = 0; - return s; -} -/*- End of function --------------------------------------------------------*/ - -SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s) -{ - return 0; -} -/*- End of function --------------------------------------------------------*/ - -SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s) -{ - free(s); - return 0; -} -/*- End of function --------------------------------------------------------*/ - SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit) { async_rx_state_t *s; @@ -205,45 +164,44 @@ SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s, +SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s, int data_bits, int parity, int stop_bits, int use_v14, - get_byte_func_t get_byte, + put_byte_func_t put_byte, void *user_data) { if (s == NULL) { - if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL) + if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL) return NULL; } - /* We have a use_v14 parameter for completeness, but right now V.14 only - applies to the receive side. We are unlikely to have an application where - flow control does not exist, so V.14 stuffing is not needed. */ s->data_bits = data_bits; s->parity = parity; s->stop_bits = stop_bits; - if (parity != ASYNC_PARITY_NONE) - s->stop_bits++; - - s->get_byte = get_byte; + s->use_v14 = use_v14; + + s->put_byte = put_byte; s->user_data = user_data; s->byte_in_progress = 0; s->bitpos = 0; s->parity_bit = 0; + + s->parity_errors = 0; + s->framing_errors = 0; return s; } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s) +SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s) { return 0; } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s) +SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s) { free(s); return 0; @@ -295,4 +253,56 @@ SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data) return bit; } /*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(void) async_tx_presend_bits(async_tx_state_t *s, int bits) +{ + s->presend_bits = bits; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s, + int data_bits, + int parity, + int stop_bits, + int use_v14, + get_byte_func_t get_byte, + void *user_data) +{ + if (s == NULL) + { + if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL) + return NULL; + } + /* We have a use_v14 parameter for completeness, but right now V.14 only + applies to the receive side. We are unlikely to have an application where + flow control does not exist, so V.14 stuffing is not needed. */ + s->data_bits = data_bits; + s->parity = parity; + s->stop_bits = stop_bits; + if (parity != ASYNC_PARITY_NONE) + s->stop_bits++; + + s->get_byte = get_byte; + s->user_data = user_data; + + s->byte_in_progress = 0; + s->bitpos = 0; + s->parity_bit = 0; + s->presend_bits = 0; + return s; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s) +{ + return 0; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/dtmf.c b/libs/spandsp/src/dtmf.c index ee61f0095c..196e3d3eca 100644 --- a/libs/spandsp/src/dtmf.c +++ b/libs/spandsp/src/dtmf.c @@ -508,21 +508,31 @@ SPAN_DECLARE(int) dtmf_tx(dtmf_tx_state_t *s, int16_t amp[], int max_samples) if (s->tones.current_section >= 0) { /* Deal with the fragment left over from last time */ - len = tone_gen(&(s->tones), amp, max_samples); + len = tone_gen(&s->tones, amp, max_samples); } - while (len < max_samples && (digit = queue_read_byte(&s->queue.queue)) >= 0) + + while (len < max_samples) { /* Step to the next digit */ + if ((digit = queue_read_byte(&s->queue.queue)) < 0) + { + /* See if we can get some more digits */ + if (s->callback == NULL) + break; + s->callback(s->callback_data); + if ((digit = queue_read_byte(&s->queue.queue)) < 0) + break; + } if (digit == 0) continue; if ((cp = strchr(dtmf_positions, digit)) == NULL) continue; - tone_gen_init(&(s->tones), &dtmf_digit_tones[cp - dtmf_positions]); + tone_gen_init(&s->tones, &dtmf_digit_tones[cp - dtmf_positions]); s->tones.tone[0].gain = s->low_level; s->tones.tone[1].gain = s->high_level; s->tones.duration[0] = s->on_time; s->tones.duration[1] = s->off_time; - len += tone_gen(&(s->tones), amp + len, max_samples - len); + len += tone_gen(&s->tones, amp + len, max_samples - len); } return len; } @@ -562,7 +572,9 @@ SPAN_DECLARE(void) dtmf_tx_set_timing(dtmf_tx_state_t *s, int on_time, int off_t } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s) +SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s, + digits_tx_callback_t callback, + void *user_data) { if (s == NULL) { @@ -572,7 +584,9 @@ SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s) memset(s, 0, sizeof(*s)); if (!dtmf_tx_inited) dtmf_tx_initialise(); - tone_gen_init(&(s->tones), &dtmf_digit_tones[0]); + s->callback = callback; + s->callback_data = user_data; + tone_gen_init(&s->tones, &dtmf_digit_tones[0]); dtmf_tx_set_level(s, DEFAULT_DTMF_TX_LEVEL, 0); dtmf_tx_set_timing(s, -1, -1); queue_init(&s->queue.queue, MAX_DTMF_DIGITS, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC); diff --git a/libs/spandsp/src/fsk.c b/libs/spandsp/src/fsk.c index 3f53aa7bc8..d95f757468 100644 --- a/libs/spandsp/src/fsk.c +++ b/libs/spandsp/src/fsk.c @@ -117,7 +117,7 @@ const fsk_spec_t preset_fsk_specs[] = 4545 }, { - "Weitbrecht 50", /* Used for Internatioal TDD (Telecoms Device for the Deaf) */ + "Weitbrecht 50", /* Used for international TDD (Telecoms Device for the Deaf) */ 1600 + 200, 1600 - 200, -14, diff --git a/libs/spandsp/src/spandsp/async.h b/libs/spandsp/src/spandsp/async.h index 8d643dd720..1b22cd5caf 100644 --- a/libs/spandsp/src/spandsp/async.h +++ b/libs/spandsp/src/spandsp/async.h @@ -86,7 +86,9 @@ enum /*! \brief The link protocol (e.g. V.42) has disconnected. */ SIG_STATUS_LINK_DISCONNECTED = -15, /*! \brief An error has occurred in the link protocol (e.g. V.42). */ - SIG_STATUS_LINK_ERROR = -16 + SIG_STATUS_LINK_ERROR = -16, + /*! \brief Keep the link in an idle state, as there is nothing to send. */ + SIG_STATUS_LINK_IDLE = -17 }; /*! Message put function for data pumps */ @@ -145,33 +147,16 @@ extern "C" \return A pointer to the description. */ SPAN_DECLARE(const char *) signal_status_to_str(int status); -/*! Initialise an asynchronous data transmit context. - \brief Initialise an asynchronous data transmit context. - \param s The transmitter context. - \param data_bits The number of data bit. - \param parity_bits The type of parity. - \param stop_bits The number of stop bits. - \param use_v14 TRUE if V.14 rate adaption processing should be used. - \param get_byte The callback routine used to get the data to be transmitted. - \param user_data An opaque pointer. - \return A pointer to the initialised context, or NULL if there was a problem. */ -SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s, - int data_bits, - int parity_bits, - int stop_bits, - int use_v14, - get_byte_func_t get_byte, - void *user_data); - -SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s); - -SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s); - -/*! Get the next bit of a transmitted serial bit stream. - \brief Get the next bit of a transmitted serial bit stream. - \param user_data An opaque point which must point to a transmitter context. - \return the next bit, or PUTBIT_END_OF_DATA to indicate the data stream has ended. */ -SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data); +/*! Accept a bit from a received serial bit stream + \brief Accept a bit from a received serial bit stream + \param user_data An opaque point which must point to a receiver context. + \param bit The new bit. Some special values are supported for this field. + - SIG_STATUS_CARRIER_UP + - SIG_STATUS_CARRIER_DOWN + - SIG_STATUS_TRAINING_SUCCEEDED + - SIG_STATUS_TRAINING_FAILED + - SIG_STATUS_END_OF_DATA */ +SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit); /*! Initialise an asynchronous data receiver context. \brief Initialise an asynchronous data receiver context. @@ -195,16 +180,39 @@ SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s); SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s); -/*! Accept a bit from a received serial bit stream - \brief Accept a bit from a received serial bit stream - \param user_data An opaque point which must point to a receiver context. - \param bit The new bit. Some special values are supported for this field. - - SIG_STATUS_CARRIER_UP - - SIG_STATUS_CARRIER_DOWN - - SIG_STATUS_TRAINING_SUCCEEDED - - SIG_STATUS_TRAINING_FAILED - - SIG_STATUS_END_OF_DATA */ -SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit); +/*! Set a minimum number of bit times of stop bit state before character transmission commences. + \brief Set a minimum number of bit times of stop bit state before character transmission commences. + \param user_data An opaque point which must point to a transmitter context. + \param the number of bits. */ +SPAN_DECLARE(void) async_tx_presend_bits(async_tx_state_t *s, int bits); + +/*! Get the next bit of a transmitted serial bit stream. + \brief Get the next bit of a transmitted serial bit stream. + \param user_data An opaque point which must point to a transmitter context. + \return the next bit, or PUTBIT_END_OF_DATA to indicate the data stream has ended. */ +SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data); + +/*! Initialise an asynchronous data transmit context. + \brief Initialise an asynchronous data transmit context. + \param s The transmitter context. + \param data_bits The number of data bit. + \param parity_bits The type of parity. + \param stop_bits The number of stop bits. + \param use_v14 TRUE if V.14 rate adaption processing should be used. + \param get_byte The callback routine used to get the data to be transmitted. + \param user_data An opaque pointer. + \return A pointer to the initialised context, or NULL if there was a problem. */ +SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s, + int data_bits, + int parity_bits, + int stop_bits, + int use_v14, + get_byte_func_t get_byte, + void *user_data); + +SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s); + +SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s); #if defined(__cplusplus) } diff --git a/libs/spandsp/src/spandsp/dtmf.h b/libs/spandsp/src/spandsp/dtmf.h index a9aeb64ef9..58ea779088 100644 --- a/libs/spandsp/src/spandsp/dtmf.h +++ b/libs/spandsp/src/spandsp/dtmf.h @@ -74,6 +74,7 @@ repertoire of 16 DTMF dual tones. #define MAX_DTMF_DIGITS 128 typedef void (*digits_rx_callback_t)(void *user_data, const char *digits, int len); +typedef void (*digits_tx_callback_t)(void *user_data); /*! DTMF generator state descriptor. This defines the state of a single @@ -122,8 +123,13 @@ SPAN_DECLARE(void) dtmf_tx_set_timing(dtmf_tx_state_t *s, int on_time, int off_t /*! \brief Initialise a DTMF tone generator context. \param s The DTMF generator context. + \param callback An optional callback routine, used to get more digits. + \param user_data An opaque pointer which is associated with the context, + and supplied in callbacks. \return A pointer to the DTMF generator context. */ -SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s); +SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s, + digits_tx_callback_t callback, + void *user_data); /*! \brief Release a DTMF tone generator context. \param s The DTMF tone generator context. diff --git a/libs/spandsp/src/spandsp/private/async.h b/libs/spandsp/src/spandsp/private/async.h index 715d659d9e..7354aaf967 100644 --- a/libs/spandsp/src/spandsp/private/async.h +++ b/libs/spandsp/src/spandsp/private/async.h @@ -43,9 +43,11 @@ struct async_tx_state_s get_byte_func_t get_byte; /*! \brief An opaque pointer passed when calling get_byte. */ void *user_data; + /*! \brief The minimum number of stop bits to send before character transmission begins. */ + int presend_bits; /*! \brief A current, partially transmitted, character. */ - unsigned int byte_in_progress; + int32_t byte_in_progress; /*! \brief The current bit position within a partially transmitted character. */ int bitpos; /*! \brief Parity bit. */ @@ -73,7 +75,7 @@ struct async_rx_state_s void *user_data; /*! \brief A current, partially complete, character. */ - unsigned int byte_in_progress; + int32_t byte_in_progress; /*! \brief The current bit position within a partially complete character. */ int bitpos; /*! \brief Parity bit. */ diff --git a/libs/spandsp/src/spandsp/private/dtmf.h b/libs/spandsp/src/spandsp/private/dtmf.h index e063470d78..eae20ad4d5 100644 --- a/libs/spandsp/src/spandsp/private/dtmf.h +++ b/libs/spandsp/src/spandsp/private/dtmf.h @@ -32,6 +32,10 @@ */ struct dtmf_tx_state_s { + /*! Optional callback funcion to get more digits. */ + digits_tx_callback_t callback; + /*! An opaque pointer passed to the callback function. */ + void *callback_data; tone_gen_state_t tones; float low_level; float high_level; diff --git a/libs/spandsp/src/spandsp/private/t38_gateway.h b/libs/spandsp/src/spandsp/private/t38_gateway.h index 075a9b221c..e8e74c2af9 100644 --- a/libs/spandsp/src/spandsp/private/t38_gateway.h +++ b/libs/spandsp/src/spandsp/private/t38_gateway.h @@ -66,6 +66,10 @@ typedef struct { /*! \brief The FAX modem set for the audio side fo the gateway. */ fax_modems_state_t modems; + /*! \brief CED detector */ + modem_connect_tones_rx_state_t connect_rx_ced; + /*! \brief CNG detector */ + modem_connect_tones_rx_state_t connect_rx_cng; } t38_gateway_audio_state_t; /*! diff --git a/libs/spandsp/src/spandsp/private/v22bis.h b/libs/spandsp/src/spandsp/private/v22bis.h index b601b0c02d..5a03cb79f8 100644 --- a/libs/spandsp/src/spandsp/private/v22bis.h +++ b/libs/spandsp/src/spandsp/private/v22bis.h @@ -138,7 +138,7 @@ struct v22bis_state_s int constellation_state; #if defined(SPANDSP_USE_FIXED_POINT) - /*! \brief The scaling factor accessed by the AGC algorithm. */ + /*! \brief The scaling factor assessed by the AGC algorithm. */ int16_t agc_scaling; /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ int16_t rrc_filter[V22BIS_RX_FILTER_STEPS]; @@ -158,7 +158,7 @@ struct v22bis_state_s /*! \brief The integral part of the carrier tracking filter. */ int32_t carrier_track_i; #else - /*! \brief The scaling factor accessed by the AGC algorithm. */ + /*! \brief The scaling factor assessed by the AGC algorithm. */ float agc_scaling; /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ float rrc_filter[V22BIS_RX_FILTER_STEPS]; diff --git a/libs/spandsp/src/spandsp/saturated.h b/libs/spandsp/src/spandsp/saturated.h index 8c159fee3a..fcefbe96ab 100644 --- a/libs/spandsp/src/spandsp/saturated.h +++ b/libs/spandsp/src/spandsp/saturated.h @@ -363,16 +363,24 @@ static __inline__ int32_t saturated_sub32(int32_t a, int32_t b) static __inline__ int16_t saturated_mul16(int16_t a, int16_t b) { - if (a == INT16_MIN && b == INT16_MIN) + int32_t product; + + product = (int32_t) a*b; + if (product == 0x40000000) return INT16_MAX; /*endif*/ - return (int16_t) (((int32_t) a*(int32_t) b) >> 15); + return product >> 15; } /*- End of function --------------------------------------------------------*/ static __inline__ int32_t saturated_mul16_32(int16_t a, int16_t b) { - return ((int32_t) a*(int32_t) b) << 1; + int32_t product; + + product = (int32_t) a*b; + if (product == 0x40000000) + return INT32_MAX; + return product << 1; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/v18.h b/libs/spandsp/src/spandsp/v18.h index bc73c7e619..08219ec0be 100644 --- a/libs/spandsp/src/spandsp/v18.h +++ b/libs/spandsp/src/spandsp/v18.h @@ -140,9 +140,19 @@ SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t amp[], int max_len); \param s The V.18 context. \param amp The audio sample buffer. \param len The number of samples in the buffer. + \return The number of unprocessed samples. */ SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len); +/*! Fake processing of a missing block of received V.18 audio samples. + (e.g due to packet loss). + \brief Fake processing of a missing block of received V.18 audio samples. + \param s The V.18 context. + \param len The number of samples to fake. + \return The number of unprocessed samples. +*/ +SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len); + /*! \brief Put a string to a V.18 context's input buffer. \param s The V.18 context. \param msg The string to be added. diff --git a/libs/spandsp/src/spandsp/v42.h b/libs/spandsp/src/spandsp/v42.h index bdd34e86f1..5ab26262dd 100644 --- a/libs/spandsp/src/spandsp/v42.h +++ b/libs/spandsp/src/spandsp/v42.h @@ -100,12 +100,12 @@ SPAN_DECLARE(void) v42_restart(v42_state_t *s); /*! Release a V.42 context. \param s The V.42 context. \return 0 if OK */ -SPAN_DECLARE(void) v42_release(v42_state_t *s); +SPAN_DECLARE(int) v42_release(v42_state_t *s); /*! Free a V.42 context. \param s The V.42 context. \return 0 if OK */ -SPAN_DECLARE(void) v42_free(v42_state_t *s); +SPAN_DECLARE(int) v42_free(v42_state_t *s); #if defined(__cplusplus) } diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 38f160d7ff..5c495dbb81 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -1406,7 +1406,7 @@ static int build_dcs(t30_state_t *s) /* We have a file to send, so tell the far end to go into receive mode. */ set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT); /* Set the Y resolution bits */ - bad = T30_ERR_OK; + bad = T30_ERR_NORESSUPPORT; row_squashing_ratio = 1; switch (s->y_resolution) { @@ -1414,19 +1414,18 @@ static int build_dcs(t30_state_t *s) switch (s->x_resolution) { case T4_X_RESOLUTION_600: - if (!(s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION)) - bad = T30_ERR_NORESSUPPORT; - else + if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE)) + { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200); + bad = T30_ERR_OK; + } break; case T4_X_RESOLUTION_1200: - if (!(s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION)) - bad = T30_ERR_NORESSUPPORT; - else + if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE)) + { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200); - break; - default: - bad = T30_ERR_NORESSUPPORT; + bad = T30_ERR_OK; + } break; } break; @@ -1434,13 +1433,11 @@ static int build_dcs(t30_state_t *s) switch (s->x_resolution) { case T4_X_RESOLUTION_R16: - if (!(s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION)) - bad = T30_ERR_NORESSUPPORT; - else + if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE)) + { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800); - break; - default: - bad = T30_ERR_NORESSUPPORT; + bad = T30_ERR_OK; + } break; } break; @@ -1448,19 +1445,18 @@ static int build_dcs(t30_state_t *s) switch (s->x_resolution) { case T4_X_RESOLUTION_300: - if (!(s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION)) - bad = T30_ERR_NORESSUPPORT; - else + if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE)) + { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600); + bad = T30_ERR_OK; + } break; case T4_X_RESOLUTION_600: - if (!(s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION)) - bad = T30_ERR_NORESSUPPORT; - else + if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE)) + { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600); - break; - default: - bad = T30_ERR_NORESSUPPORT; + bad = T30_ERR_OK; + } break; } break; @@ -1468,45 +1464,40 @@ static int build_dcs(t30_state_t *s) switch (s->x_resolution) { case T4_X_RESOLUTION_300: - if (!(s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION)) - bad = T30_ERR_NORESSUPPORT; - else + if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE)) + { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300); - break; - default: - bad = T30_ERR_NORESSUPPORT; + bad = T30_ERR_OK; + } break; } break; case T4_Y_RESOLUTION_SUPERFINE: if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION)) { - switch (s->x_resolution) + if (s->x_resolution == T4_X_RESOLUTION_R16 && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE)) { - case T4_X_RESOLUTION_R8: - set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400); - break; - case T4_X_RESOLUTION_R16: set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400); - break; - default: - bad = T30_ERR_NORESSUPPORT; + bad = T30_ERR_OK; + break; + } + if (s->x_resolution == T4_X_RESOLUTION_R8 && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE)) + { + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400); + bad = T30_ERR_OK; break; } - break; } row_squashing_ratio <<= 1; /* Fall through */ case T4_Y_RESOLUTION_FINE: - if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION)) + if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE)) { switch (s->x_resolution) { case T4_X_RESOLUTION_R8: set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200); - break; - default: - bad = T30_ERR_NORESSUPPORT; + bad = T30_ERR_OK; break; } break; @@ -1519,9 +1510,7 @@ static int build_dcs(t30_state_t *s) { case T4_X_RESOLUTION_R8: /* No bits to set for this */ - break; - default: - bad = T30_ERR_NORESSUPPORT; + bad = T30_ERR_OK; break; } break; @@ -1533,97 +1522,89 @@ static int build_dcs(t30_state_t *s) span_log(&s->logging, SPAN_LOG_FLOW, "Image resolution (%d x %d) not acceptable\n", s->x_resolution, s->y_resolution); return -1; } - /* Deal with the image width. The X resolution will fall in line with any valid width. */ + + /* Deal with the image width. */ /* Low (R4) res widths are not supported in recent versions of T.30 */ bad = T30_ERR_OK; /* The following treats a width field of 11 like 10, which does what note 6 of Table 2/T.30 says we should do with the invalid value 11. */ - switch (s->image_width) + if (((s->image_width == T4_WIDTH_R8_A4) && (s->x_resolution == T4_X_RESOLUTION_R8)) + || + ((s->image_width == T4_WIDTH_300_A4) && (s->x_resolution == T4_X_RESOLUTION_300)) + || + ((s->image_width == T4_WIDTH_R16_A4) && (s->x_resolution == T4_X_RESOLUTION_R16)) + || + ((s->image_width == T4_WIDTH_600_A4) && (s->x_resolution == T4_X_RESOLUTION_600)) + || + ((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200))) { - case T4_WIDTH_R8_A4: - case T4_WIDTH_300_A4: - case T4_WIDTH_R16_A4: - case T4_WIDTH_600_A4: - case T4_WIDTH_1200_A4: + span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 0x%x 0x%x\n", s->image_width, s->x_resolution); /* No width related bits need to be set. */ - break; - case T4_WIDTH_R8_B4: - case T4_WIDTH_300_B4: - case T4_WIDTH_R16_B4: - case T4_WIDTH_600_B4: - case T4_WIDTH_1200_B4: - if ((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) < 1) - bad = T30_ERR_NOSIZESUPPORT; - else if (!(s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH)) - bad = T30_ERR_NOSIZESUPPORT; - else + } + else if (((s->image_width == T4_WIDTH_R8_B4) && (s->x_resolution == T4_X_RESOLUTION_R8)) + || + ((s->image_width == T4_WIDTH_300_B4) && (s->x_resolution == T4_X_RESOLUTION_300)) + || + ((s->image_width == T4_WIDTH_R16_B4) && (s->x_resolution == T4_X_RESOLUTION_R16)) + || + ((s->image_width == T4_WIDTH_600_B4) && (s->x_resolution == T4_X_RESOLUTION_600)) + || + ((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200))) + { + if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 1) + && + (s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH)) + { + span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4\n"); set_ctrl_bit(s->dcs_frame, 17); - break; - case T4_WIDTH_R8_A3: - case T4_WIDTH_300_A3: - case T4_WIDTH_R16_A3: - case T4_WIDTH_600_A3: - case T4_WIDTH_1200_A3: - if ((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) < 2) - bad = T30_ERR_NOSIZESUPPORT; - else if (!(s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH)) - bad = T30_ERR_NOSIZESUPPORT; + } else + { + /* We do not support this width and resolution combination */ + bad = T30_ERR_NOSIZESUPPORT; + } + } + else if (((s->image_width == T4_WIDTH_R8_A3) && (s->x_resolution == T4_X_RESOLUTION_R8)) + || + ((s->image_width == T4_WIDTH_300_A3) && (s->x_resolution == T4_X_RESOLUTION_300)) + || + ((s->image_width == T4_WIDTH_R16_A3) && (s->x_resolution == T4_X_RESOLUTION_R16)) + || + ((s->image_width == T4_WIDTH_600_A3) && (s->x_resolution == T4_X_RESOLUTION_600)) + || + ((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200))) + { + if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 2) + && + (s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH)) + { + span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3\n"); set_ctrl_bit(s->dcs_frame, 18); - break; - default: - /* T.30 does not support this width */ - bad = T30_ERR_NOSIZESUPPORT; - break; + } + else + { + /* We do not support this width and resolution combination */ + bad = T30_ERR_NOSIZESUPPORT; + } } + else + { + /* We do not support this width and resolution combination */ + bad = T30_ERR_NOSIZESUPPORT; + } + if (bad != T30_ERR_OK) { t30_set_status(s, bad); - span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width); - return -1; - } - switch (s->image_width) - { - case T4_WIDTH_R8_A4: - case T4_WIDTH_R8_B4: - case T4_WIDTH_R8_A3: - /* These are always OK */ - break; - case T4_WIDTH_300_A4: - case T4_WIDTH_300_B4: - case T4_WIDTH_300_A3: - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE) && !test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE)) - bad = T30_ERR_NOSIZESUPPORT; - break; - case T4_WIDTH_R16_A4: - case T4_WIDTH_R16_B4: - case T4_WIDTH_R16_A3: - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE)) - bad = T30_ERR_NOSIZESUPPORT; - break; - case T4_WIDTH_600_A4: - case T4_WIDTH_600_B4: - case T4_WIDTH_600_A3: - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE) && !test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE)) - bad = T30_ERR_NOSIZESUPPORT; - break; - case T4_WIDTH_1200_A4: - case T4_WIDTH_1200_B4: - case T4_WIDTH_1200_A3: - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE)) - bad = T30_ERR_NOSIZESUPPORT; - break; - default: - /* T.30 does not support this width */ - bad = T30_ERR_NOSIZESUPPORT; - break; - } - if (bad != T30_ERR_OK) - { - t30_set_status(s, bad); - span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width); + span_log(&s->logging, + SPAN_LOG_FLOW, + "Image width (%d pixels) and resolution (%d x %d) is not an acceptable\n", + s->image_width, + s->x_resolution, + s->y_resolution); return -1; } + /* Deal with the image length */ /* If the other end supports unlimited length, then use that. Otherwise, if the other end supports B4 use that, as its longer than the default A4 length. */ @@ -2004,6 +1985,7 @@ static int start_sending_document(t30_state_t *s) if (tx_start_page(s)) return -1; + s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx); s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx); s->image_width = t4_tx_get_image_width(&s->t4.tx); @@ -2337,6 +2319,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) }; uint8_t dcs_frame[T30_MAX_DIS_DTC_DCS_LEN]; int i; + int x; int new_status; t30_decode_dis_dtc_dcs(s, msg, len); @@ -2368,46 +2351,104 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) s->octets_per_ecm_frame = test_ctrl_bit(dcs_frame, T30_DCS_BIT_64_OCTET_ECM_FRAMES) ? 256 : 64; + s->x_resolution = -1; + s->y_resolution = -1; + x = -1; if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200)) - s->x_resolution = T4_X_RESOLUTION_1200; - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200)) - s->x_resolution = T4_X_RESOLUTION_600; - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800)) - s->x_resolution = T4_X_RESOLUTION_R16; - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600)) - s->x_resolution = T4_X_RESOLUTION_300; - else - s->x_resolution = T4_X_RESOLUTION_R8; - - if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200)) - s->y_resolution = T4_Y_RESOLUTION_1200; + { + if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_1200; + s->y_resolution = T4_Y_RESOLUTION_1200; + x = 5; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200)) + { + if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_600; + s->y_resolution = T4_Y_RESOLUTION_1200; + x = 4; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600)) + { + if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_600; + s->y_resolution = T4_Y_RESOLUTION_600; + x = 4; + } + } else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800)) - s->y_resolution = T4_Y_RESOLUTION_800; - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600)) - s->y_resolution = T4_Y_RESOLUTION_600; - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400)) - s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; + { + if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_R16; + s->y_resolution = T4_Y_RESOLUTION_800; + x = 3; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400)) + { + if ((s->supported_resolutions & T30_SUPPORT_400_400_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_R16; + s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; + x = 3; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600)) + { + if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_300; + s->y_resolution = T4_Y_RESOLUTION_600; + x = 2; + } + } else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300)) - s->y_resolution = T4_Y_RESOLUTION_300; + { + if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_300; + s->y_resolution = T4_Y_RESOLUTION_300; + x = 2; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400)) + { + if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_R8; + s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; + x = 1; + } + } else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200)) - s->y_resolution = T4_Y_RESOLUTION_FINE; + { + if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_R8; + s->y_resolution = T4_Y_RESOLUTION_FINE; + x = 1; + } + } else + { + s->x_resolution = T4_X_RESOLUTION_R8; s->y_resolution = T4_Y_RESOLUTION_STANDARD; + x = 1; + } - if (s->x_resolution == T4_X_RESOLUTION_1200) - i = 5; - else if (s->x_resolution == T4_X_RESOLUTION_600) - i = 4; - else if (s->x_resolution == T4_X_RESOLUTION_R16) - i = 3; - else if (s->x_resolution == T4_X_RESOLUTION_300) - i = 2; - else if (s->x_resolution == T4_X_RESOLUTION_R4) - i = 0; - else - i = 1; + if (x < 0) + { + t30_set_status(s, T30_ERR_NORESSUPPORT); + return -1; + } - s->image_width = widths[i][dcs_frame[5] & (DISBIT2 | DISBIT1)]; + s->image_width = widths[x][dcs_frame[5] & (DISBIT2 | DISBIT1)]; /* Check which compression the far end has decided to use. */ #if defined(SPANDSP_SUPPORT_T42) diff --git a/libs/spandsp/src/v18.c b/libs/spandsp/src/v18.c index 639ae0770c..e1cfdc005a 100644 --- a/libs/spandsp/src/v18.c +++ b/libs/spandsp/src/v18.c @@ -387,9 +387,9 @@ static int cmp(const void *s, const void *t) SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[]) { const char *t; - char *u; const char *v; - + char *u; + t = msg; u = dtmf; while (*t) @@ -685,7 +685,8 @@ static void v18_tdd_put_async_byte(void *user_data, int byte) { /* Whatever we have to date constitutes the message */ s->rx_msg[s->rx_msg_len] = '\0'; - s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len); + if (s->put_msg) + s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len); s->rx_msg_len = 0; } break; @@ -701,7 +702,8 @@ static void v18_tdd_put_async_byte(void *user_data, int byte) if (s->rx_msg_len >= 256) { s->rx_msg[s->rx_msg_len] = '\0'; - s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len); + if (s->put_msg) + s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len); s->rx_msg_len = 0; } } @@ -815,6 +817,33 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(const char *) v18_mode_to_str(int mode) +{ + switch (mode & 0xFF) + { + case V18_MODE_NONE: + return "None"; + case V18_MODE_5BIT_45: + return "Weitbrecht TDD (45.45bps)"; + case V18_MODE_5BIT_50: + return "Weitbrecht TDD (50bps)"; + case V18_MODE_DTMF: + return "DTMF"; + case V18_MODE_EDT: + return "EDT"; + case V18_MODE_BELL103: + return "Bell 103"; + case V18_MODE_V23VIDEOTEX: + return "Videotex"; + case V18_MODE_V21TEXTPHONE: + return "V.21"; + case V18_MODE_V18TEXTPHONE: + return "V.18 text telephone"; + } + return "???"; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s) { return &s->logging; @@ -863,7 +892,7 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s, s->repeat_shifts = mode & 0x100; break; case V18_MODE_DTMF: - dtmf_tx_init(&s->dtmftx); + dtmf_tx_init(&s->dtmftx, NULL, NULL); dtmf_rx_init(&s->dtmfrx, v18_rx_dtmf, s); break; case V18_MODE_EDT: @@ -909,31 +938,4 @@ SPAN_DECLARE(int) v18_free(v18_state_t *s) return 0; } /*- End of function --------------------------------------------------------*/ - -SPAN_DECLARE(const char *) v18_mode_to_str(int mode) -{ - switch (mode & 0xFF) - { - case V18_MODE_NONE: - return "None"; - case V18_MODE_5BIT_45: - return "Weitbrecht TDD (45.45bps)"; - case V18_MODE_5BIT_50: - return "Weitbrecht TDD (50bps)"; - case V18_MODE_DTMF: - return "DTMF"; - case V18_MODE_EDT: - return "EDT"; - case V18_MODE_BELL103: - return "Bell 103"; - case V18_MODE_V23VIDEOTEX: - return "Videotex"; - case V18_MODE_V21TEXTPHONE: - return "V.21"; - case V18_MODE_V18TEXTPHONE: - return "V.18 text telephone"; - } - return "???"; -} -/*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/v42.c b/libs/spandsp/src/v42.c index eec5a87099..3e73d67c27 100644 --- a/libs/spandsp/src/v42.c +++ b/libs/spandsp/src/v42.c @@ -1554,16 +1554,18 @@ SPAN_DECLARE(v42_state_t *) v42_init(v42_state_t *ss, } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) v42_release(v42_state_t *s) +SPAN_DECLARE(int) v42_release(v42_state_t *s) { reset_lapm(s); + return 0; } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) v42_free(v42_state_t *s) +SPAN_DECLARE(int) v42_free(v42_state_t *s) { v42_release(s); free(s); + return 0; } /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ From e9425718762b4c4e38ba86a3d2483d34bf1b454d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 9 Mar 2013 07:58:09 -0600 Subject: [PATCH 008/113] FS-5160 --resolve This is depricated in favor of {loops=10}tone_stream://path=/foo/bar.ttml adding legacy code to let both ways work --- conf/vanilla/dialplan/default.xml | 4 ++-- src/mod/formats/mod_tone_stream/mod_tone_stream.c | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/conf/vanilla/dialplan/default.xml b/conf/vanilla/dialplan/default.xml index 7f5002152f..72b9431a40 100644 --- a/conf/vanilla/dialplan/default.xml +++ b/conf/vanilla/dialplan/default.xml @@ -695,14 +695,14 @@ - + - + diff --git a/src/mod/formats/mod_tone_stream/mod_tone_stream.c b/src/mod/formats/mod_tone_stream/mod_tone_stream.c index fe3080f4c5..bf373f4162 100644 --- a/src/mod/formats/mod_tone_stream/mod_tone_stream.c +++ b/src/mod/formats/mod_tone_stream/mod_tone_stream.c @@ -136,6 +136,15 @@ static switch_status_t tone_stream_file_open(switch_file_handle_t *handle, const switch_buffer_create_dynamic(&audio_buffer, 1024, 1024, 0); switch_assert(audio_buffer); + if ((tmp = (char *)switch_stristr(";loops=", tonespec))) { + *tmp = '\0'; + tmp += 7; + if (tmp) { + loops = atoi(tmp); + switch_buffer_set_loops(audio_buffer, loops); + } + } + if (handle->params) { if ((tmp = switch_event_get_header(handle->params, "loops"))) { loops = atoi(tmp); From a324d460256d246483c28263e39799acd2853e64 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sat, 9 Mar 2013 09:18:09 -0600 Subject: [PATCH 009/113] required trivial fix for windows for last spandsp commit --- libs/spandsp/src/spandsp/saturated.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/spandsp/src/spandsp/saturated.h b/libs/spandsp/src/spandsp/saturated.h index fcefbe96ab..a508e860c2 100644 --- a/libs/spandsp/src/spandsp/saturated.h +++ b/libs/spandsp/src/spandsp/saturated.h @@ -369,7 +369,7 @@ static __inline__ int16_t saturated_mul16(int16_t a, int16_t b) if (product == 0x40000000) return INT16_MAX; /*endif*/ - return product >> 15; + return (int16_t)product >> 15; } /*- End of function --------------------------------------------------------*/ From 76dc11585d53133181ddda1639bc1ffa7f64ad0e Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sat, 9 Mar 2013 11:00:07 -0600 Subject: [PATCH 010/113] spandsp trivial compiler warning - oops better do this instead --- libs/spandsp/src/spandsp/saturated.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/spandsp/src/spandsp/saturated.h b/libs/spandsp/src/spandsp/saturated.h index a508e860c2..aaa760a7ad 100644 --- a/libs/spandsp/src/spandsp/saturated.h +++ b/libs/spandsp/src/spandsp/saturated.h @@ -369,7 +369,7 @@ static __inline__ int16_t saturated_mul16(int16_t a, int16_t b) if (product == 0x40000000) return INT16_MAX; /*endif*/ - return (int16_t)product >> 15; + return (int16_t)(product >> 15); } /*- End of function --------------------------------------------------------*/ From d9a4b8a9b0304ceb9267b9e7c8551066a1826b0b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sat, 9 Mar 2013 13:00:22 -0600 Subject: [PATCH 011/113] FS-5156 --resolve default configuration needs new dsn --- conf/vanilla/autoload_configs/nibblebill.conf.xml | 4 +--- .../mod_nibblebill/conf/autoload_configs/nibblebill.conf.xml | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/conf/vanilla/autoload_configs/nibblebill.conf.xml b/conf/vanilla/autoload_configs/nibblebill.conf.xml index ed1c9332c8..043c985482 100644 --- a/conf/vanilla/autoload_configs/nibblebill.conf.xml +++ b/conf/vanilla/autoload_configs/nibblebill.conf.xml @@ -3,9 +3,7 @@ - - - + diff --git a/src/mod/applications/mod_nibblebill/conf/autoload_configs/nibblebill.conf.xml b/src/mod/applications/mod_nibblebill/conf/autoload_configs/nibblebill.conf.xml index ed1c9332c8..043c985482 100644 --- a/src/mod/applications/mod_nibblebill/conf/autoload_configs/nibblebill.conf.xml +++ b/src/mod/applications/mod_nibblebill/conf/autoload_configs/nibblebill.conf.xml @@ -3,9 +3,7 @@ - - - + From 45eaaf41781eb6d1921d4fa22b9062c7aeb5abfe Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sun, 10 Mar 2013 20:55:21 +0800 Subject: [PATCH 012/113] Spandspi's FAX engine now gives separate size and resolution information about the images on the line and the images in the file. The ties in with the recent addition of image resizing and flattenign for colur images. mod_spandsp has been changed to make use of the additional information. --- libs/spandsp/src/spandsp/private/t30.h | 2 + libs/spandsp/src/spandsp/private/t4_tx.h | 14 +++++-- libs/spandsp/src/spandsp/saturated.h | 2 +- libs/spandsp/src/spandsp/t30.h | 20 ++++++++-- libs/spandsp/src/spandsp/t4_rx.h | 30 +++++++++++--- libs/spandsp/src/t30.c | 13 ++++++- libs/spandsp/src/t4_rx.c | 39 +++++++++++++++++++ libs/spandsp/src/t4_tx.c | 33 +++++++++++++--- libs/spandsp/tests/dtmf_tx_tests.c | 4 +- libs/spandsp/tests/fax_tester.h | 9 +++-- libs/spandsp/tests/fax_tests.c | 4 +- libs/spandsp/tests/fax_utils.c | 5 ++- libs/spandsp/tests/t4_tests.c | 2 + .../mod_spandsp/mod_spandsp_fax.c | 39 +++++++++++++------ 14 files changed, 172 insertions(+), 44 deletions(-) diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index 9b70a7a73b..47574360ec 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.h @@ -218,6 +218,8 @@ struct t30_state_s /*! \brief TRUE if a local T.30 interrupt is pending. */ int local_interrupt_pending; + /*! \brief The image coding to be used on the line for non-bilevel images. */ + int multilevel_line_encoding; /*! \brief The image coding being used on the line. */ int line_encoding; /*! \brief The image coding being used for output files. */ diff --git a/libs/spandsp/src/spandsp/private/t4_tx.h b/libs/spandsp/src/spandsp/private/t4_tx.h index 078ac97b8a..afc44fcf53 100644 --- a/libs/spandsp/src/spandsp/private/t4_tx.h +++ b/libs/spandsp/src/spandsp/private/t4_tx.h @@ -57,9 +57,15 @@ typedef struct /*! \brief Row counter for playing out the rows of the image. */ int row; - /*! \brief Image length of the image in the file. This is used when the - image is resized or dithered flat. */ + /*! \brief Width of the image in the file. */ + int image_width; + /*! \brief Length of the image in the file. */ int image_length; + /*! \brief Column-to-column (X) resolution in pixels per metre of the image in the file. */ + int image_x_resolution; + /*! \brief Row-to-row (Y) resolution in pixels per metre of the image in the file. */ + int image_y_resolution; + /*! \brief Row counter used when the image is resized or dithered flat. */ int raw_row; } t4_tx_tiff_state_t; @@ -72,9 +78,9 @@ typedef struct */ typedef struct { - /*! \brief Column-to-column (X) resolution in pixels per metre. */ + /*! \brief Column-to-column (X) resolution in pixels per metre on the wire. */ int x_resolution; - /*! \brief Row-to-row (Y) resolution in pixels per metre. */ + /*! \brief Row-to-row (Y) resolution in pixels per metre on the wire. */ int y_resolution; } t4_tx_metadata_t; diff --git a/libs/spandsp/src/spandsp/saturated.h b/libs/spandsp/src/spandsp/saturated.h index aaa760a7ad..d8872f9c3b 100644 --- a/libs/spandsp/src/spandsp/saturated.h +++ b/libs/spandsp/src/spandsp/saturated.h @@ -369,7 +369,7 @@ static __inline__ int16_t saturated_mul16(int16_t a, int16_t b) if (product == 0x40000000) return INT16_MAX; /*endif*/ - return (int16_t)(product >> 15); + return (int16_t) (product >> 15); } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/t30.h b/libs/spandsp/src/spandsp/t30.h index a954be1c36..7606f42d75 100644 --- a/libs/spandsp/src/spandsp/t30.h +++ b/libs/spandsp/src/spandsp/t30.h @@ -531,13 +531,25 @@ typedef struct int pages_rx; /*! \brief The number of pages in the file (<0 if not known). */ int pages_in_file; - /*! \brief The horizontal column-to-column resolution of the most recent page, in pixels per metre */ + /*! \brief The type of image of the most recent file page */ + int image_type; + /*! \brief The horizontal column-to-column resolution of the most recent file page, in pixels per metre */ + int image_x_resolution; + /*! \brief The vertical row-to-row resolution of the most recent file page, in pixels per metre */ + int image_y_resolution; + /*! \brief The number of horizontal pixels in the most recent file page. */ + int image_width; + /*! \brief The number of vertical pixels in the most recent file page. */ + int image_length; + /*! \brief The type of image of the most recent exchanged page */ + int type; + /*! \brief The horizontal column-to-column resolution of the most recent exchanged page, in pixels per metre */ int x_resolution; - /*! \brief The vertical row-to-row resolution of the most recent page, in pixels per metre */ + /*! \brief The vertical row-to-row resolution of the most recent exchanged page, in pixels per metre */ int y_resolution; - /*! \brief The number of horizontal pixels in the most recent page. */ + /*! \brief The number of horizontal pixels in the most recent exchanged page. */ int width; - /*! \brief The number of vertical pixels in the most recent page. */ + /*! \brief The number of vertical pixels in the most recent exchanged page. */ int length; /*! \brief The size of the image, in bytes */ int image_size; diff --git a/libs/spandsp/src/spandsp/t4_rx.h b/libs/spandsp/src/spandsp/t4_rx.h index ba7dedb23f..f2ff4fa0ee 100644 --- a/libs/spandsp/src/spandsp/t4_rx.h +++ b/libs/spandsp/src/spandsp/t4_rx.h @@ -232,18 +232,30 @@ typedef struct int pages_transferred; /*! \brief The number of pages in the file (<0 if unknown). */ int pages_in_file; - /*! \brief The number of horizontal pixels in the most recent page. */ - int width; - /*! \brief The number of vertical pixels in the most recent page. */ - int length; /*! \brief The number of bad pixel rows in the most recent page. */ int bad_rows; /*! \brief The largest number of bad pixel rows in a block in the most recent page. */ int longest_bad_row_run; - /*! \brief The horizontal resolution of the page in pixels per metre */ + /*! \brief The type of image in the file page */ + int image_type; + /*! \brief The horizontal resolution of the file page in pixels per metre */ + int image_x_resolution; + /*! \brief The vertical resolution of the file page in pixels per metre */ + int image_y_resolution; + /*! \brief The number of horizontal pixels in the file page. */ + int image_width; + /*! \brief The number of vertical pixels in the file page. */ + int image_length; + /*! \brief The type of image in the exchanged page */ + int type; + /*! \brief The horizontal resolution of the exchanged page in pixels per metre */ int x_resolution; - /*! \brief The vertical resolution of the page in pixels per metre */ + /*! \brief The vertical resolution of the exchanged page in pixels per metre */ int y_resolution; + /*! \brief The number of horizontal pixels in the exchanged page. */ + int width; + /*! \brief The number of vertical pixels in the exchanged page. */ + int length; /*! \brief The type of compression used between the FAX machines */ int encoding; /*! \brief The size of the image on the line, in bytes */ @@ -369,6 +381,12 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t \return A pointer to the string. */ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding); +/*! Get the short text name of an image format. + \brief Get the short text name of an image format. + \param encoding The image format. + \return A pointer to the string. */ +SPAN_DECLARE(const char *) t4_image_type_to_str(int type); + #if defined(__cplusplus) } #endif diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 5c495dbb81..ddb0337834 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -6313,12 +6313,21 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t) t->pages_tx = s->tx_page_number; t->pages_rx = s->rx_page_number; t->pages_in_file = stats.pages_in_file; - t->width = stats.width; - t->length = stats.length; t->bad_rows = stats.bad_rows; t->longest_bad_row_run = stats.longest_bad_row_run; + + t->image_type = stats.image_type; + t->image_x_resolution = stats.image_x_resolution; + t->image_y_resolution = stats.image_y_resolution; + t->image_width = stats.image_width; + t->image_length = stats.image_length; + + t->type = stats.type; t->x_resolution = stats.x_resolution; t->y_resolution = stats.y_resolution; + t->width = stats.width; + t->length = stats.length; + t->encoding = stats.encoding; t->image_size = stats.line_image_size; t->current_status = s->current_status; diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index 293ea72b41..a331225ddf 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -114,6 +114,27 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(const char *) t4_image_type_to_str(int type) +{ + switch (type) + { + case T4_IMAGE_TYPE_BILEVEL: + return "bi-level"; + case T4_IMAGE_TYPE_COLOUR_BILEVEL: + return "bi-level colour"; + case T4_IMAGE_TYPE_GRAY_8BIT: + return "8-bit gray scale"; + case T4_IMAGE_TYPE_GRAY_12BIT: + return "12-bit gray scale"; + case T4_IMAGE_TYPE_COLOUR_8BIT: + return "8-bit colour"; + case T4_IMAGE_TYPE_COLOUR_12BIT: + return "12-bit colour"; + } + return "???"; +} +/*- End of function --------------------------------------------------------*/ + static int set_tiff_directory_info(t4_rx_state_t *s) { time_t now; @@ -573,6 +594,8 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t memset(t, 0, sizeof(*t)); t->pages_transferred = s->current_page; t->pages_in_file = s->tiff.pages_in_file; + t->image_x_resolution = s->metadata.x_resolution; + t->image_y_resolution = s->metadata.y_resolution; t->x_resolution = s->metadata.x_resolution; t->y_resolution = s->metadata.y_resolution; t->encoding = s->line_encoding; @@ -581,28 +604,44 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t case T4_COMPRESSION_ITU_T4_1D: case T4_COMPRESSION_ITU_T4_2D: case T4_COMPRESSION_ITU_T6: + t->type = T4_IMAGE_TYPE_BILEVEL; t->width = t4_t6_decode_get_image_width(&s->decoder.t4_t6); t->length = t4_t6_decode_get_image_length(&s->decoder.t4_t6); + t->image_type = t->type; + t->image_width = t->width; + t->image_length = t->length; t->line_image_size = t4_t6_decode_get_compressed_image_size(&s->decoder.t4_t6)/8; t->bad_rows = s->decoder.t4_t6.bad_rows; t->longest_bad_row_run = s->decoder.t4_t6.longest_bad_row_run; break; case T4_COMPRESSION_ITU_T42: + t->type = 0; t->width = t42_decode_get_image_width(&s->decoder.t42); t->length = t42_decode_get_image_length(&s->decoder.t42); + t->image_type = t->type; + t->image_width = t->width; + t->image_length = t->length; t->line_image_size = t42_decode_get_compressed_image_size(&s->decoder.t42)/8; break; #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_ITU_T43: + t->type = 0; t->width = t43_decode_get_image_width(&s->decoder.t43); t->length = t43_decode_get_image_length(&s->decoder.t43); + t->image_type = t->type; + t->image_width = t->width; + t->image_length = t->length; t->line_image_size = t43_decode_get_compressed_image_size(&s->decoder.t43)/8; break; #endif case T4_COMPRESSION_ITU_T85: case T4_COMPRESSION_ITU_T85_L0: + t->type = T4_IMAGE_TYPE_BILEVEL; t->width = t85_decode_get_image_width(&s->decoder.t85); t->length = t85_decode_get_image_length(&s->decoder.t85); + t->image_type = t->type; + t->image_width = t->width; + t->image_length = t->length; t->line_image_size = t85_decode_get_compressed_image_size(&s->decoder.t85)/8; break; } diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 82cf97026e..840b27a2f2 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -289,10 +289,11 @@ static int get_tiff_directory_info(t4_tx_state_t *s) #endif parm32 = 0; TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32); + t->image_width = s->image_width = parm32; parm32 = 0; TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32); - s->tiff.image_length = + t->image_length = s->image_length = parm32; x_resolution = 0.0f; TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution); @@ -322,6 +323,10 @@ static int get_tiff_directory_info(t4_tx_state_t *s) break; } } + if (res_unit == RESUNIT_INCH) + t->image_x_resolution = x_resolution*100.0f/CM_PER_INCH; + else + t->image_x_resolution = x_resolution*100.0f; s->metadata.y_resolution = T4_Y_RESOLUTION_STANDARD; for (i = 0; y_res_table[i].code > 0; i++) @@ -332,6 +337,11 @@ static int get_tiff_directory_info(t4_tx_state_t *s) break; } } + if (res_unit == RESUNIT_INCH) + t->image_y_resolution = y_resolution*100.0f/CM_PER_INCH; + else + t->image_y_resolution = y_resolution*100.0f; + t4_tx_set_image_width(s, s->image_width); t4_tx_set_image_length(s, s->image_length); t4_tx_set_max_2d_rows_per_1d_row(s, -s->metadata.y_resolution); @@ -421,7 +431,7 @@ static int test_tiff_directory_info(t4_tx_state_t *s) if (t->image_type != T4_IMAGE_TYPE_BILEVEL) return -1; #endif - if (s->tiff.image_type != image_type) + if (t->image_type != image_type) return 1; parm32 = 0; @@ -984,6 +994,13 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t memset(t, 0, sizeof(*t)); t->pages_transferred = s->current_page - s->start_page; t->pages_in_file = s->tiff.pages_in_file; + + t->image_type = s->tiff.image_type; + t->image_width = s->tiff.image_width; + t->image_length = s->tiff.image_length; + t->image_x_resolution = s->tiff.image_x_resolution; + t->image_y_resolution = s->tiff.image_y_resolution; + t->x_resolution = s->metadata.x_resolution; t->y_resolution = s->metadata.y_resolution/s->row_squashing_ratio; t->encoding = s->line_encoding; @@ -992,26 +1009,30 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t case T4_COMPRESSION_ITU_T4_1D: case T4_COMPRESSION_ITU_T4_2D: case T4_COMPRESSION_ITU_T6: + t->type = T4_IMAGE_TYPE_BILEVEL; t->width = t4_t6_encode_get_image_width(&s->encoder.t4_t6); - t->length = t4_t6_encode_get_image_length(&s->encoder.t4_t6); + t->length = t4_t6_encode_get_image_length(&s->encoder.t4_t6)/s->row_squashing_ratio; t->line_image_size = t4_t6_encode_get_compressed_image_size(&s->encoder.t4_t6)/8; break; case T4_COMPRESSION_ITU_T42: + t->type = 0; t->width = t42_encode_get_image_width(&s->encoder.t42); - t->length = t42_encode_get_image_length(&s->encoder.t42); + t->length = t42_encode_get_image_length(&s->encoder.t42)/s->row_squashing_ratio; t->line_image_size = t42_encode_get_compressed_image_size(&s->encoder.t42)/8; break; #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_ITU_T43: + t->type = 0; t->width = t43_encode_get_image_width(&s->encoder.t43); - t->length = t43_encode_get_image_length(&s->encoder.t43); + t->length = t43_encode_get_image_length(&s->encoder.t43)/s->row_squashing_ratio; t->line_image_size = t43_encode_get_compressed_image_size(&s->encoder.t43)/8; break; #endif case T4_COMPRESSION_ITU_T85: case T4_COMPRESSION_ITU_T85_L0: + t->type = T4_IMAGE_TYPE_BILEVEL; t->width = t85_encode_get_image_width(&s->encoder.t85); - t->length = t85_encode_get_image_length(&s->encoder.t85); + t->length = t85_encode_get_image_length(&s->encoder.t85)/s->row_squashing_ratio; t->line_image_size = t85_encode_get_compressed_image_size(&s->encoder.t85)/8; break; } diff --git a/libs/spandsp/tests/dtmf_tx_tests.c b/libs/spandsp/tests/dtmf_tx_tests.c index 75151129a0..176cf1783b 100644 --- a/libs/spandsp/tests/dtmf_tx_tests.c +++ b/libs/spandsp/tests/dtmf_tx_tests.c @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) exit(2); } - gen = dtmf_tx_init(NULL); + gen = dtmf_tx_init(NULL, NULL, NULL); len = dtmf_tx(gen, amp, 16384); printf("Generated %d samples\n", len); sf_writef_short(outhandle, amp, len); @@ -117,7 +117,7 @@ int main(int argc, char *argv[]) } while (len > 0); - dtmf_tx_init(gen); + dtmf_tx_init(gen, NULL, NULL); len = dtmf_tx(gen, amp, 16384); printf("Generated %d samples\n", len); sf_writef_short(outhandle, amp, len); diff --git a/libs/spandsp/tests/fax_tester.h b/libs/spandsp/tests/fax_tester.h index 3d64e2e6b7..0d1f77f0bb 100644 --- a/libs/spandsp/tests/fax_tester.h +++ b/libs/spandsp/tests/fax_tester.h @@ -83,14 +83,17 @@ struct faxtester_state_s int image_len; int image_ptr; int image_bit_ptr; - + int ecm_frame_size; int corrupt_crc; - + int final_delayed; fax_modems_state_t modems; - + + /*! \brief CED or CNG detector */ + modem_connect_tones_rx_state_t connect_rx; + /*! If TRUE, transmission is in progress */ int transmit; diff --git a/libs/spandsp/tests/fax_tests.c b/libs/spandsp/tests/fax_tests.c index fc0e20988e..cf28500905 100644 --- a/libs/spandsp/tests/fax_tests.c +++ b/libs/spandsp/tests/fax_tests.c @@ -529,7 +529,7 @@ int main(int argc, char *argv[]) decode_file_name = NULL; code_to_look_up = -1; t38_transport = T38_TRANSPORT_UDPTL; - while ((opt = getopt(argc, argv, "c:d:D:efFgH:i:Ilm:M:n:p:s:tT:u:v:z:")) != -1) + while ((opt = getopt(argc, argv, "c:d:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1) { switch (opt) { @@ -865,7 +865,7 @@ int main(int argc, char *argv[]) T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION - | T30_SUPPORT_T81_COMPRESSION + //| T30_SUPPORT_T81_COMPRESSION | T30_SUPPORT_T85_COMPRESSION | T30_SUPPORT_T85_L0_COMPRESSION); } diff --git a/libs/spandsp/tests/fax_utils.c b/libs/spandsp/tests/fax_utils.c index 9548808086..b306855965 100644 --- a/libs/spandsp/tests/fax_utils.c +++ b/libs/spandsp/tests/fax_utils.c @@ -105,8 +105,9 @@ void fax_log_page_transfer_statistics(t30_state_t *s, const char *tag) printf("%s: Bad ECM frames %d\n", tag, t.error_correcting_mode_retries); printf("%s: Compression type %s (%d)\n", tag, t4_encoding_to_str(t.encoding), t.encoding); printf("%s: Compressed image size %d bytes\n", tag, t.image_size); - printf("%s: Image size %d pels x %d pels\n", tag, t.width, t.length); - printf("%s: Image resolution %d pels/m x %d pels/m\n", tag, t.x_resolution, t.y_resolution); + printf("%s: Image type %s (%s in the file)\n", tag, t4_image_type_to_str(t.type), t4_image_type_to_str(t.image_type)); + printf("%s: Image size %d pels x %d pels (%d pels x %d pels in the file)\n", tag, t.width, t.length, t.image_width, t.image_length); + printf("%s: Image resolution %d pels/m x %d pels/m (%d pels/m x %d pels/m in the file)\n", tag, t.x_resolution, t.y_resolution, t.image_x_resolution, t.image_y_resolution); #if defined(SPANDSP_EXPOSE_INTERNAL_STRUCTURES) printf("%s: Bits per row - min %d, max %d\n", tag, s->t4.tx.encoder.t4_t6.min_row_bits, s->t4.tx.encoder.t4_t6.max_row_bits); #endif diff --git a/libs/spandsp/tests/t4_tests.c b/libs/spandsp/tests/t4_tests.c index 0e2167513b..8b96f390f1 100644 --- a/libs/spandsp/tests/t4_tests.c +++ b/libs/spandsp/tests/t4_tests.c @@ -130,7 +130,9 @@ static void display_page_stats(t4_rx_state_t *s) printf("Pages = %d\n", stats.pages_transferred); printf("Compression = %s\n", t4_encoding_to_str(stats.encoding)); printf("Compressed size = %d\n", stats.line_image_size); + printf("Raw image size = %d pels x %d pels\n", stats.image_width, stats.image_length); printf("Image size = %d pels x %d pels\n", stats.width, stats.length); + printf("Raw image resolution = %d pels/m x %d pels/m\n", stats.image_x_resolution, stats.image_y_resolution); printf("Image resolution = %d pels/m x %d pels/m\n", stats.x_resolution, stats.y_resolution); printf("Bad rows = %d\n", stats.bad_rows); printf("Longest bad row run = %d\n", stats.longest_bad_row_run); diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index 0af26ce625..ff0b9a36f9 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -358,9 +358,11 @@ static int phase_b_handler(t30_state_t *s, void *user_data, int result) static int phase_d_handler(t30_state_t *s, void *user_data, int msg) { t30_stats_t t30_stats; - char *fax_image_resolution = NULL; + char *fax_file_image_resolution = NULL; + char *fax_line_image_resolution = NULL; + char *fax_file_image_pixel_size = NULL; + char *fax_line_image_pixel_size = NULL; char *fax_image_size = NULL; - char *fax_image_pixel_size = NULL; char *fax_bad_rows = NULL; char *fax_encoding = NULL; char *fax_longest_bad_row_run = NULL; @@ -383,14 +385,24 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg) /* Set Channel Variable */ - fax_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.x_resolution, t30_stats.y_resolution); - if (fax_image_resolution) { - switch_channel_set_variable(channel, "fax_image_resolution", fax_image_resolution); + fax_line_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.x_resolution, t30_stats.y_resolution); + if (fax_line_image_resolution) { + switch_channel_set_variable(channel, "fax_image_resolution", fax_line_image_resolution); } - fax_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.width, t30_stats.length); - if (fax_image_pixel_size) { - switch_channel_set_variable(channel, "fax_image_pixel_size", fax_image_pixel_size);; + fax_file_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.image_x_resolution, t30_stats.image_y_resolution); + if (fax_file_image_resolution) { + switch_channel_set_variable(channel, "fax_file_image_resolution", fax_file_image_resolution); + } + + fax_line_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.width, t30_stats.length); + if (fax_line_image_pixel_size) { + switch_channel_set_variable(channel, "fax_image_pixel_size", fax_line_image_pixel_size);; + } + + fax_file_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.image_width, t30_stats.image_length); + if (fax_file_image_pixel_size) { + switch_channel_set_variable(channel, "fax_file_image_pixel_size", fax_file_image_pixel_size);; } fax_image_size = switch_core_session_sprintf(session, "%d", t30_stats.image_size); @@ -423,8 +435,9 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==== Page %s===========================================================\n", pvt->app_mode == FUNCTION_TX ? "Sent ====": "Received "); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Page no = %d\n", (pvt->app_mode == FUNCTION_TX) ? t30_stats.pages_tx : t30_stats.pages_rx); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image size = %d x %d pixels\n", t30_stats.width, t30_stats.length); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image resolution = %d/m x %d/m\n", t30_stats.x_resolution, t30_stats.y_resolution); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image type = %s (%s in the file)\n", t4_image_type_to_str(t30_stats.type), t4_image_type_to_str(t30_stats.image_type)); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image size = %d x %d pixels (%d x %d pixels in the file)\n", t30_stats.width, t30_stats.length, t30_stats.image_width, t30_stats.image_length); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image resolution = %d/m x %d/m (%d/m x %d/m in the file)\n", t30_stats.x_resolution, t30_stats.y_resolution, t30_stats.image_x_resolution, t30_stats.image_y_resolution); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compression = %s (%d)\n", t4_encoding_to_str(t30_stats.encoding), t30_stats.encoding); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compressed image size = %d bytes\n", t30_stats.image_size); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad rows = %d\n", t30_stats.bad_rows); @@ -436,9 +449,11 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg) if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXPAGERESULT : SPANDSP_EVENT_RXFAXPAGERESULT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_image_resolution); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_line_image_resolution); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-file-image-resolution", fax_file_image_resolution); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-pixel-size", fax_image_pixel_size); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-pixel-size", fax_line_image_pixel_size); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-file-image-pixel-size", fax_file_image_pixel_size); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-bad-rows", fax_bad_rows); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-longest-bad-row-run", fax_longest_bad_row_run); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-encoding", fax_encoding); From 6fe64c68c0eb0aa093c6ce85942ff67a02c90032 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sun, 10 Mar 2013 15:01:38 -0500 Subject: [PATCH 013/113] FS-4000 --resolve --- src/include/switch_apr.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index 671052ab30..ace5f18569 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -1042,6 +1042,11 @@ SWITCH_DECLARE(switch_status_t) switch_thread_create(switch_thread_t ** new_thre * The default values come from FreeBSD 4.1.1 */ #define SWITCH_INET AF_INET +#ifdef AF_INET6 +#define SWITCH_INET6 AF_INET6 +#else +#define SWITCH_INET6 0 +#endif /** @def SWITCH_UNSPEC * Let the system decide which address family to use From 05895faa770d227953346ec3f573e724073d2cdf Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sun, 10 Mar 2013 15:14:53 -0500 Subject: [PATCH 014/113] FS-3996 --resolve stop conference recording when only 1 person left --- src/mod/applications/mod_conference/mod_conference.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 95e4fcc978..25b5f29d69 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -3932,7 +3932,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_event_fire(&event); } - while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) { + while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count > 1) { len = 0; From 5f733b24bfcd04c4c9e24acf59701a380d232ade Mon Sep 17 00:00:00 2001 From: Seven Du Date: Mon, 11 Mar 2013 18:04:05 +0800 Subject: [PATCH 015/113] FS-4225 --- conf/vanilla/sip_profiles/internal.xml | 3 +++ src/mod/endpoints/mod_sofia/conf/sofia.conf.xml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/conf/vanilla/sip_profiles/internal.xml b/conf/vanilla/sip_profiles/internal.xml index f4e0cfc54b..7beecbfeab 100644 --- a/conf/vanilla/sip_profiles/internal.xml +++ b/conf/vanilla/sip_profiles/internal.xml @@ -293,6 +293,9 @@ + + + diff --git a/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml b/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml index 150a3fe1d6..bf6bee7b28 100644 --- a/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml +++ b/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml @@ -342,6 +342,9 @@ + + + From 0026f9e4966390e068cbe3cb34be00cf0032beef Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 11 Mar 2013 09:14:11 -0500 Subject: [PATCH 016/113] FS-5163 --resolve --- src/mod/applications/mod_fifo/mod_fifo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index ce0bf39ac4..5d21fc141e 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -2927,8 +2927,6 @@ SWITCH_STANDARD_APP(fifo_function) if (announce) { switch_ivr_play_file(session, NULL, announce, NULL); - } else { - switch_ivr_sleep(session, 500, SWITCH_TRUE, NULL); } switch_channel_set_variable(other_channel, "fifo_serviced_by", my_id); From 5655320dae3aa61d472634628682de49661ac449 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 11 Mar 2013 09:33:08 -0500 Subject: [PATCH 017/113] FS-5087 --resolve --- src/mod/applications/mod_voicemail/mod_voicemail.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index ccb0811ddd..e3fe91da88 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -674,6 +674,7 @@ vm_profile_t *profile_set_config(vm_profile_t *profile) &profile->db_password_override, SWITCH_FALSE, NULL, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "allow-empty-password-auth", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &profile->allow_empty_password_auth, SWITCH_TRUE, NULL, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(profile->config[i++], "auto-playback-recordings", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &profile->auto_playback_recordings, SWITCH_FALSE, NULL, NULL, NULL); switch_assert(i < VM_PROFILE_CONFIGITEM_COUNT); From ee7425440931ce8bc2960e8743b4d9ed6e28ebd6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 11 Mar 2013 17:10:52 +0000 Subject: [PATCH 018/113] Improve instructions for Debian util.sh build These instructions comprise everything needed to build the Debian packages from a virgin Debian image. --- debian/README.source | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/debian/README.source b/debian/README.source index 1f1f054f8e..566cfe6f2f 100644 --- a/debian/README.source +++ b/debian/README.source @@ -74,13 +74,23 @@ To build for a stable branch, do this: dpkg-buildpackage -b -us -uc -Zxz -z9 git reset --hard origin/master -Alternatively, you can build using our automated tools: +Alternatively, you can build using our automated tools. To build the +source packages and all supported binary packages for sid, wheezy, +squeeze on i386 and amd64, run the following as root from a clean +Debian 'buildd' image: - aptitude install cowbuilder + aptitude update && aptitude upgrade + aptitude install -y \ + rsync git less cowbuilder ccache \ + devscripts equivs build-essential + mkdir /usr/src/freeswitch + git clone git://git.freeswitch.org/freeswitch /usr/src/freeswitch/src + cd /usr/src/freeswitch/src # if you only want to build some modules, create a modules.conf # outside the source tree and add -f ../path/to/modules.conf to the - # command below. - ./debian/util.sh build-all -bn -a amd64 -c sid # update as needed + # command below. See ./debian/util.sh -h for further usage + # information. + ./debian/util.sh build-all -bn -z9 The source packages for sounds and music on hold are maintained in a separate repository. Each set of sounds has a separate version number @@ -94,4 +104,4 @@ freeswitch-music-*: git clone https://github.com/traviscross/freeswitch-sounds.git cd freeswitch-sounds && cat debian/README.source - -- Travis Cross , Wed, 3 Oct 2012 02:15:24 +0000 + -- Travis Cross , Mon, 11 Mar 2013 17:09:33 +0000 From 209aec39e5e09564532f4ee35029284d4dd44636 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Mon, 11 Mar 2013 10:44:53 -0700 Subject: [PATCH 019/113] update to be recorded phrases --- docs/phrase/phrase_en.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index 9fdcd924db..9da5162aef 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -629,7 +629,7 @@ - + From 7d29a92f55981c31e03e7c6d9de1dc132260e6bd Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 11 Mar 2013 22:35:18 -0500 Subject: [PATCH 020/113] Allow logging of detailed verbose per UUID for debugging --- .../mod_spandsp/mod_spandsp_fax.c | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index ff0b9a36f9..8504fda1d5 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -262,7 +262,12 @@ static void counter_increment(void) void spanfax_log_message(void *user_data, int level, const char *msg) { int fs_log_level; - + switch_core_session_t *session; + pvt_t *pvt; + + pvt = (pvt_t *) user_data; + session = pvt->session; + switch (level) { case SPAN_LOG_NONE: return; @@ -283,7 +288,7 @@ void spanfax_log_message(void *user_data, int level, const char *msg) } if (!zstr(msg)) { - switch_log_printf(SWITCH_CHANNEL_LOG, fs_log_level, "%s", msg); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), fs_log_level, "%s", msg); } } @@ -724,8 +729,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) fax_set_transmit_on_idle(fax, TRUE); - span_log_set_message_handler(fax_get_logging_state(fax), spanfax_log_message, NULL); - span_log_set_message_handler(t30_get_logging_state(t30), spanfax_log_message, NULL); + span_log_set_message_handler(fax_get_logging_state(fax), spanfax_log_message, pvt); + span_log_set_message_handler(t30_get_logging_state(t30), spanfax_log_message, pvt); if (pvt->verbose) { span_log_set_level(fax_get_logging_state(fax), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); @@ -780,8 +785,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) } } - span_log_set_message_handler(t38_terminal_get_logging_state(t38), spanfax_log_message, NULL); - span_log_set_message_handler(t30_get_logging_state(t30), spanfax_log_message, NULL); + span_log_set_message_handler(t38_terminal_get_logging_state(t38), spanfax_log_message, pvt); + span_log_set_message_handler(t30_get_logging_state(t30), spanfax_log_message, pvt); if (pvt->verbose) { span_log_set_level(t38_terminal_get_logging_state(t38), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); @@ -835,8 +840,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) } - span_log_set_message_handler(t38_gateway_get_logging_state(pvt->t38_gateway_state), spanfax_log_message, NULL); - span_log_set_message_handler(t38_core_get_logging_state(pvt->t38_core), spanfax_log_message, NULL); + span_log_set_message_handler(t38_gateway_get_logging_state(pvt->t38_gateway_state), spanfax_log_message, pvt); + span_log_set_message_handler(t38_core_get_logging_state(pvt->t38_core), spanfax_log_message, pvt); if (pvt->verbose) { span_log_set_level(t38_gateway_get_logging_state(pvt->t38_gateway_state), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); From 4e812bb26371c4cbde1ca39d757dfdc6d5832a6d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 13 Mar 2013 10:37:34 -0500 Subject: [PATCH 021/113] FS-5169 --resolve --- src/switch_channel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/switch_channel.c b/src/switch_channel.c index aa31df0ad3..655dea39c0 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -74,6 +74,7 @@ static struct switch_cause_table CAUSE_CHART[] = { {"BEARERCAPABILITY_NOTAUTH", SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH}, {"BEARERCAPABILITY_NOTAVAIL", SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL}, {"SERVICE_UNAVAILABLE", SWITCH_CAUSE_SERVICE_UNAVAILABLE}, + {"BEARERCAPABILITY_NOTIMPL", SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL}, {"CHAN_NOT_IMPLEMENTED", SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED}, {"FACILITY_NOT_IMPLEMENTED", SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED}, {"SERVICE_NOT_IMPLEMENTED", SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED}, @@ -108,6 +109,7 @@ static struct switch_cause_table CAUSE_CHART[] = { {"GATEWAY_DOWN", SWITCH_CAUSE_GATEWAY_DOWN}, {"INVALID_URL", SWITCH_CAUSE_INVALID_URL}, {"INVALID_PROFILE", SWITCH_CAUSE_INVALID_PROFILE}, + {"NO_PICKUP", SWITCH_CAUSE_NO_PICKUP}, {NULL, 0} }; From 93bb5ca5c7620dcdb41a9436cb27a86ad5f4ef04 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Thu, 14 Mar 2013 05:04:43 +0800 Subject: [PATCH 022/113] Removal of numerous trailing spaces, to tidy up spandsp in line with the master version. --- libs/spandsp/spandsp-sim/g1050.c | 12 +++--- libs/spandsp/spandsp-sim/line_model.c | 26 ++++++------ libs/spandsp/spandsp-sim/make_line_models.c | 12 +++--- libs/spandsp/spandsp-sim/rfc2198_sim.c | 4 +- libs/spandsp/spandsp-sim/spandsp/g1050.h | 2 +- libs/spandsp/spandsp-sim/spandsp/line_model.h | 10 ++--- libs/spandsp/spandsp-sim/test_utils.c | 8 ++-- libs/spandsp/src/adsi.c | 12 +++--- libs/spandsp/src/async.c | 4 +- libs/spandsp/src/at_interpreter.c | 24 +++++------ libs/spandsp/src/awgn.c | 4 +- libs/spandsp/src/bell_r2_mf.c | 6 +-- libs/spandsp/src/bert.c | 4 +- libs/spandsp/src/fax.c | 6 +-- libs/spandsp/src/filter_tools.h | 1 - libs/spandsp/src/g722.c | 8 ++-- libs/spandsp/src/g726.c | 14 +++---- libs/spandsp/src/gsm0610_decode.c | 2 +- libs/spandsp/src/gsm0610_encode.c | 8 ++-- libs/spandsp/src/gsm0610_lpc.c | 22 +++++----- libs/spandsp/src/gsm0610_preprocess.c | 10 ++--- libs/spandsp/src/gsm0610_rpe.c | 18 ++++---- libs/spandsp/src/gsm0610_short_term.c | 2 +- libs/spandsp/src/hdlc.c | 4 +- libs/spandsp/src/lpc10_analyse.c | 13 +++--- libs/spandsp/src/lpc10_decode.c | 15 +++---- libs/spandsp/src/lpc10_encdecs.h | 6 +-- libs/spandsp/src/lpc10_encode.c | 29 +++++++------ libs/spandsp/src/lpc10_placev.c | 6 +-- libs/spandsp/src/lpc10_voicing.c | 8 ++-- libs/spandsp/src/make_at_dictionary.c | 14 +++---- libs/spandsp/src/make_cielab_luts.c | 4 +- libs/spandsp/src/make_modem_filter.c | 2 +- libs/spandsp/src/math_fixed.c | 2 +- libs/spandsp/src/playout.c | 20 ++++----- libs/spandsp/src/plc.c | 2 +- libs/spandsp/src/queue.c | 10 ++--- libs/spandsp/src/spandsp/ademco_contactid.h | 2 +- libs/spandsp/src/spandsp/adsi.h | 26 ++++++------ libs/spandsp/src/spandsp/arctan2.h | 2 +- libs/spandsp/src/spandsp/awgn.h | 10 ++--- libs/spandsp/src/spandsp/bell_r2_mf.h | 10 ++--- libs/spandsp/src/spandsp/biquad.h | 8 ++-- libs/spandsp/src/spandsp/bit_operations.h | 2 +- libs/spandsp/src/spandsp/g168models.h | 20 ++++----- libs/spandsp/src/spandsp/g711.h | 8 ++-- .../spandsp/src/spandsp/modem_connect_tones.h | 4 +- libs/spandsp/src/spandsp/modem_echo.h | 10 ++--- .../src/spandsp/private/ademco_contactid.h | 2 +- libs/spandsp/src/spandsp/private/adsi.h | 4 +- .../src/spandsp/private/at_interpreter.h | 2 +- libs/spandsp/src/spandsp/private/g722.h | 2 +- libs/spandsp/src/spandsp/private/g726.h | 4 +- libs/spandsp/src/spandsp/private/gsm0610.h | 2 +- libs/spandsp/src/spandsp/private/lpc10.h | 2 +- .../src/spandsp/private/modem_connect_tones.h | 2 +- libs/spandsp/src/spandsp/private/sig_tone.h | 2 +- libs/spandsp/src/spandsp/private/t30.h | 6 +-- .../spandsp/private/t30_dis_dtc_dcs_bits.h | 6 +-- libs/spandsp/src/spandsp/private/t38_core.h | 6 +-- libs/spandsp/src/spandsp/private/t4_rx.h | 12 +++--- libs/spandsp/src/spandsp/private/t4_tx.h | 2 +- libs/spandsp/src/spandsp/private/v17rx.h | 2 +- libs/spandsp/src/spandsp/private/v17tx.h | 2 +- libs/spandsp/src/spandsp/private/v18.h | 2 +- libs/spandsp/src/spandsp/private/v22bis.h | 4 +- libs/spandsp/src/spandsp/private/v27ter_rx.h | 2 +- libs/spandsp/src/spandsp/private/v27ter_tx.h | 2 +- libs/spandsp/src/spandsp/private/v29rx.h | 2 +- libs/spandsp/src/spandsp/private/v42bis.h | 6 +-- libs/spandsp/src/spandsp/private/v8.h | 4 +- libs/spandsp/src/spandsp/t30.h | 14 +++---- libs/spandsp/src/spandsp/t31.h | 2 +- libs/spandsp/src/spandsp/t38_non_ecm_buffer.h | 2 +- libs/spandsp/src/spandsp/tone_generate.h | 4 +- libs/spandsp/src/spandsp/v17rx.h | 6 +-- libs/spandsp/src/spandsp/v17tx.h | 6 +-- libs/spandsp/src/spandsp/v18.h | 2 +- libs/spandsp/src/spandsp/v27ter_rx.h | 2 +- libs/spandsp/src/spandsp/v27ter_tx.h | 6 +-- libs/spandsp/src/spandsp/v29rx.h | 8 ++-- libs/spandsp/src/spandsp/v29tx.h | 12 +++--- libs/spandsp/src/spandsp/v42.h | 2 +- libs/spandsp/src/spandsp/v42bis.h | 2 +- libs/spandsp/src/t30.c | 18 ++++---- libs/spandsp/src/t30_logging.c | 8 ++-- libs/spandsp/src/t31.c | 14 +++---- libs/spandsp/src/t35.c | 30 ++++++------- libs/spandsp/src/t38_core.c | 2 +- libs/spandsp/src/t38_gateway.c | 16 +++---- libs/spandsp/src/t38_non_ecm_buffer.c | 4 +- libs/spandsp/src/t38_terminal.c | 12 +++--- libs/spandsp/src/t4_rx.c | 2 - libs/spandsp/src/t85_decode.c | 2 +- libs/spandsp/src/t85_encode.c | 4 +- libs/spandsp/src/tone_generate.c | 4 +- libs/spandsp/src/v17rx.c | 4 +- libs/spandsp/src/v18.c | 8 ++-- libs/spandsp/src/v22bis_rx.c | 4 +- libs/spandsp/src/v22bis_tx.c | 4 +- libs/spandsp/src/v27ter_rx.c | 6 +-- libs/spandsp/src/v27ter_tx.c | 2 +- libs/spandsp/src/v29rx.c | 4 +- libs/spandsp/src/vector_int.c | 42 +++++++++---------- libs/spandsp/tests/bell_mf_rx_tests.c | 12 +++--- libs/spandsp/tests/bert_tests.c | 4 +- libs/spandsp/tests/bit_operations_tests.c | 24 +++++------ libs/spandsp/tests/bitstream_tests.c | 2 +- libs/spandsp/tests/crc_tests.c | 6 +-- libs/spandsp/tests/echo_monitor.cpp | 10 ++--- libs/spandsp/tests/fax_tester.h | 2 +- libs/spandsp/tests/line_model_monitor.cpp | 4 +- libs/spandsp/tests/line_model_tests.c | 14 +++---- libs/spandsp/tests/lpc10_tests.c | 6 +-- libs/spandsp/tests/media_monitor.cpp | 12 +++--- libs/spandsp/tests/modem_monitor.cpp | 12 +++--- .../spandsp/tests/t31_pseudo_terminal_tests.c | 10 ++--- libs/spandsp/tests/t31_tests.c | 6 +-- libs/spandsp/tests/t38_core_tests.c | 6 +-- libs/spandsp/tests/t38_decode.c | 4 +- libs/spandsp/tests/t38_non_ecm_buffer_tests.c | 2 +- libs/spandsp/tests/t4_tests.c | 4 +- libs/spandsp/tests/tsb85_tests.c | 18 ++++---- libs/spandsp/tests/v18_tests.c | 4 +- libs/spandsp/tests/v22bis_tests.c | 10 ++--- libs/spandsp/tests/v29_tests.c | 4 +- libs/spandsp/tests/v42bis_tests.c | 4 +- libs/spandsp/tests/v8_tests.c | 6 +-- libs/spandsp/tests/vector_float_tests.c | 8 ++-- libs/spandsp/tests/vector_int_tests.c | 4 +- 130 files changed, 494 insertions(+), 498 deletions(-) diff --git a/libs/spandsp/spandsp-sim/g1050.c b/libs/spandsp/spandsp-sim/g1050.c index afdcf82d63..c1e8b9d415 100644 --- a/libs/spandsp/spandsp-sim/g1050.c +++ b/libs/spandsp/spandsp-sim/g1050.c @@ -780,7 +780,7 @@ static void g1050_core_init(g1050_core_state_t *s, g1050_core_model_t *parms, in /* How far into the first CLEAN interval we are. This is like the route flap initialzation. */ s->link_failure_counter = s->link_failure_interval_ticks - 99 - floor(s->link_failure_interval_ticks*q1050_rand()); s->link_recovery_counter = s->link_failure_duration_ticks; - + s->base_delay = parms->base_regional_delay; s->max_jitter = parms->max_jitter; s->prob_packet_loss = parms->prob_packet_loss/100.0; @@ -1053,7 +1053,7 @@ static int g1050_core_delay(g1050_core_state_t *s, static void g1050_simulate_chunk(g1050_state_t *s) { int i; - + s->base_time += 1.0; memcpy(&s->segment[0].delays[0], &s->segment[0].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[0].delays[0])); @@ -1116,7 +1116,7 @@ SPAN_DECLARE(g1050_state_t *) g1050_init(int model, mo = &g1050_standard_models[model]; memset(s, 0, sizeof(*s)); - + s->packet_rate = packet_rate; s->packet_size = packet_size; @@ -1190,7 +1190,7 @@ SPAN_DECLARE(void) g1050_dump_parms(int model, int speed_pattern) { g1050_channel_speeds_t *sp; g1050_model_t *mo; - + sp = &g1050_speed_patterns[speed_pattern - 1]; mo = &g1050_standard_models[model]; @@ -1245,8 +1245,8 @@ SPAN_DECLARE(int) g1050_put(g1050_state_t *s, const uint8_t buf[], int len, int } if (e) { - element->next = e->next; - element->prev = e; + element->next = e->next; + element->prev = e; e->next = element; } else diff --git a/libs/spandsp/spandsp-sim/line_model.c b/libs/spandsp/spandsp-sim/line_model.c index 001af2c581..4326ae7d29 100644 --- a/libs/spandsp/spandsp-sim/line_model.c +++ b/libs/spandsp/spandsp-sim/line_model.c @@ -221,7 +221,7 @@ static float calc_near_line_filter(one_way_line_model_state_t *s, float v) if (++p == s->near_filter_len) p = 0; s->near_buf_ptr = p; - + /* Apply the filter */ sum = 0.0f; for (j = 0; j < s->near_filter_len; j++) @@ -230,10 +230,10 @@ static float calc_near_line_filter(one_way_line_model_state_t *s, float v) if (++p >= s->near_filter_len) p = 0; } - + /* Add noise */ sum += awgn(&s->near_noise); - + return sum; } /*- End of function --------------------------------------------------------*/ @@ -250,7 +250,7 @@ static float calc_far_line_filter(one_way_line_model_state_t *s, float v) if (++p == s->far_filter_len) p = 0; s->far_buf_ptr = p; - + /* Apply the filter */ sum = 0.0f; for (j = 0; j < s->far_filter_len; j++) @@ -259,7 +259,7 @@ static float calc_far_line_filter(one_way_line_model_state_t *s, float v) if (++p >= s->far_filter_len) p = 0; } - + /* Add noise */ sum += awgn(&s->far_noise); @@ -267,7 +267,7 @@ static float calc_far_line_filter(one_way_line_model_state_t *s, float v) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) one_way_line_model(one_way_line_model_state_t *s, +SPAN_DECLARE(void) one_way_line_model(one_way_line_model_state_t *s, int16_t output[], const int16_t input[], int samples) @@ -302,10 +302,10 @@ SPAN_DECLARE(void) one_way_line_model(one_way_line_model_state_t *s, in = input[i]; /* Near end analogue section */ - + /* Line model filters & noise */ out = calc_near_line_filter(s, in); - + /* Long distance digital section */ amp[0] = out; @@ -319,10 +319,10 @@ SPAN_DECLARE(void) one_way_line_model(one_way_line_model_state_t *s, s->bulk_delay_ptr = 0; /* Far end analogue section */ - + /* Line model filters & noise */ out = calc_far_line_filter(s, out); - + if (s->mains_interference) { tone_gen(&s->mains_tone, amp, 1); @@ -352,7 +352,7 @@ SPAN_DECLARE(void) one_way_line_model_set_mains_pickup(one_way_line_model_state_ } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s, +SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s, int16_t output1[], const int16_t input1[], int16_t output2[], @@ -486,7 +486,7 @@ SPAN_DECLARE(one_way_line_model_state_t *) one_way_line_model_init(int model, fl /* Put half the noise in each analogue section */ awgn_init_dbm0(&s->near_noise, 1234567, noise - 3.02f); awgn_init_dbm0(&s->far_noise, 1234567, noise - 3.02f); - + s->dc_offset = 0.0f; s->mains_interference = 0; @@ -554,7 +554,7 @@ SPAN_DECLARE(both_ways_line_model_state_t *) both_ways_line_model_init(int model s->line2.near_co_hybrid_echo = pow(10, echo_level_co2/20.0f); s->line1.near_cpe_hybrid_echo = pow(10, echo_level_cpe1/20.0f); s->line2.near_cpe_hybrid_echo = pow(10, echo_level_cpe2/20.0f); - + return s; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/spandsp-sim/make_line_models.c b/libs/spandsp/spandsp-sim/make_line_models.c index 300de80c22..ed7cfe934e 100644 --- a/libs/spandsp/spandsp-sim/make_line_models.c +++ b/libs/spandsp/spandsp-sim/make_line_models.c @@ -69,7 +69,7 @@ /* Tabulated medium range telephone line response (from p 537, Digital Communication, John G. Proakis */ /* - amp 1.0 -> 2.15, freq = 3000 Hz -> 3.2, by 0.2 increments + amp 1.0 -> 2.15, freq = 3000 Hz -> 3.2, by 0.2 increments delay = 4 ms -> 2.2 */ @@ -849,7 +849,7 @@ static void generate_ad_edd(void) } //phase = 2.0f*M_PI*f*delay*0.001f; phase = 0.0f; -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) in[i][0] = amp*cosf(phase); in[i][1] = amp*sinf(phase); in[FFT_SIZE - i][0] = in[i][0]; @@ -865,7 +865,7 @@ static void generate_ad_edd(void) for (i = 0; i < FFT_SIZE; i++) fprintf(outfile, "%5d %15.5f,%15.5f\n", i, in[i].re, in[i].im); #endif -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) fftw_execute(p); #else fftw_one(p, in, out); @@ -892,7 +892,7 @@ static void generate_ad_edd(void) l = FFT_SIZE - (LINE_FILTER_SIZE - 1)/2; for (i = 0; i < LINE_FILTER_SIZE; i++) { - + #if defined(HAVE_FFTW3_H) impulse_responses[filter_sets][i] = out[l][0]/pw; #else @@ -1023,9 +1023,9 @@ int main(int argc, char *argv[]) generate_proakis(); generate_ad_edd(); - + fclose(outfile); - + if (argc > 1) { for (i = 0; i < LINE_FILTER_SIZE; i++) diff --git a/libs/spandsp/spandsp-sim/rfc2198_sim.c b/libs/spandsp/spandsp-sim/rfc2198_sim.c index b187ae6e15..6ecba89214 100644 --- a/libs/spandsp/spandsp-sim/rfc2198_sim.c +++ b/libs/spandsp/spandsp-sim/rfc2198_sim.c @@ -86,7 +86,7 @@ SPAN_DECLARE(int) rfc2198_sim_put(rfc2198_sim_state_t *s, memcpy(s->tx_pkt[s->next_pkt], buf, len); s->tx_pkt_len[s->next_pkt] = len; s->tx_pkt_seq_no[s->next_pkt] = seq_no; - + /* Construct the redundant packet */ p = buf2; slot = s->next_pkt; @@ -127,7 +127,7 @@ SPAN_DECLARE(int) rfc2198_sim_get(rfc2198_sim_state_t *s, uint8_t *p; uint16_t *q; int redundancy_depth; - + if (s->rx_queued_pkts) { /* We have some stuff from the last g1050_get() still to deliver */ diff --git a/libs/spandsp/spandsp-sim/spandsp/g1050.h b/libs/spandsp/spandsp-sim/spandsp/g1050.h index 731947b39c..687630e834 100644 --- a/libs/spandsp/spandsp-sim/spandsp/g1050.h +++ b/libs/spandsp/spandsp-sim/spandsp/g1050.h @@ -188,7 +188,7 @@ typedef struct /*! 3 seconds of predicted delays for the link */ double delays[3*G1050_TICKS_PER_SEC]; - + /*! A count of packets lost on the link. */ uint32_t lost_packets; /*! An extra debug count of packets lost on the link. */ diff --git a/libs/spandsp/spandsp-sim/spandsp/line_model.h b/libs/spandsp/spandsp-sim/spandsp/line_model.h index 550e8a80fe..8465d4b457 100644 --- a/libs/spandsp/spandsp-sim/spandsp/line_model.h +++ b/libs/spandsp/spandsp-sim/spandsp/line_model.h @@ -107,7 +107,7 @@ typedef struct float far_co_hybrid_echo; /*! DC offset impairment */ float dc_offset; - + /*! Mains pickup impairment */ int mains_interference; tone_gen_state_t mains_tone; @@ -122,7 +122,7 @@ typedef struct one_way_line_model_state_t line1; one_way_line_model_state_t line2; float fout1; - float fout2; + float fout2; } both_ways_line_model_state_t; #ifdef __cplusplus @@ -132,7 +132,7 @@ extern "C" SPAN_DECLARE_DATA extern const float *line_models[]; -SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s, +SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s, int16_t output1[], const int16_t input1[], int16_t output2[], @@ -142,7 +142,7 @@ SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s, SPAN_DECLARE(void) both_ways_line_model_set_dc(both_ways_line_model_state_t *s, float dc1, float dc2); SPAN_DECLARE(void) both_ways_line_model_set_mains_pickup(both_ways_line_model_state_t *s, int f, float level1, float level2); - + SPAN_DECLARE(both_ways_line_model_state_t *) both_ways_line_model_init(int model1, float noise1, float echo_level_cpe1, @@ -156,7 +156,7 @@ SPAN_DECLARE(both_ways_line_model_state_t *) both_ways_line_model_init(int model SPAN_DECLARE(int) both_ways_line_model_release(both_ways_line_model_state_t *s); -SPAN_DECLARE(void) one_way_line_model(one_way_line_model_state_t *s, +SPAN_DECLARE(void) one_way_line_model(one_way_line_model_state_t *s, int16_t output[], const int16_t input[], int samples); diff --git a/libs/spandsp/spandsp-sim/test_utils.c b/libs/spandsp/spandsp-sim/test_utils.c index f02d08de30..d37c8977bb 100644 --- a/libs/spandsp/spandsp-sim/test_utils.c +++ b/libs/spandsp/spandsp-sim/test_utils.c @@ -272,7 +272,7 @@ SPAN_DECLARE(void) ifft(complex_t data[], int len) SPAN_DECLARE(codec_munge_state_t *) codec_munge_init(int codec, int info) { codec_munge_state_t *s; - + if ((s = (codec_munge_state_t *) malloc(sizeof(*s)))) { switch (codec) @@ -362,7 +362,7 @@ SPAN_DECLARE(void) codec_munge(codec_munge_state_t *s, int16_t amp[], int len) static void sf_close_at_exit(void) { int i; - + for (i = 0; i < SF_MAX_HANDLE; i++) { if (sf_close_at_exit_list[i]) @@ -377,7 +377,7 @@ static void sf_close_at_exit(void) static int sf_record_handle(SNDFILE *handle) { int i; - + for (i = 0; i < SF_MAX_HANDLE; i++) { if (sf_close_at_exit_list[i] == NULL) @@ -448,7 +448,7 @@ SPAN_DECLARE(int) sf_close_telephony(SNDFILE *handle) { int res; int i; - + if ((res = sf_close(handle)) == 0) { for (i = 0; i < SF_MAX_HANDLE; i++) diff --git a/libs/spandsp/src/adsi.c b/libs/spandsp/src/adsi.c index 647bf371ab..44add41be0 100644 --- a/libs/spandsp/src/adsi.c +++ b/libs/spandsp/src/adsi.c @@ -88,7 +88,7 @@ static int adsi_tx_get_bit(void *user_data) { int bit; adsi_tx_state_t *s; - + s = (adsi_tx_state_t *) user_data; /* This is similar to the async. handling code in fsk.c, but a few special things are needed in the preamble, and postamble of an ADSI message. */ @@ -162,7 +162,7 @@ static int adsi_tx_get_bit(void *user_data) static int adsi_tdd_get_async_byte(void *user_data) { adsi_tx_state_t *s; - + s = (adsi_tx_state_t *) user_data; if (s->byte_no < s->msg_len) return s->msg[s->byte_no++]; @@ -241,7 +241,7 @@ static void adsi_rx_put_bit(void *user_data, int bit) { if (s->msg_len == 0) { - /* A message should start DLE SOH, but let's just check + /* A message should start DLE SOH, but let's just check we are starting with a DLE for now */ if (s->in_progress == (0x80 | DLE)) s->msg[s->msg_len++] = (uint8_t) s->in_progress; @@ -302,7 +302,7 @@ static void adsi_tdd_put_async_byte(void *user_data, int byte) { adsi_rx_state_t *s; uint8_t octet; - + s = (adsi_rx_state_t *) user_data; //printf("Rx bit %x\n", bit); if (byte < 0) @@ -604,7 +604,7 @@ SPAN_DECLARE(int) adsi_tx_put_message(adsi_tx_state_t *s, const uint8_t *msg, in i += len - 2; s->msg[i++] = DLE; s->msg[i++] = ETX; - + /* Set the parity bits */ for (j = 0; j < i; j++) { @@ -639,7 +639,7 @@ SPAN_DECLARE(int) adsi_tx_put_message(adsi_tx_state_t *s, const uint8_t *msg, in s->msg[len] = (uint8_t) ((-sum) & 0xFF); s->msg_len = len + 1; break; - } + } /* Prepare the bit sequencing */ s->byte_no = 0; s->bit_pos = 0; diff --git a/libs/spandsp/src/async.c b/libs/spandsp/src/async.c index 49e25fde23..4df12dffb6 100644 --- a/libs/spandsp/src/async.c +++ b/libs/spandsp/src/async.c @@ -212,7 +212,7 @@ SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data) { async_tx_state_t *s; int bit; - + s = (async_tx_state_t *) user_data; if (s->bitpos == 0) { @@ -281,7 +281,7 @@ SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s, s->stop_bits = stop_bits; if (parity != ASYNC_PARITY_NONE) s->stop_bits++; - + s->get_byte = get_byte; s->user_data = user_data; diff --git a/libs/spandsp/src/at_interpreter.c b/libs/spandsp/src/at_interpreter.c index 1203d3caa8..1878ab2ed6 100644 --- a/libs/spandsp/src/at_interpreter.c +++ b/libs/spandsp/src/at_interpreter.c @@ -211,7 +211,7 @@ SPAN_DECLARE(void) at_set_at_rx_mode(at_state_t *s, int new_mode) SPAN_DECLARE(void) at_put_response(at_state_t *s, const char *t) { uint8_t buf[3]; - + buf[0] = s->p.s_regs[3]; buf[1] = s->p.s_regs[4]; buf[2] = '\0'; @@ -375,7 +375,7 @@ SPAN_DECLARE(void) at_reset_call_info(at_state_t *s) { at_call_id_t *call_id; at_call_id_t *next; - + for (call_id = s->call_id; call_id; call_id = next) { next = call_id->next; @@ -424,7 +424,7 @@ SPAN_DECLARE(void) at_display_call_info(at_state_t *s) { snprintf(buf, sizeof(buf), - "%s=%s", + "%s=%s", (call_id->id) ? call_id->id : "NULL", (call_id->value) ? call_id->value : ""); at_put_response(s, buf); @@ -437,7 +437,7 @@ SPAN_DECLARE(void) at_display_call_info(at_state_t *s) static int parse_num(const char **s, int max_value) { int i; - + /* The spec. says no digits is valid, and should be treated as zero. */ i = 0; while (isdigit((int) **s)) @@ -454,7 +454,7 @@ static int parse_num(const char **s, int max_value) static int parse_hex_num(const char **s, int max_value) { int i; - + /* The spec. says a hex value is always 2 digits, and the alpha digits are upper case. */ i = 0; @@ -859,7 +859,7 @@ static int process_class1_cmd(at_state_t *s, const char **t) allowed = "24,48,72,73,74,96,97,98,121,122,145,146"; break; } - + val = -1; if (!parse_out(s, t, &val, 255, NULL, allowed)) return TRUE; @@ -4043,11 +4043,11 @@ static const char *at_cmd_plus_IBC(at_state_t *s, const char *t) /* 0: In-band control service disabled 1: In-band control service enabled, 7-bit codes allowed, and top bit insignificant 2; In-band control service enabled, 7-bit codes allowed, and 8-bit codes available - + Circuits 105, 106, 107, 108, 109, 110, 125, 132, 133, 135, 142 in that order. For each one: 0: disabled 1: enabled - + DCE line connect status reports: 0: disabled 1: enabled */ @@ -4081,9 +4081,9 @@ static const char *at_cmd_plus_IBM(at_state_t *s, const char *t) T3 = entire interval -- N*T2 7: report the first time when is exceeded, and then each time is exceeded, and then once more when the mark idle period ends; T3 = entire mark idle period -- N*T2 - T1 - + T1 in units of 10ms - + T2 in units of 10ms */ locations[0] = NULL; locations[1] = NULL; @@ -4106,7 +4106,7 @@ static const char *at_cmd_plus_ICF(at_state_t *s, const char *t) 4: 7 data 2 stop 5: 7 data 1 parity 1 stop 6: 7 data 1 stop - + Parity 0: Odd 1: Even @@ -4235,7 +4235,7 @@ static const char *at_cmd_plus_MS(at_state_t *s, const char *t) static const char *at_cmd_plus_MSC(at_state_t *s, const char *t) { /* V.250 6.4.8 - Seamless rate change enable */ - /* 0 Disables V.34 seamless rate change + /* 0 Disables V.34 seamless rate change 1 Enables V.34 seamless rate change */ /* TODO: */ t += 4; diff --git a/libs/spandsp/src/awgn.c b/libs/spandsp/src/awgn.c index b432901bb2..582959cc93 100644 --- a/libs/spandsp/src/awgn.c +++ b/libs/spandsp/src/awgn.c @@ -29,14 +29,14 @@ paper somewhere. I can't track down where I got the original from, so that due recognition can be given. The original had no explicit copyright notice, and I hope nobody objects to its use here. - + Having a reasonable Gaussian noise generator is pretty important for telephony testing (in fact, pretty much any DSP testing), and this one seems to have served me OK. Since the generation of Gaussian noise is only for test purposes, and not a core system component, I don't intend to worry excessively about copyright issues, unless someone worries me. - + The non-core nature of this code also explains why it is unlikely to ever be optimised. */ diff --git a/libs/spandsp/src/bell_r2_mf.c b/libs/spandsp/src/bell_r2_mf.c index 76b0049453..dba407cddd 100644 --- a/libs/spandsp/src/bell_r2_mf.c +++ b/libs/spandsp/src/bell_r2_mf.c @@ -647,10 +647,10 @@ SPAN_DECLARE(bell_mf_rx_state_t *) bell_mf_rx_init(bell_mf_rx_state_t *s, s->digits_callback = callback; s->digits_callback_data = user_data; - s->hits[0] = + s->hits[0] = s->hits[1] = s->hits[2] = - s->hits[3] = + s->hits[3] = s->hits[4] = 0; for (i = 0; i < 6; i++) @@ -730,7 +730,7 @@ SPAN_DECLARE(int) r2_mf_rx(r2_mf_rx_state_t *s, const int16_t amp[], int samples best = 1; second_best = 0; } - + for (i = 2; i < 6; i++) { energy[i] = goertzel_result(&s->out[i]); diff --git a/libs/spandsp/src/bert.c b/libs/spandsp/src/bert.c index 4ba0c335f7..a8ad5ad6b7 100644 --- a/libs/spandsp/src/bert.c +++ b/libs/spandsp/src/bert.c @@ -338,7 +338,7 @@ SPAN_DECLARE(void) bert_set_report(bert_state_t *s, int freq, bert_report_func_t s->report_frequency = freq; s->reporter = reporter; s->user_data = user_data; - + s->rx.report_countdown = s->report_frequency; } /*- End of function --------------------------------------------------------*/ @@ -487,7 +487,7 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern, } s->error_rate = 8; s->rx.measurement_step = MEASUREMENT_STEP; - + span_log_init(&s->logging, SPAN_LOG_NONE, NULL); span_log_set_protocol(&s->logging, "BERT"); diff --git a/libs/spandsp/src/fax.c b/libs/spandsp/src/fax.c index 9b68b00601..ef7e33433a 100644 --- a/libs/spandsp/src/fax.c +++ b/libs/spandsp/src/fax.c @@ -219,7 +219,7 @@ SPAN_DECLARE_NONSTD(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len) int len; #if defined(LOG_FAX_AUDIO) int required_len; - + required_len = max_len; #endif len = 0; @@ -236,7 +236,7 @@ SPAN_DECLARE_NONSTD(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len) { /* Pad to the requested length with silence */ memset(amp + len, 0, (max_len - len)*sizeof(int16_t)); - len = max_len; + len = max_len; } break; } @@ -248,7 +248,7 @@ SPAN_DECLARE_NONSTD(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len) { /* Pad to the requested length with silence */ memset(amp, 0, max_len*sizeof(int16_t)); - len = max_len; + len = max_len; } } #if defined(LOG_FAX_AUDIO) diff --git a/libs/spandsp/src/filter_tools.h b/libs/spandsp/src/filter_tools.h index 4df89adab4..cca1871cfd 100644 --- a/libs/spandsp/src/filter_tools.h +++ b/libs/spandsp/src/filter_tools.h @@ -48,7 +48,6 @@ void compute_raised_cosine_filter(double coeffs[], void compute_hilbert_transform(double coeffs[], int len); - #if defined(__cplusplus) } #endif diff --git a/libs/spandsp/src/g722.c b/libs/spandsp/src/g722.c index f2cca6b179..f223592dc8 100644 --- a/libs/spandsp/src/g722.c +++ b/libs/spandsp/src/g722.c @@ -367,7 +367,7 @@ SPAN_DECLARE(int) g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8 else if (wd1 > 18432) wd1 = 18432; s->band[0].nb = (int16_t) wd1; - + /* Block 3L, SCALEL */ wd1 = (s->band[0].nb >> 6) & 31; wd2 = 8 - (s->band[0].nb >> 11); @@ -375,7 +375,7 @@ SPAN_DECLARE(int) g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8 s->band[0].det = (int16_t) (wd3 << 2); block4(&s->band[0], dlow); - + if (!s->eight_k) { /* Block 2H, INVQAH */ @@ -394,7 +394,7 @@ SPAN_DECLARE(int) g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8 else if (wd1 > 22528) wd1 = 22528; s->band[1].nb = (int16_t) wd1; - + /* Block 3H, SCALEH */ wd1 = (s->band[1].nb >> 6) & 31; wd2 = 10 - (s->band[1].nb >> 11); @@ -566,7 +566,7 @@ SPAN_DECLARE(int) g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const s->band[0].det = (int16_t) (wd3 << 2); block4(&s->band[0], dlow); - + if (s->eight_k) { /* Just leave the high bits as zero */ diff --git a/libs/spandsp/src/g726.c b/libs/spandsp/src/g726.c index f4a9127a92..6be385fc5f 100644 --- a/libs/spandsp/src/g726.c +++ b/libs/spandsp/src/g726.c @@ -695,7 +695,7 @@ static uint8_t g726_16_encoder(g726_state_t *s, int16_t amp) int16_t dqsez; int16_t dq; int16_t i; - + sezi = predictor_zero(s); sei = sezi + predictor_pole(s); se = sei >> 1; @@ -711,7 +711,7 @@ static uint8_t g726_16_encoder(g726_state_t *s, int16_t amp) /* Pole prediction difference */ dqsez = sr + (sezi >> 1) - se; - + update(s, y, g726_16_witab[i], g726_16_fitab[i], dq, sr, dqsez); return (uint8_t) i; } @@ -773,7 +773,7 @@ static uint8_t g726_24_encoder(g726_state_t *s, int16_t amp) int16_t dq; int16_t i; int y; - + sezi = predictor_zero(s); sei = sezi + predictor_pole(s); se = sei >> 1; @@ -789,7 +789,7 @@ static uint8_t g726_24_encoder(g726_state_t *s, int16_t amp) /* Pole prediction difference */ dqsez = sr + (sezi >> 1) - se; - + update(s, y, g726_24_witab[i], g726_24_fitab[i], dq, sr, dqsez); return (uint8_t) i; } @@ -851,7 +851,7 @@ static uint8_t g726_32_encoder(g726_state_t *s, int16_t amp) int16_t dq; int16_t i; int y; - + sezi = predictor_zero(s); sei = sezi + predictor_pole(s); se = sei >> 1; @@ -930,7 +930,7 @@ static uint8_t g726_40_encoder(g726_state_t *s, int16_t amp) int16_t dq; int16_t i; int y; - + sezi = predictor_zero(s); sei = sezi + predictor_pole(s); se = sei >> 1; @@ -970,7 +970,7 @@ static int16_t g726_40_decoder(g726_state_t *s, uint8_t code) code &= 0x1F; sezi = predictor_zero(s); sei = sezi + predictor_pole(s); - + y = step_size(s); dq = reconstruct(code & 0x10, g726_40_dqlntab[code], y); diff --git a/libs/spandsp/src/gsm0610_decode.c b/libs/spandsp/src/gsm0610_decode.c index 783acda4b3..d3e21f390f 100644 --- a/libs/spandsp/src/gsm0610_decode.c +++ b/libs/spandsp/src/gsm0610_decode.c @@ -105,7 +105,7 @@ SPAN_DECLARE(int) gsm0610_unpack_none(gsm0610_frame_t *s, const uint8_t c[]) int i; int j; int k; - + i = 0; for (j = 0; j < 8; j++) s->LARc[j] = c[i++]; diff --git a/libs/spandsp/src/gsm0610_encode.c b/libs/spandsp/src/gsm0610_encode.c index c49ed1e93b..c9e5251ef0 100644 --- a/libs/spandsp/src/gsm0610_encode.c +++ b/libs/spandsp/src/gsm0610_encode.c @@ -57,7 +57,7 @@ /* The RPE-LTD coder works on a frame by frame basis. The length of the frame is equal to 160 samples. Some computations are done once per frame to produce at the output of the coder the - LARc[1..8] parameters which are the coded LAR coefficients and + LARc[1..8] parameters which are the coded LAR coefficients and also to realize the inverse filtering operation for the entire frame (160 samples of signal d[0..159]). These parts produce at the output of the coder: @@ -107,7 +107,7 @@ static void encode_a_frame(gsm0610_state_t *s, gsm0610_frame_t *f, const int16_t SPAN_DECLARE(int) gsm0610_set_packing(gsm0610_state_t *s, int packing) { s->packing = packing; - return 0; + return 0; } /*- End of function --------------------------------------------------------*/ @@ -147,7 +147,7 @@ SPAN_DECLARE(int) gsm0610_pack_none(uint8_t c[], const gsm0610_frame_t *s) int i; int j; int k; - + i = 0; for (j = 0; j < 8; j++) c[i++] = (uint8_t) s->LARc[j]; @@ -169,7 +169,7 @@ SPAN_DECLARE(int) gsm0610_pack_wav49(uint8_t c[], const gsm0610_frame_t *s) { uint16_t sr; int i; - + sr = 0; sr = (sr >> 6) | (s->LARc[0] << 10); sr = (sr >> 6) | (s->LARc[1] << 10); diff --git a/libs/spandsp/src/gsm0610_lpc.c b/libs/spandsp/src/gsm0610_lpc.c index a7173f2086..8d32edab6b 100644 --- a/libs/spandsp/src/gsm0610_lpc.c +++ b/libs/spandsp/src/gsm0610_lpc.c @@ -59,15 +59,15 @@ /* The number of left shifts needed to normalize the 32 bit variable x for positive values on the interval with minimum of - minimum of 1073741824 (01000000000000000000000000000000) and + minimum of 1073741824 (01000000000000000000000000000000) and maximum of 2147483647 (01111111111111111111111111111111) and for negative values on the interval with minimum of -2147483648 (-10000000000000000000000000000000) and maximum of -1073741824 ( -1000000000000000000000000000000). - + In order to normalize the result, the following operation must be done: norm_var1 = x << gsm0610_norm(x); - + (That's 'ffs', only from the left, not the right..) */ @@ -89,7 +89,7 @@ int16_t gsm0610_norm(int32_t x) /* (From p. 46, end of section 4.2.5) - + NOTE: The following lines gives [sic] one correct implementation of the div(num, denum) arithmetic operation. Compute div which is the integer division of num by denom: with @@ -188,7 +188,7 @@ static void gsm0610_vec_vsraw(const int16_t *p, int n, int bits) " addq $2,%%rdx;\n" /* now edx = top-2 */ " cmpq %%rdx,%%rsi;\n" " ja 2f;\n" - + " movzwl (%%rsi),%%eax;\n" " movd %%eax,%%mm0;\n" " paddsw %%mm2,%%mm0;\n" @@ -251,7 +251,7 @@ static void gsm0610_vec_vsraw(const int16_t *p, int n, int bits) " addl $2,%%edx;\n" /* now edx = top-2 */ " cmpl %%edx,%%esi;\n" " ja 2f;\n" - + " movzwl (%%esi),%%eax;\n" " movd %%eax,%%mm0;\n" " paddsw %%mm2,%%mm0;\n" @@ -283,7 +283,7 @@ static void autocorrelation(int16_t amp[GSM0610_FRAME_LEN], int32_t L_ACF[9]) int16_t *sp; int16_t sl; #endif - + /* The goal is to compute the array L_ACF[k]. The signal s[i] must be scaled in order to avoid an overflow situation. */ @@ -411,7 +411,7 @@ static void autocorrelation(int16_t amp[GSM0610_FRAME_LEN], int32_t L_ACF[9]) /* Rescaling of the array s[0..159] */ if (scalauto > 0) { - assert(scalauto <= 4); + assert(scalauto <= 4); for (k = 0; k < GSM0610_FRAME_LEN; k++) amp[k] <<= scalauto; /*endfor*/ @@ -480,7 +480,7 @@ static void reflection_coefficients(int32_t L_ACF[9], int16_t r[8]) /*endif*/ assert(*r != INT16_MIN); if (n == 8) - return; + return; /*endif*/ /* Schur recursion */ @@ -508,7 +508,7 @@ static void transform_to_log_area_ratios(int16_t r[8]) int i; /* The following scaling for r[..] and LAR[..] has been used: - + r[..] = integer (real_r[..]*32768.); -1 <= real_r < 1. LAR[..] = integer (real_LAR[..] * 16384); with -1.625 <= real_LAR <= 1.625 @@ -551,7 +551,7 @@ static void quantization_and_coding(int16_t LAR[8]) /* This procedure needs four tables; the following equations give the optimum scaling for the constants: - + A[0..7] = integer(real_A[0..7] * 1024) B[0..7] = integer(real_B[0..7] * 512) MAC[0..7] = maximum of the LARc[0..7] diff --git a/libs/spandsp/src/gsm0610_preprocess.c b/libs/spandsp/src/gsm0610_preprocess.c index d48d164f87..92ca2e30b3 100644 --- a/libs/spandsp/src/gsm0610_preprocess.c +++ b/libs/spandsp/src/gsm0610_preprocess.c @@ -53,18 +53,18 @@ /* 4.2.0 .. 4.2.3 PREPROCESSING SECTION - + After A-law to linear conversion (or directly from the A to D converter) the following scaling is assumed for input to the RPE-LTP algorithm: - + in: 0.1.....................12 S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.* - + Where S is the sign bit, v a valid bit, and * a "don't care" bit. The original signal is called sop[..] - - out: 0.1................... 12 + + out: 0.1................... 12 S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0 */ diff --git a/libs/spandsp/src/gsm0610_rpe.c b/libs/spandsp/src/gsm0610_rpe.c index c62d892ce7..68ddff3e1e 100644 --- a/libs/spandsp/src/gsm0610_rpe.c +++ b/libs/spandsp/src/gsm0610_rpe.c @@ -88,7 +88,7 @@ static void weighting_filter(int16_t x[40], "1:\n" " movq (%%rcx,%%rsi,2),%%mm0;\n" " pmaddwd %%mm1,%%mm0;\n" - + " movq 8(%%rcx,%%rsi,2),%%mm4;\n" " pmaddwd %%mm2,%%mm4;\n" " paddd %%mm4,%%mm0;\n" @@ -103,7 +103,7 @@ static void weighting_filter(int16_t x[40], " paddd %%mm5,%%mm0;\n" /* Add for roundoff */ " psrad $13,%%mm0;\n" - " packssdw %%mm0,%%mm0;\n" + " packssdw %%mm0,%%mm0;\n" " movd %%mm0,%%eax;\n" /* eax has result */ " movw %%ax,(%%rdi,%%rsi,2);\n" " incq %%rsi;\n" @@ -143,7 +143,7 @@ static void weighting_filter(int16_t x[40], "1:\n" " movq (%%ecx,%%esi,2),%%mm0;\n" " pmaddwd %%mm1,%%mm0;\n" - + " movq 8(%%ecx,%%esi,2),%%mm4;\n" " pmaddwd %%mm2,%%mm4;\n" " paddd %%mm4,%%mm0;\n" @@ -158,7 +158,7 @@ static void weighting_filter(int16_t x[40], " paddd %%mm5,%%mm0;\n" /* Add for roundoff */ " psrad $13,%%mm0;\n" - " packssdw %%mm0,%%mm0;\n" + " packssdw %%mm0,%%mm0;\n" " movd %%mm0,%%eax;\n" /* eax has result */ " movw %%ax,(%%edi,%%esi,2);\n" " incl %%esi;\n" @@ -175,8 +175,8 @@ static void weighting_filter(int16_t x[40], /* The coefficients of the weighting filter are stored in a table (see table 4.4). The following scaling is used: - - H[0..10] = integer(real_H[0..10] * 8192); + + H[0..10] = integer(real_H[0..10] * 8192); */ /* Initialization of a temporary working array wt[0...49] */ @@ -205,7 +205,7 @@ static void weighting_filter(int16_t x[40], #define STEP(i,H) (e[k + i] * (int32_t) H) /* Every one of these multiplications is done twice, - but I don't see an elegant way to optimize this. + but I don't see an elegant way to optimize this. Do you? */ result += STEP( 0, -134); @@ -446,14 +446,14 @@ static void apcm_quantization(int16_t xM[13], can be calculated by using the exponent and the mantissa part of xmaxc (logarithmic table). So, this method avoids any division and uses only a scaling - of the RPE samples by a function of the exponent. A direct + of the RPE samples by a function of the exponent. A direct multiplication by the inverse of the mantissa (NRFAC[0..7] found in table 4.5) gives the 3 bit coded version xMc[0..12] of the RPE samples. */ /* Direct computation of xMc[0..12] using table 4.5 */ assert(exp <= 4096 && exp >= -4096); - assert(mant >= 0 && mant <= 7); + assert(mant >= 0 && mant <= 7); temp1 = (int16_t) (6 - exp); /* Normalization by the exponent */ temp2 = gsm_NRFAC[mant]; /* Inverse mantissa */ diff --git a/libs/spandsp/src/gsm0610_short_term.c b/libs/spandsp/src/gsm0610_short_term.c index 226ac1f6eb..1eb46a7e97 100644 --- a/libs/spandsp/src/gsm0610_short_term.c +++ b/libs/spandsp/src/gsm0610_short_term.c @@ -97,7 +97,7 @@ static void decode_log_area_ratios(int16_t LARc[8], int16_t *LARpp) analysis and synthesis filters operate with four different sets of coefficients, derived from the previous set of decoded LARs(LARpp(j - 1)) and the actual set of decoded LARs (LARpp(j)) - + (Initial value: LARpp(j - 1)[1..8] = 0.) */ diff --git a/libs/spandsp/src/hdlc.c b/libs/spandsp/src/hdlc.c index 951b44eb7c..7733aa8280 100644 --- a/libs/spandsp/src/hdlc.c +++ b/libs/spandsp/src/hdlc.c @@ -81,7 +81,7 @@ static __inline__ void octet_set_and_count(hdlc_rx_state_t *s) { if (s->octet_count_report_interval == 0) return; - + /* If we are not in octet counting mode, we start it. If we are in octet counting mode, we update it. */ if (s->octet_counting_mode) @@ -465,7 +465,7 @@ SPAN_DECLARE_NONSTD(int) hdlc_tx_get_byte(hdlc_tx_state_t *s) { s->abort_octets = 0; return 0x7F; - } + } return s->idle_octet; } if (s->len) diff --git a/libs/spandsp/src/lpc10_analyse.c b/libs/spandsp/src/lpc10_analyse.c index 0db0f5ad21..e809d41ec8 100644 --- a/libs/spandsp/src/lpc10_analyse.c +++ b/libs/spandsp/src/lpc10_analyse.c @@ -78,7 +78,7 @@ static void remove_dc_bias(float speech[], int len, float sigout[]) static void eval_amdf(float speech[], int32_t lpita, - const int32_t tau[], + const int32_t tau[], int32_t ltau, int32_t maxlag, float amdf[], @@ -111,7 +111,7 @@ static void eval_amdf(float speech[], static void eval_highres_amdf(float speech[], int32_t lpita, - const int32_t tau[], + const int32_t tau[], int32_t ltau, float amdf[], int32_t *minptr, @@ -547,11 +547,10 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int { static const int32_t tau[60] = { - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 84, 88, 92, 96, - 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, - 148, 152, 156 + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 84, 88, 92, 96, + 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156 }; static const int32_t buflim[4] = { diff --git a/libs/spandsp/src/lpc10_decode.c b/libs/spandsp/src/lpc10_decode.c index 6746d2ceae..19860e149d 100644 --- a/libs/spandsp/src/lpc10_decode.c +++ b/libs/spandsp/src/lpc10_decode.c @@ -113,8 +113,9 @@ static void bsynz(lpc10_decode_state_t *s, { static const int32_t kexc[25] = { - 8, -16, 26, -48, 86, -162, 294, -502, 718, -728, 184, - 672, -610, -672, 184, 728, 718, 502, 294, 162, 86, 48, 26, 16, 8 + 8, -16, 26, -48, 86, -162, 294, -502, 718, -728, 184, + 672, -610, -672, 184, 728, 718, 502, 294, 162, 86, 48, + 26, 16, 8 }; int32_t i; int32_t j; @@ -217,11 +218,11 @@ static void bsynz(lpc10_decode_state_t *s, /* Synthesize a single pitch epoch */ static int pitsyn(lpc10_decode_state_t *s, - int voice[], + int voice[], int32_t *pitch, float *rms, float *rc, - int32_t ivuv[], + int32_t ivuv[], int32_t ipiti[], float *rmsi, float *rci, @@ -917,7 +918,7 @@ static void decode(lpc10_decode_state_t *s, /* If bit 2 of ICORF is set then smooth RMS and RC's, */ if ((icorf & bit[1]) != 0) { - if ((float) abs(s->drms[1] - s->drms[0]) >= corth[ixcor + 3] + if ((float) abs(s->drms[1] - s->drms[0]) >= corth[ixcor + 3] && (float) abs(s->drms[1] - s->drms[2]) >= corth[ixcor + 3]) { @@ -936,7 +937,7 @@ static void decode(lpc10_decode_state_t *s, /* If bit 3 of ICORF is set then smooth pitch */ if ((icorf & bit[2]) != 0) { - if ((float) abs(s->dpit[1] - s->dpit[0]) >= corth[ixcor - 1] + if ((float) abs(s->dpit[1] - s->dpit[0]) >= corth[ixcor - 1] && (float) abs(s->dpit[1] - s->dpit[2]) >= corth[ixcor - 1]) { @@ -1070,7 +1071,7 @@ SPAN_DECLARE(lpc10_decode_state_t *) lpc10_decode_init(lpc10_decode_state_t *s, s->dei[i] = 0.0f; for (i = 0; i < 3; i++) s->deo[i] = 0.0f; - + return s; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/lpc10_encdecs.h b/libs/spandsp/src/lpc10_encdecs.h index 1e276e374b..f146652ac4 100644 --- a/libs/spandsp/src/lpc10_encdecs.h +++ b/libs/spandsp/src/lpc10_encdecs.h @@ -38,13 +38,13 @@ void lpc10_placea(int32_t *ipitch, int32_t af, int32_t vwin[3][2], int32_t awin[3][2], - int32_t ewin[3][2], + int32_t ewin[3][2], int32_t lframe, int32_t maxwin); void lpc10_placev(int32_t *osbuf, int32_t *osptr, - int32_t oslen, + int32_t oslen, int32_t *obound, int32_t vwin[3][2], int32_t af, @@ -61,7 +61,7 @@ void lpc10_voicing(lpc10_encode_state_t *st, const int32_t buflim[], int32_t half, float *minamd, - float *maxamd, + float *maxamd, int32_t *mintau, float *ivrc, int32_t *obound); diff --git a/libs/spandsp/src/lpc10_encode.c b/libs/spandsp/src/lpc10_encode.c index 0ab0874a31..739734f866 100644 --- a/libs/spandsp/src/lpc10_encode.c +++ b/libs/spandsp/src/lpc10_encode.c @@ -111,11 +111,10 @@ static int encode(lpc10_encode_state_t *s, }; static const int32_t entau[60] = { - 19, 11, 27, 25, 29, 21, 23, 22, 30, 14, 15, 7, 39, 38, 46, - 42, 43, 41, 45, 37, 53, 49, 51, 50, 54, 52, 60, 56, 58, 26, - 90, 88, 92, 84, 86, 82, 83, 81, 85, 69, 77, 73, 75, 74, 78, - 70, 71, 67, 99, 97, 113, 112, 114, 98, 106, 104, 108, 100, - 101, 76 + 19, 11, 27, 25, 29, 21, 23, 22, 30, 14, 15, 7, 39, 38, 46, + 42, 43, 41, 45, 37, 53, 49, 51, 50, 54, 52, 60, 56, 58, 26, + 90, 88, 92, 84, 86, 82, 83, 81, 85, 69, 77, 73, 75, 74, 78, + 70, 71, 67, 99, 97, 113, 112, 114, 98, 106, 104, 108, 100, 101, 76 }; static const int32_t enadd[8] = { @@ -137,14 +136,14 @@ static int encode(lpc10_encode_state_t *s, }; static const int32_t rmst[64] = { - 1024, 936, 856, 784, 718, 656, 600, 550, 502, - 460, 420, 384, 352, 328, 294, 270, 246, 226, - 206, 188, 172, 158, 144, 132, 120, 110, 102, - 92, 84, 78, 70, 64, 60, 54, 50, - 46, 42, 38, 34, 32, 30, 26, 24, - 22, 20, 18, 17, 16, 15, 14, 13, - 12, 11, 10, 9, 8, 7, 6, 5, 4, - 3, 2, 1, 0 + 1024, 936, 856, 784, 718, 656, 600, 550, + 502, 460, 420, 384, 352, 328, 294, 270, + 246, 226, 206, 188, 172, 158, 144, 132, + 120, 110, 102, 92, 84, 78, 70, 64, + 60, 54, 50, 46, 42, 38, 34, 32, + 30, 26, 24, 22, 20, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0 }; int32_t idel; @@ -281,7 +280,7 @@ SPAN_DECLARE(lpc10_encode_state_t *) lpc10_encode_init(lpc10_encode_state_t *s, s->z21 = 0.0f; s->z12 = 0.0f; s->z22 = 0.0f; - + /* State used by function lpc10_analyse */ for (i = 0; i < 540; i++) { @@ -355,7 +354,7 @@ SPAN_DECLARE(lpc10_encode_state_t *) lpc10_encode_init(lpc10_encode_state_t *s, /* State used by function lpc10_pack */ s->isync = 0; - + return s; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/lpc10_placev.c b/libs/spandsp/src/lpc10_placev.c index 982b1d7c4e..f728d6fa63 100644 --- a/libs/spandsp/src/lpc10_placev.c +++ b/libs/spandsp/src/lpc10_placev.c @@ -56,7 +56,7 @@ void lpc10_placea(int32_t *ipitch, int32_t af, int32_t vwin[3][2], int32_t awin[3][2], - int32_t ewin[3][2], + int32_t ewin[3][2], int32_t lframe, int32_t maxwin) { @@ -69,7 +69,7 @@ void lpc10_placea(int32_t *ipitch, int32_t hrange; int ephase; int32_t lrange; - + lrange = (af - 2)*lframe + 1; hrange = af*lframe; @@ -181,7 +181,7 @@ void lpc10_placea(int32_t *ipitch, void lpc10_placev(int32_t *osbuf, int32_t *osptr, - int32_t oslen, + int32_t oslen, int32_t *obound, int32_t vwin[3][2], int32_t af, diff --git a/libs/spandsp/src/lpc10_voicing.c b/libs/spandsp/src/lpc10_voicing.c index db45c15602..90891f9cca 100644 --- a/libs/spandsp/src/lpc10_voicing.c +++ b/libs/spandsp/src/lpc10_voicing.c @@ -57,7 +57,7 @@ static void vparms(int32_t vwin[], int32_t half, float *dither, int32_t *mintau, - int32_t *zc, + int32_t *zc, int32_t *lbe, int32_t *fbe, float *qs, @@ -207,7 +207,7 @@ void lpc10_voicing(lpc10_encode_state_t *s, const int32_t buflim[], int32_t half, float *minamd, - float *maxamd, + float *maxamd, int32_t *mintau, float ivrc[], int32_t obound[]) @@ -250,7 +250,7 @@ void lpc10_voicing(lpc10_encode_state_t *s, int32_t lbe; float snr2; -#if (_MSC_VER >= 1400) +#if (_MSC_VER >= 1400) __analysis_assume(half >= 0 && half < 2); #endif inbuf_offset = 0; @@ -305,7 +305,7 @@ void lpc10_voicing(lpc10_encode_state_t *s, vparms(vwin, &inbuf[inbuf_offset], &lpbuf[lpbuf_offset], - buflim, + buflim, half, &s->dither, mintau, diff --git a/libs/spandsp/src/make_at_dictionary.c b/libs/spandsp/src/make_at_dictionary.c index a0d8e16eb4..7f05dd9b14 100644 --- a/libs/spandsp/src/make_at_dictionary.c +++ b/libs/spandsp/src/make_at_dictionary.c @@ -468,7 +468,7 @@ typedef struct static trie_node_t *trie_node_create(void) { trie_node_t *s; - + if ((s = (trie_node_t *) malloc(sizeof(*s)))) { memset(s, 0, sizeof(*s)); @@ -481,7 +481,7 @@ static trie_node_t *trie_node_create(void) static trie_t *trie_create(void) { trie_t *s; - + if ((s = (trie_t *) malloc(sizeof(*s)))) { memset(s, 0, sizeof(*s)); @@ -494,7 +494,7 @@ static trie_t *trie_create(void) static void trie_recursive_add_node_numbers(trie_node_t *t) { int index; - + if (t) { if (t->first <= t->last) @@ -516,7 +516,7 @@ static void trie_recursive_add_node_numbers(trie_node_t *t) static void trie_recursive_build_packed_trie(trie_node_t *t) { int i; - + if (t) { if (t->first <= t->last) @@ -551,7 +551,7 @@ static void trie_add(trie_t *s, const char *u, size_t len) { /* The character in u we are processing... */ index = (unsigned char) u[i]; - + /* Is there a child node for this character? */ if (t->child_list[index] == NULL) { @@ -561,7 +561,7 @@ static void trie_add(trie_t *s, const char *u, size_t len) if (index > t->last) t->last = index; } - + /* Move to the new node... and loop */ t = t->child_list[index]; } @@ -612,7 +612,7 @@ int main(int argc, char *argv[]) { trie_t *s; int i; - + s = trie_create(); for (i = 0; wordlist[i]; i++) diff --git a/libs/spandsp/src/make_cielab_luts.c b/libs/spandsp/src/make_cielab_luts.c index 905005674f..5fca6c7236 100644 --- a/libs/spandsp/src/make_cielab_luts.c +++ b/libs/spandsp/src/make_cielab_luts.c @@ -64,11 +64,11 @@ int main(int argc, char *argv[]) /* sRGB to Linear RGB */ r = (r > 0.04045f) ? powf((r + 0.055f)/1.055f, 2.4f) : r/12.92f; - + printf((i < 255) ? " %f,\n" : " %f\n", r); } printf("};\n"); - + printf("static const uint8_t linear_to_srgb[4096] =\n"); printf("{\n"); for (i = 0; i < 4096; i++) diff --git a/libs/spandsp/src/make_modem_filter.c b/libs/spandsp/src/make_modem_filter.c index 9bf49eb0aa..593f894cbf 100644 --- a/libs/spandsp/src/make_modem_filter.c +++ b/libs/spandsp/src/make_modem_filter.c @@ -112,7 +112,7 @@ static void make_tx_filter(int coeff_sets, for (i = 0; i < total_coeffs; i++) coeffs[i] *= scaling; } - + /* Churn out the data as a C source code header file, which can be directly included by the modem code. */ printf("#define TX_PULSESHAPER%s_GAIN %ff\n", tag, gain); diff --git a/libs/spandsp/src/math_fixed.c b/libs/spandsp/src/math_fixed.c index b627fe1719..b4d57a917d 100644 --- a/libs/spandsp/src/math_fixed.c +++ b/libs/spandsp/src/math_fixed.c @@ -227,7 +227,7 @@ SPAN_DECLARE(uint16_t) fixed_atan2(int16_t y, int16_t x) return ((y & 0x8000) | 0x4000); abs_x = abs(x); abs_y = abs(y); - + if (abs_y < abs_x) { recip = fixed_reciprocal16(abs_x, &shift); diff --git a/libs/spandsp/src/playout.c b/libs/spandsp/src/playout.c index 073c4bf96b..e98e48d70c 100644 --- a/libs/spandsp/src/playout.c +++ b/libs/spandsp/src/playout.c @@ -65,7 +65,7 @@ static playout_frame_t *queue_get(playout_state_t *s, timestamp_t sender_stamp) s->last_frame = NULL; } return frame; - } + } return NULL; } @@ -86,7 +86,7 @@ SPAN_DECLARE(timestamp_t) playout_current_length(playout_state_t *s) SPAN_DECLARE(playout_frame_t *) playout_get_unconditional(playout_state_t *s) { playout_frame_t *frame; - + if ((frame = queue_get(s, 0x7FFFFFFF))) { /* Put it on the free list */ @@ -127,7 +127,7 @@ SPAN_DECLARE(int) playout_get(playout_state_t *s, playout_frame_t *frameout, tim s->state_late += ((((frame->receiver_stamp > s->latest_expected) ? 0x10000000 : 0) - s->state_late) >> 8); s->state_just_in_time += ((((frame->receiver_stamp > s->latest_expected - frame->sender_len) ? 0x10000000 : 0) - s->state_just_in_time) >> 8); s->latest_expected += frame->sender_len; - + if (s->state_late > s->dropable_threshold) { if (s->since_last_step < 10) @@ -169,7 +169,7 @@ SPAN_DECLARE(int) playout_get(playout_state_t *s, playout_frame_t *frameout, tim s->state_just_in_time = s->dropable_threshold; s->state_late = 0; s->since_last_step = 0; - + s->last_speech_sender_stamp += s->last_speech_sender_len; } } @@ -181,12 +181,12 @@ SPAN_DECLARE(int) playout_get(playout_state_t *s, playout_frame_t *frameout, tim { /* Rewind last_speech_sender_stamp, since this isn't speech */ s->last_speech_sender_stamp -= s->last_speech_sender_len; - + *frameout = *frame; /* Put it on the free list */ frame->later = s->free_frames; s->free_frames = frame; - + s->frames_out++; return PLAYOUT_OK; } @@ -271,7 +271,7 @@ SPAN_DECLARE(int) playout_put(playout_state_t *s, void *data, int type, timestam /* Find where it should go in the queue */ p = s->last_frame; - while (sender_stamp < p->sender_stamp && p->earlier) + while (sender_stamp < p->sender_stamp && p->earlier) p = p->earlier; if (p->earlier) @@ -323,7 +323,7 @@ SPAN_DECLARE(void) playout_restart(playout_state_t *s, int min_length, int max_l s->start = TRUE; s->since_last_step = 0x7FFFFFFF; /* Start with the minimum buffer length allowed, and work from there */ - s->actual_buffer_length = + s->actual_buffer_length = s->target_buffer_length = (s->max_length - s->min_length)/2; } /*- End of function --------------------------------------------------------*/ @@ -344,7 +344,7 @@ SPAN_DECLARE(int) playout_release(playout_state_t *s) { playout_frame_t *frame; playout_frame_t *next; - + /* Free all the frames in the queue. In most cases these should have been removed already, so their associated data could be freed. */ for (frame = s->first_frame; frame; frame = next) @@ -367,7 +367,7 @@ SPAN_DECLARE(int) playout_free(playout_state_t *s) if (s) { playout_release(s); - /* Finally, free ourselves! */ + /* Finally, free ourselves! */ free(s); } return 0; diff --git a/libs/spandsp/src/plc.c b/libs/spandsp/src/plc.c index 3d07417f68..dcb07120e1 100644 --- a/libs/spandsp/src/plc.c +++ b/libs/spandsp/src/plc.c @@ -121,7 +121,7 @@ SPAN_DECLARE(int) plc_rx(plc_state_t *s, int16_t amp[], int len) float old_weight; float new_weight; float gain; - + if (s->missing_samples) { /* Although we have a real signal, we need to smooth it to fit well diff --git a/libs/spandsp/src/queue.c b/libs/spandsp/src/queue.c index 7430aa4100..264cee0c87 100644 --- a/libs/spandsp/src/queue.c +++ b/libs/spandsp/src/queue.c @@ -52,7 +52,7 @@ SPAN_DECLARE(int) queue_empty(queue_state_t *s) SPAN_DECLARE(int) queue_free_space(queue_state_t *s) { int len; - + if ((len = s->optr - s->iptr - 1) < 0) len += s->len; /*endif*/ @@ -63,7 +63,7 @@ SPAN_DECLARE(int) queue_free_space(queue_state_t *s) SPAN_DECLARE(int) queue_contents(queue_state_t *s) { int len; - + if ((len = s->iptr - s->optr) < 0) len += s->len; /*endif*/ @@ -83,7 +83,7 @@ SPAN_DECLARE(int) queue_view(queue_state_t *s, uint8_t *buf, int len) int to_end; int iptr; int optr; - + /* Snapshot the values (although only iptr should be changeable during this processing) */ iptr = s->iptr; optr = s->optr; @@ -134,7 +134,7 @@ SPAN_DECLARE(int) queue_read(queue_state_t *s, uint8_t *buf, int len) int new_optr; int iptr; int optr; - + /* Snapshot the values (although only iptr should be changeable during this processing) */ iptr = s->iptr; optr = s->optr; @@ -191,7 +191,7 @@ SPAN_DECLARE(int) queue_read_byte(queue_state_t *s) int iptr; int optr; int byte; - + /* Snapshot the values (although only iptr should be changeable during this processing) */ iptr = s->iptr; optr = s->optr; diff --git a/libs/spandsp/src/spandsp/ademco_contactid.h b/libs/spandsp/src/spandsp/ademco_contactid.h index 8e42d70256..abae8e701b 100644 --- a/libs/spandsp/src/spandsp/ademco_contactid.h +++ b/libs/spandsp/src/spandsp/ademco_contactid.h @@ -33,7 +33,7 @@ enum ADEMCO_CONTACTID_MESSAGE_TYPE_18 = 0x18, ADEMCO_CONTACTID_MESSAGE_TYPE_98 = 0x98 }; - + enum { ADEMCO_CONTACTID_QUALIFIER_NEW_EVENT = 1, diff --git a/libs/spandsp/src/spandsp/adsi.h b/libs/spandsp/src/spandsp/adsi.h index 0d5e30adfc..751f57c03d 100644 --- a/libs/spandsp/src/spandsp/adsi.h +++ b/libs/spandsp/src/spandsp/adsi.h @@ -47,16 +47,16 @@ in various formats. Currently, the supported formats are: - ETSI ETS 300 648, ETS 300 659-1 CLIP (Calling Line Identity Presentation) DTMF standard variant 1 (Belgium, Brazil, Denmark, Finland, Iceland, India, Netherlands, Saudi Arabia, Sweden and Uruguay). - + - ETSI ETS 300 648, ETS 300 659-1 CLIP (Calling Line Identity Presentation) DTMF standard variant 2 (Denmark and Holland). - + - ETSI ETS 300 648, ETS 300 659-1 CLIP (Calling Line Identity Presentation) DTMF standard variant 3. - + - ETSI ETS 300 648, ETS 300 659-1 CLIP (Calling Line Identity Presentation) DTMF standard variant 4. (Taiwan and Kuwait). - + - ETSI Caller-ID support in UK (British Telecom), British Telecomm SIN227, SIN242. - Nippon Telegraph & Telephone Corporation JCLIP (Japanese Calling Line Identity @@ -79,7 +79,7 @@ two rings. This silence period is long in the US, so the message fits easily. In other places, where the standard ring tone has much smaller silences, a line voltage reversal is used to wake up a power saving receiver, then the message is sent, then the phone begins to ring. - + The message is sent using a Bell 202 FSK modem. The data rate is 1200 bits per second. The message protocol uses 8-bit data words (bytes), each bounded by a start bit and a stop bit. @@ -87,34 +87,34 @@ by a start bit and a stop bit. Channel Carrier Message Message Data Checksum Seizure Signal Type Length Word(s) Word Signal Word Word - + \section adsi_page_sec_2a1 CHANNEL SEIZURE SIGNAL The channel seizure is 30 continuous bytes of 55h (01010101), including the start and stop bits (i.e. 300 bits of alternations in total). This provides a detectable alternating function to the CPE (i.e. the modem data pump). - + \section adsi_page_sec_2a2 CARRIER SIGNAL The carrier signal consists of 180 bits of 1s. This may be reduced to 80 bits of 1s for caller ID on call waiting. - + \section adsi_page_sec_2a3 MESSAGE TYPE WORD -Various message types are defined. The commonest ones for the US CLASS +Various message types are defined. The commonest ones for the US CLASS standard are: - Type 0x04 (SDMF) - single data message. Simple caller ID (CND) - Type 0x80 (MDMF) - multiple data message. A more flexible caller ID, with extra information. -Other messages support message waiting, for voice mail, and other display features. +Other messages support message waiting, for voice mail, and other display features. \section adsi_page_sec_2a4 MESSAGE LENGTH WORD The message length word specifies the total number of data words to follow. - + \section adsi_page_sec_2a5 DATA WORDS The data words contain the actual message. - + \section adsi_page_sec_2a6 CHECKSUM WORD The Checksum Word contains the twos complement of the modulo 256 sum of the other words in the data message (i.e., message type, @@ -177,7 +177,7 @@ while off hook. This results in a sequence - CPE hangs up on receipt of the caller ID message - The phone line rings a second time - The CPE answers a second time, connecting the called party with the caller. - + Timeouts are, obviously, required to ensure this system behaves well when the caller ID message or the second ring are missing. */ diff --git a/libs/spandsp/src/spandsp/arctan2.h b/libs/spandsp/src/spandsp/arctan2.h index f39257dc85..aefac60d67 100644 --- a/libs/spandsp/src/spandsp/arctan2.h +++ b/libs/spandsp/src/spandsp/arctan2.h @@ -107,7 +107,7 @@ static __inline__ float arctan2f(float y, float x) angle = 3.1415926f/2.0f - fx*fy/(y*y + 0.28125f*x*x); else angle = fy*fx/(x*x + 0.28125f*y*y); - + /* Deal with the quadrants, to bring the final answer to the range +-pi */ if (x < 0.0f) angle = 3.1415926f - angle; diff --git a/libs/spandsp/src/spandsp/awgn.h b/libs/spandsp/src/spandsp/awgn.h index 7f8b780273..e61ffc42db 100644 --- a/libs/spandsp/src/spandsp/awgn.h +++ b/libs/spandsp/src/spandsp/awgn.h @@ -29,14 +29,14 @@ paper somewhere. I can't track down where I got the original from, so that due recognition can be given. The original had no explicit copyright notice, and I hope nobody objects to its use here. - + Having a reasonable Gaussian noise generator is pretty important for telephony testing (in fact, pretty much any DSP testing), and this one seems to have served me OK. Since the generation of Gaussian noise is only for test purposes, and not a core system component, I don't intend to worry excessively about copyright issues, unless someone worries me. - + The non-core nature of this code also explains why it is unlikely to ever be optimised. */ @@ -47,20 +47,20 @@ \section awgn_page_sec_1 What does it do? Adding noise is not the most useful thing in most DSP applications, but it is -awfully useful for test suites. +awfully useful for test suites. \section awgn_page_sec_2 How does it work? This code is based on some demonstration code in a research paper somewhere. I can't track down where I got the original from, so that due recognition can be given. The original had no explicit copyright notice, and I hope nobody objects -to its use here. +to its use here. Having a reasonable Gaussian noise generator is pretty important for telephony testing (in fact, pretty much any DSP testing), and this one seems to have served me OK. Since the generation of Gaussian noise is only for test purposes, and not a core system component, I don't intend to worry excessively about -copyright issues, unless someone worries me. +copyright issues, unless someone worries me. The non-core nature of this code also explains why it is unlikely to ever be optimised. diff --git a/libs/spandsp/src/spandsp/bell_r2_mf.h b/libs/spandsp/src/spandsp/bell_r2_mf.h index 6421a36a41..98d9f749e8 100644 --- a/libs/spandsp/src/spandsp/bell_r2_mf.h +++ b/libs/spandsp/src/spandsp/bell_r2_mf.h @@ -31,7 +31,7 @@ /*! \page mfc_r2_tone_generation_page MFC/R2 tone generation \section mfc_r2_tone_generation_page_sec_1 What does it do? The MFC/R2 tone generation module provides for the generation of the -repertoire of 15 dual tones needs for the digital MFC/R2 signalling protocol. +repertoire of 15 dual tones needs for the digital MFC/R2 signalling protocol. \section mfc_r2_tone_generation_page_sec_2 How does it work? */ @@ -39,7 +39,7 @@ repertoire of 15 dual tones needs for the digital MFC/R2 signalling protocol. /*! \page bell_mf_tone_generation_page Bell MF tone generation \section bell_mf_tone_generation_page_sec_1 What does it do? The Bell MF tone generation module provides for the generation of the -repertoire of 15 dual tones needs for various Bell MF signalling protocols. +repertoire of 15 dual tones needs for various Bell MF signalling protocols. \section bell_mf_tone_generation_page_sec_2 How does it work? Basic Bell MF tone generation specs: @@ -53,7 +53,7 @@ Basic Bell MF tone generation specs: \section mfc_r2_tone_rx_page_sec_1 What does it do? The MFC/R2 tone receiver module provides for the detection of the -repertoire of 15 dual tones needs for the digital MFC/R2 signalling protocol. +repertoire of 15 dual tones needs for the digital MFC/R2 signalling protocol. It is compliant with ITU-T Q.441D. \section mfc_r2_tone_rx_page_sec_2 How does it work? @@ -79,7 +79,7 @@ Basic MFC/R2 tone detection specs: \section bell_mf_tone_rx_page_sec_1 What does it do? The Bell MF tone receiver module provides for the detection of the -repertoire of 15 dual tones needs for various Bell MF signalling protocols. +repertoire of 15 dual tones needs for various Bell MF signalling protocols. It is compliant with ITU-T Q.320, ITU-T Q.322, ITU-T Q.323B. \section bell_mf_tone_rx_page_sec_2 How does it work? @@ -132,7 +132,7 @@ extern "C" \param s The Bell MF generator context. \param amp The buffer for the generated signal. \param max_samples The required number of generated samples. - \return The number of samples actually generated. This may be less than + \return The number of samples actually generated. This may be less than max_samples if the input buffer empties. */ SPAN_DECLARE(int) bell_mf_tx(bell_mf_tx_state_t *s, int16_t amp[], int max_samples); diff --git a/libs/spandsp/src/spandsp/biquad.h b/libs/spandsp/src/spandsp/biquad.h index f17ca95fab..95e8517e1c 100644 --- a/libs/spandsp/src/spandsp/biquad.h +++ b/libs/spandsp/src/spandsp/biquad.h @@ -71,9 +71,9 @@ static __inline__ void biquad2_init(biquad2_state_t *bq, bq->a2 = a2; bq->b1 = b1; bq->b2 = b2; - + bq->z1 = 0; - bq->z2 = 0; + bq->z2 = 0; #if FIRST_ORDER_NOISE_SHAPING bq->residue = 0; @@ -88,14 +88,14 @@ static __inline__ int16_t biquad2(biquad2_state_t *bq, int16_t sample) { int32_t y; int32_t z0; - + z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2; y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2; bq->z2 = bq->z1; bq->z1 = z0 >> 15; #if FIRST_ORDER_NOISE_SHAPING - y += bq->residue; + y += bq->residue; bq->residue = y & 0x7FFF; #elif SECOND_ORDER_NOISE_SHAPING y += (2*bq->residue1 - bq->residue2); diff --git a/libs/spandsp/src/spandsp/bit_operations.h b/libs/spandsp/src/spandsp/bit_operations.h index 8ce3c44430..2deca2828a 100644 --- a/libs/spandsp/src/spandsp/bit_operations.h +++ b/libs/spandsp/src/spandsp/bit_operations.h @@ -144,7 +144,7 @@ static __inline__ int top_bit(unsigned int bits) static __inline__ int bottom_bit(unsigned int bits) { int res; - + #if defined(SPANDSP_USE_86_ASM) __asm__ (" xorl %[res],%[res];\n" " decl %[res];\n" diff --git a/libs/spandsp/src/spandsp/g168models.h b/libs/spandsp/src/spandsp/g168models.h index 1bc728e300..4e71112eef 100644 --- a/libs/spandsp/src/spandsp/g168models.h +++ b/libs/spandsp/src/spandsp/g168models.h @@ -43,12 +43,12 @@ const int32_t line_model_d2_coeffs[] = { -436, -829, -2797, -4208, -17968, -11215, 46150, 34480, -10427, 9049, -1309, -6320, 390, -8191, -1751, -6051, - -3796, -4055, -3948, -2557, -3372, -1808, -2259, -1300, + -3796, -4055, -3948, -2557, -3372, -1808, -2259, -1300, -1098, -618, -340, -61, 323, 419, 745, 716, 946, 880, 1014, 976, 1033, 1091, 1053, 1042, - 794, 831, 899, 716, 390, 313, 304, 304, + 794, 831, 899, 716, 390, 313, 304, 304, 73, -119, -109, -176, -359, -407, -512, -580, - -704, -618, -685, -791, -772, -820, -839, -724 + -704, -618, -685, -791, -772, -820, -839, -724 }; #define LINE_MODEL_D2_GAIN 1.39E-5f @@ -114,16 +114,16 @@ const int32_t line_model_d5_coeffs[] = -4470, 25356, 11458, -19696, -11800, 5766, 789, 6633, 14624, -6975, -17156, -187, 149, 1515, 14907, 4345, -7128, -2757, -10185, -7083, 6850, 3944, 6969, 8694, - -4068, -3852, -5793, -9371, 453, 1060, 3965, 9463, + -4068, -3852, -5793, -9371, 453, 1060, 3965, 9463, 2393, 2784, -892, -7366, -3376, -5847, -2399, 3011, 1537, 6623, 4205, 1602, 1592, -4752, -3646, -5207, - -5577, -501, -1174, 4041, 5647, 4628, 7252, 2123, + -5577, -501, -1174, 4041, 5647, 4628, 7252, 2123, 2654, -881, -4113, -3244, -7289, -3830, -4600, -2508, 431, -144, 4184, 2372, 4617, 3576, 2382, 2839, - -404, 539, -1803, -1401, -1705, -2269, -783, -1608, + -404, 539, -1803, -1401, -1705, -2269, -783, -1608, -220, -306, 257, 615, 225, 561, 8, 344, 127, -57, 182, 41, 203, -111, 95, -79, - 30, 84, -13, -68, -241, -68, -24, 19, + 30, 84, -13, -68, -241, -68, -24, 19, -57, -24, 30, -68, 84, -155, -68, 19 }; #define LINE_MODEL_D5_GAIN 1.77E-5f @@ -145,7 +145,7 @@ const int32_t line_model_d6_coeffs[] = -821, -2068, -2236, -4283, -3406, -5022, -4039, -4842, -4104, -4089, -3582, -2978, -2734, -1805, -1608, -645, -495, 279, 471, 947, 1186, 1438, 1669, 1640, - 1901, 1687, 1803, 1543, 1566, 1342, 1163, 963, + 1901, 1687, 1803, 1543, 1566, 1342, 1163, 963, 733, 665, 323, 221, -14, -107, -279, -379, -468, -513, -473, -588, -612, -652, -616, -566, -515, -485, -404, -344, -290, -202, -180, -123 @@ -171,7 +171,7 @@ const int32_t line_model_d7_coeffs[] = 3946, 4414, 4026, 3005, 3380, 1616, 2007, 158, 388, -1198, -1117, -2134, -2547, -2589, -3310, -2778, -3427, -2779, -3116, -2502, -2399, -1956, -1539, -1239, - -570, -377, 251, 331, 964, 1177, 1449, 1564, + -570, -377, 251, 331, 964, 1177, 1449, 1564, 1724, 1871, 1767, 1802, 1630, 1632, 1379, 1271, 1063, 856, 711, 482, 289, 54, -137, -321, -490, -638, -764, -836, -800, -859, -838, -837, @@ -196,7 +196,7 @@ const int32_t line_model_d8_coeffs[] = -16854, -3115, 9483, -17799, 7399, -4342, -7415, 7929, -10726, 6239, -2526, -1317, 5345, -4565, 6868, -2195, 3425, 1969, -109, 3963, -1275, 3087, -892, 1239, - 2, -427, 596, -1184, 551, -1244, 141, -743, + 2, -427, 596, -1184, 551, -1244, 141, -743, -415, -372, -769, -183, -785, -270, -659, -377, -523, -325, -245, -255, -60, 35, 218, 149, 340, 233, 365, 303, 251, 230, 209, 179 diff --git a/libs/spandsp/src/spandsp/g711.h b/libs/spandsp/src/spandsp/g711.h index a2e094843e..1e2a7f652c 100644 --- a/libs/spandsp/src/spandsp/g711.h +++ b/libs/spandsp/src/spandsp/g711.h @@ -33,7 +33,7 @@ these routines are slow in C, is the lack of direct access to the CPU's "find the first 1" instruction. A little in-line assembler fixes that, and the conversion routines can be faster than lookup tables, in most real world usage. A "find the first 1" instruction is available on most modern CPUs, and is a -much underused feature. +much underused feature. If an assembly language method of bit searching is not available, these routines revert to a method that can be a little slow, so the cache thrashing might not @@ -82,7 +82,7 @@ extern "C" * segment, but a little inline assembly can fix that on an i386, x86_64 and * many other modern processors. */ - + /* * Mu-law is basically as follows: * @@ -162,7 +162,7 @@ static __inline__ uint8_t linear_to_ulaw(int linear) static __inline__ int16_t ulaw_to_linear(uint8_t ulaw) { int t; - + /* Complement to obtain normal u-law value. */ ulaw = ~ulaw; /* @@ -203,7 +203,7 @@ static __inline__ uint8_t linear_to_alaw(int linear) { int mask; int seg; - + if (linear >= 0) { /* Sign (bit 7) bit = 1 */ diff --git a/libs/spandsp/src/spandsp/modem_connect_tones.h b/libs/spandsp/src/spandsp/modem_connect_tones.h index 3ac5be361e..7c2b980753 100644 --- a/libs/spandsp/src/spandsp/modem_connect_tones.h +++ b/libs/spandsp/src/spandsp/modem_connect_tones.h @@ -24,7 +24,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ #if !defined(_SPANDSP_MODEM_CONNECT_TONES_H_) @@ -50,7 +50,7 @@ unfiltered energy, then a large proportion of the energy must be at the notch frequency. This type of detector may seem less intuitive than using a narrow bandpass filter to isolate the energy at the notch freqency. However, a sharp bandpass implemented as an IIR filter rings badly. The reciprocal notch filter -is very well behaved for our purpose. +is very well behaved for our purpose. */ enum diff --git a/libs/spandsp/src/spandsp/modem_echo.h b/libs/spandsp/src/spandsp/modem_echo.h index acfe7506a2..2f19f0bd18 100644 --- a/libs/spandsp/src/spandsp/modem_echo.h +++ b/libs/spandsp/src/spandsp/modem_echo.h @@ -37,7 +37,7 @@ This module aims to cancel electrical echoes (e.g. from 2-4 wire hybrids) in modem applications. It is not very suitable for speech applications, which require additional refinements for satisfactory performance. It is, however, more -efficient and better suited to modem applications. +efficient and better suited to modem applications. \section modem_echo_can_page_sec_2 How does it work? The heart of the echo cancellor is an adaptive FIR filter. This is adapted to @@ -48,14 +48,14 @@ FIR filter. The resulting output is an estimate of the echo signal. This is then subtracted from the received signal, and the result should be an estimate of the signal which originates within the environment being cancelled (people talking in the room, or the signal from the far end of a telephone line) free -from the echos of our own transmitted signal. +from the echos of our own transmitted signal. The FIR filter is adapted using the least mean squares (LMS) algorithm. This algorithm is attributed to Widrow and Hoff, and was introduced in 1960. It is the commonest form of filter adaption used in things like modem line equalisers and line echo cancellers. It works very well if the signal level is constant, which is true for a modem signal. To ensure good performa certain conditions must -be met: +be met: - The transmitted signal has weak self-correlation. - There is no signal being generated within the environment being cancelled. @@ -67,13 +67,13 @@ transmitting something highly correlative (e.g. tones, like DTMF), the adaption can go seriously wrong. The reason is there is only one solution for the adaption on a near random signal. For a repetitive signal, there are a number of solutions which converge the adaption, and nothing guides the adaption to choose -the correct one. +the correct one. \section modem_echo_can_page_sec_3 How do I use it? The echo cancellor processes both the transmit and receive streams sample by sample. The processing function is not declared inline. Unfortunately, cancellation requires many operations per sample, so the call overhead is only a -minor burden. +minor burden. */ #include "fir.h" diff --git a/libs/spandsp/src/spandsp/private/ademco_contactid.h b/libs/spandsp/src/spandsp/private/ademco_contactid.h index bada9193a1..f38b50a4b3 100644 --- a/libs/spandsp/src/spandsp/private/ademco_contactid.h +++ b/libs/spandsp/src/spandsp/private/ademco_contactid.h @@ -77,7 +77,7 @@ struct ademco_contactid_sender_state_s int tx_digits_len; /*! \brief The number of consecutive retries. */ int tries; - + int tone_state; int duration; int last_hit; diff --git a/libs/spandsp/src/spandsp/private/adsi.h b/libs/spandsp/src/spandsp/private/adsi.h index 676e05ab40..f1d3d06a27 100644 --- a/libs/spandsp/src/spandsp/private/adsi.h +++ b/libs/spandsp/src/spandsp/private/adsi.h @@ -71,7 +71,7 @@ struct adsi_tx_state_s int stop_bits; /*! */ int baudot_shift; - + /*! */ logging_state_t logging; }; @@ -106,7 +106,7 @@ struct adsi_rx_state_s int msg_len; /*! */ int baudot_shift; - + /*! A count of the framing errors. */ int framing_errors; diff --git a/libs/spandsp/src/spandsp/private/at_interpreter.h b/libs/spandsp/src/spandsp/private/at_interpreter.h index 5cda92e4ec..a60a9aa46e 100644 --- a/libs/spandsp/src/spandsp/private/at_interpreter.h +++ b/libs/spandsp/src/spandsp/private/at_interpreter.h @@ -80,7 +80,7 @@ struct at_state_s int rx_window; /*! Value set by +EWIND */ int tx_window; - + int v8bis_signal; int v8bis_1st_message; int v8bis_2nd_message; diff --git a/libs/spandsp/src/spandsp/private/g722.h b/libs/spandsp/src/spandsp/private/g722.h index 5cb2e0b77f..74ee517f3f 100644 --- a/libs/spandsp/src/spandsp/private/g722.h +++ b/libs/spandsp/src/spandsp/private/g722.h @@ -98,7 +98,7 @@ struct g722_decode_state_s int ptr; g722_band_t band[2]; - + uint32_t in_buffer; int in_bits; uint32_t out_buffer; diff --git a/libs/spandsp/src/spandsp/private/g726.h b/libs/spandsp/src/spandsp/private/g726.h index 9d69d00ec2..48b4454858 100644 --- a/libs/spandsp/src/spandsp/private/g726.h +++ b/libs/spandsp/src/spandsp/private/g726.h @@ -56,7 +56,7 @@ struct g726_state_s int16_t dml; /*! Linear weighting coefficient of 'yl' and 'yu'. */ int16_t ap; - + /*! Coefficients of pole portion of prediction filter. */ int16_t a[2]; /*! Coefficients of zero portion of prediction filter. */ @@ -71,7 +71,7 @@ struct g726_state_s int16_t sr[2]; /*! Delayed tone detect */ int td; - + /*! \brief The bit stream processing context. */ bitstream_state_t bs; diff --git a/libs/spandsp/src/spandsp/private/gsm0610.h b/libs/spandsp/src/spandsp/private/gsm0610.h index 103a6ebd2c..466be71207 100644 --- a/libs/spandsp/src/spandsp/private/gsm0610.h +++ b/libs/spandsp/src/spandsp/private/gsm0610.h @@ -54,7 +54,7 @@ struct gsm0610_state_s int16_t v[9]; /*! Decoder postprocessing */ int16_t msr; - + /*! Encoder data */ int16_t e[50]; }; diff --git a/libs/spandsp/src/spandsp/private/lpc10.h b/libs/spandsp/src/spandsp/private/lpc10.h index ae9b9528bb..b61893637c 100644 --- a/libs/spandsp/src/spandsp/private/lpc10.h +++ b/libs/spandsp/src/spandsp/private/lpc10.h @@ -44,7 +44,7 @@ struct lpc10_encode_state_s float z12; /*! \brief ??? */ float z22; - + /* State used by function lpc10_analyse */ /*! \brief ??? */ float inbuf[LPC10_SAMPLES_PER_FRAME*3]; diff --git a/libs/spandsp/src/spandsp/private/modem_connect_tones.h b/libs/spandsp/src/spandsp/private/modem_connect_tones.h index feb602bdef..c1c33d25a4 100644 --- a/libs/spandsp/src/spandsp/private/modem_connect_tones.h +++ b/libs/spandsp/src/spandsp/private/modem_connect_tones.h @@ -24,7 +24,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ #if !defined(_SPANDSP_PRIVATE_MODEM_CONNECT_TONES_H_) diff --git a/libs/spandsp/src/spandsp/private/sig_tone.h b/libs/spandsp/src/spandsp/private/sig_tone.h index 1bbeef0466..e7c6217051 100644 --- a/libs/spandsp/src/spandsp/private/sig_tone.h +++ b/libs/spandsp/src/spandsp/private/sig_tone.h @@ -218,7 +218,7 @@ struct sig_tone_rx_state_s int flat_mode_timeout; /*! \brief ??? */ int notch_insertion_timeout; - + /*! \brief ??? */ int signalling_state; /*! \brief ??? */ diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index 47574360ec..b1bef5d112 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.h @@ -45,7 +45,7 @@ struct t30_state_s /*! \brief TRUE if behaving as the calling party */ int calling_party; - + /*! \brief Internet aware FAX mode bit mask. */ int iaf; /*! \brief A bit mask of the currently supported modem types. */ @@ -212,7 +212,7 @@ struct t30_state_s /*! \brief TRUE once the far end FAX entity has been detected. */ int far_end_detected; - + /*! \brief TRUE once the end of procedure condition has been detected. */ int end_of_procedure_detected; @@ -250,7 +250,7 @@ struct t30_state_s int16_t ecm_len[256]; /*! \brief A bit map of the OK ECM frames, constructed as a PPR frame. */ uint8_t ecm_frame_map[3 + 32]; - + /*! \brief The current page number for receiving, in ECM or non-ECM mode. This is reset at the start of a call. */ int rx_page_number; /*! \brief The current page number for sending, in ECM or non-ECM mode. This is reset at the start of a call. */ diff --git a/libs/spandsp/src/spandsp/private/t30_dis_dtc_dcs_bits.h b/libs/spandsp/src/spandsp/private/t30_dis_dtc_dcs_bits.h index 4ff7cf0a46..9ec15f5f27 100644 --- a/libs/spandsp/src/spandsp/private/t30_dis_dtc_dcs_bits.h +++ b/libs/spandsp/src/spandsp/private/t30_dis_dtc_dcs_bits.h @@ -221,16 +221,16 @@ /* In a DIS/DTC frame, setting bit 97 to "0" indicates that the called terminal does not have the capability to accept 300 pels/25.4 mm x 300 lines/25.4 mm or 400 pels/25.4 mm x 400 lines/25.4 mm resolutions for colour/gray-scale images or T.44 Mixed Raster Content (MRC) mask layer. - + Setting bit 97 to "1" indicates that the called terminal does have the capability to accept 300 pels/25.4 mm x 300 lines/25.4 mm or 400 pels/25.4 mm x 400 lines/25.4 mm resolutions for colour/gray-scale images and MRC mask layer. Bit 97 is valid only when bits 68 and 42 or 43 (300 pels/25.4 mm x 300 lines/25.4 mm or 400 pels/25.4 mm x 400 lines/25.4 mm) are set to "1". - + In a DCS frame, setting bit 97 to "0" indicates that the calling terminal does not use 300 pels/25.4 mm x 300 lines/25.4 mm or 400 pels/25.4 mm x 400 lines/25.4 mm resolutions for colour/gray-scale images and mask layer. - + Setting bit 97 to "1" indicates that the calling terminal uses 300 pels/25.4 mm x 300 lines/25.4 mm or 400 pels/25.4 mm x 400 lines/25.4 mm resolutions for colour/gray-scale images and MRC mask layer. Bit 97 is valid only when bits 68 and 42 or 43 (300 pels/25.4 mm x 300 lines/25.4 mm and diff --git a/libs/spandsp/src/spandsp/private/t38_core.h b/libs/spandsp/src/spandsp/private/t38_core.h index e965ca6f40..40123128af 100644 --- a/libs/spandsp/src/spandsp/private/t38_core.h +++ b/libs/spandsp/src/spandsp/private/t38_core.h @@ -54,7 +54,7 @@ struct t38_core_state_s Method 2: Transfer of TCF is required for use with UDP (UDPTL or RTP). Method 2 is not recommended for use with TCP. */ int data_rate_management_method; - + /*! \brief The emitting gateway may indicate a preference for either UDP/UDPTL, or UDP/RTP, or TCP for transport of T.38 IFP Packets. The receiving device selects the transport protocol. */ @@ -81,7 +81,7 @@ struct t38_core_state_s int max_buffer_size; /*! \brief This option indicates the maximum size of a UDPTL packet or the - maximum size of the payload within an RTP packet that can be accepted + maximum size of the payload within an RTP packet that can be accepted by the remote device. */ int max_datagram_size; @@ -102,7 +102,7 @@ struct t38_core_state_s over TCP they are not relevent. */ int check_sequence_numbers; - /*! \brief The number of times each packet type will be sent (low byte). The + /*! \brief The number of times each packet type will be sent (low byte). The depth of redundancy (2nd byte). Higher numbers may increase reliability for UDP transmission. Zero is valid for the indicator packet category, to suppress all indicator packets (typicaly for TCP transmission). */ diff --git a/libs/spandsp/src/spandsp/private/t4_rx.h b/libs/spandsp/src/spandsp/private/t4_rx.h index 44eb2d2664..3004d348b7 100644 --- a/libs/spandsp/src/spandsp/private/t4_rx.h +++ b/libs/spandsp/src/spandsp/private/t4_rx.h @@ -71,15 +71,15 @@ typedef struct int y_resolution; /* "Background" information about the FAX, which can be stored in the image file. */ - /*! \brief The vendor of the machine which produced the file. */ + /*! \brief The vendor of the machine which produced the file. */ const char *vendor; - /*! \brief The model of machine which produced the file. */ + /*! \brief The model of machine which produced the file. */ const char *model; - /*! \brief The remote end's ident string. */ + /*! \brief The remote end's ident string. */ const char *far_ident; - /*! \brief The FAX sub-address. */ + /*! \brief The FAX sub-address. */ const char *sub_address; - /*! \brief The FAX DCS information, as an ASCII hex string. */ + /*! \brief The FAX DCS information, as an ASCII hex string. */ const char *dcs; } t4_rx_metadata_t; @@ -102,7 +102,7 @@ struct t4_rx_state_s /*! \brief The type of compression used between the FAX machines. */ int line_encoding; - + /*! \brief The width of the current page, in pixels. */ uint32_t image_width; diff --git a/libs/spandsp/src/spandsp/private/t4_tx.h b/libs/spandsp/src/spandsp/private/t4_tx.h index afc44fcf53..6f2fd12349 100644 --- a/libs/spandsp/src/spandsp/private/t4_tx.h +++ b/libs/spandsp/src/spandsp/private/t4_tx.h @@ -128,7 +128,7 @@ struct t4_tx_state_s in no header line. */ const char *header_info; /*! \brief The local ident string. This is used with header_info to form a - page header line. */ + page header line. */ const char *local_ident; /*! \brief The page number of current page. The first page is zero. If FAX page headers are used, the page number in the header will be one more than diff --git a/libs/spandsp/src/spandsp/private/v17rx.h b/libs/spandsp/src/spandsp/private/v17rx.h index 9f22208e80..2082722fd6 100644 --- a/libs/spandsp/src/spandsp/private/v17rx.h +++ b/libs/spandsp/src/spandsp/private/v17rx.h @@ -180,7 +180,7 @@ struct v17_rx_state_s /*! \brief The carrier update rate saved for reuse when using short training. */ int32_t carrier_phase_rate_save; - /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ + /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ power_meter_t power; /*! \brief The power meter level at which carrier on is declared. */ int32_t carrier_on_power; diff --git a/libs/spandsp/src/spandsp/private/v17tx.h b/libs/spandsp/src/spandsp/private/v17tx.h index f6c9d21343..3e2fff6d2c 100644 --- a/libs/spandsp/src/spandsp/private/v17tx.h +++ b/libs/spandsp/src/spandsp/private/v17tx.h @@ -94,7 +94,7 @@ struct v17_tx_state_s int32_t carrier_phase_rate; /*! \brief The current fractional phase of the baud timing. */ int baud_phase; - + /*! \brief The current number of data bits per symbol. This does not include the redundant bit. */ int bits_per_symbol; diff --git a/libs/spandsp/src/spandsp/private/v18.h b/libs/spandsp/src/spandsp/private/v18.h index b51a899ec6..086262c720 100644 --- a/libs/spandsp/src/spandsp/private/v18.h +++ b/libs/spandsp/src/spandsp/private/v18.h @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + #if !defined(_SPANDSP_PRIVATE_V18_H_) #define _SPANDSP_PRIVATE_V18_H_ diff --git a/libs/spandsp/src/spandsp/private/v22bis.h b/libs/spandsp/src/spandsp/private/v22bis.h index 5a03cb79f8..c0da6b0aa6 100644 --- a/libs/spandsp/src/spandsp/private/v22bis.h +++ b/libs/spandsp/src/spandsp/private/v22bis.h @@ -128,7 +128,7 @@ struct v22bis_state_s routine. */ void *qam_user_data; - /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ + /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ power_meter_t rx_power; /*! \brief The power meter level at which carrier on is declared. */ int32_t carrier_on_power; @@ -192,7 +192,7 @@ struct v22bis_state_s int total_baud_timing_correction; /*! \brief The current fractional phase of the baud timing. */ int baud_phase; - + int sixteen_way_decisions; int pattern_repeats; diff --git a/libs/spandsp/src/spandsp/private/v27ter_rx.h b/libs/spandsp/src/spandsp/private/v27ter_rx.h index e10781f72e..fbec14c5ed 100644 --- a/libs/spandsp/src/spandsp/private/v27ter_rx.h +++ b/libs/spandsp/src/spandsp/private/v27ter_rx.h @@ -158,7 +158,7 @@ struct v27ter_rx_state_s /*! \brief The carrier update rate saved for reuse when using short training. */ int32_t carrier_phase_rate_save; - /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ + /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ power_meter_t power; /*! \brief The power meter level at which carrier on is declared. */ int32_t carrier_on_power; diff --git a/libs/spandsp/src/spandsp/private/v27ter_tx.h b/libs/spandsp/src/spandsp/private/v27ter_tx.h index 5d8d41f842..ba9ab8b5aa 100644 --- a/libs/spandsp/src/spandsp/private/v27ter_tx.h +++ b/libs/spandsp/src/spandsp/private/v27ter_tx.h @@ -67,7 +67,7 @@ struct v27ter_tx_state_s /*! \brief Current offset into the RRC pulse shaping filter buffer. */ int rrc_filter_step; - + /*! \brief The register for the training and data scrambler. */ uint32_t scramble_reg; /*! \brief A counter for the number of consecutive bits of repeating pattern through diff --git a/libs/spandsp/src/spandsp/private/v29rx.h b/libs/spandsp/src/spandsp/private/v29rx.h index 385c787dd6..fd931af0f8 100644 --- a/libs/spandsp/src/spandsp/private/v29rx.h +++ b/libs/spandsp/src/spandsp/private/v29rx.h @@ -163,7 +163,7 @@ struct v29_rx_state_s /*! \brief The carrier update rate saved for reuse when using short training. */ int32_t carrier_phase_rate_save; - /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ + /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ power_meter_t power; /*! \brief The power meter level at which carrier on is declared. */ int32_t carrier_on_power; diff --git a/libs/spandsp/src/spandsp/private/v42bis.h b/libs/spandsp/src/spandsp/private/v42bis.h index 2c801ebe24..967b1fd909 100644 --- a/libs/spandsp/src/spandsp/private/v42bis.h +++ b/libs/spandsp/src/spandsp/private/v42bis.h @@ -92,14 +92,14 @@ typedef struct /*! \brief Compression performance metric */ uint16_t compression_performance; - /*! \brief Outgoing bit buffer (compression), or incoming bit buffer (decompression) */ + /*! \brief Outgoing bit buffer (compression), or incoming bit buffer (decompression) */ uint32_t bit_buffer; - /*! \brief Outgoing bit count (compression), or incoming bit count (decompression) */ + /*! \brief Outgoing bit count (compression), or incoming bit count (decompression) */ int bit_count; /*! \brief The output composition buffer */ uint8_t output_buf[V42BIS_MAX_OUTPUT_LENGTH]; - /*! \brief The length of the contents of the output composition buffer */ + /*! \brief The length of the contents of the output composition buffer */ int output_octet_count; /*! \brief The current value of the escape code */ diff --git a/libs/spandsp/src/spandsp/private/v8.h b/libs/spandsp/src/spandsp/private/v8.h index 77dd55eea0..213d445f52 100644 --- a/libs/spandsp/src/spandsp/private/v8.h +++ b/libs/spandsp/src/spandsp/private/v8.h @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + #if !defined(_SPANDSP_PRIVATE_V8_H_) #define _SPANDSP_PRIVATE_V8_H_ @@ -62,7 +62,7 @@ struct v8_state_s int preamble_type; uint8_t rx_data[64]; int rx_data_ptr; - + /*! \brief a reference copy of the last CM or JM message, used when testing for matches. */ uint8_t cm_jm_data[64]; diff --git a/libs/spandsp/src/spandsp/t30.h b/libs/spandsp/src/spandsp/t30.h index 7606f42d75..241df11d9e 100644 --- a/libs/spandsp/src/spandsp/t30.h +++ b/libs/spandsp/src/spandsp/t30.h @@ -74,7 +74,7 @@ generated according to the specification. The T.30 spec. specifies a number of time-outs. For example, after dialing a number, a calling fax system should listen for a response for 35 seconds before giving up. -These time-out periods are as follows: +These time-out periods are as follows: - T1 - 35+-5s: the maximum time for which two fax system will attempt to identify each other - T2 - 6+-1s: a time-out used to start the sequence for changing transmit parameters @@ -86,7 +86,7 @@ ignored, sometimes with good reason. For example, after placing a call, the calling fax system is supposed to wait for 35 seconds before giving up. If the answering unit does not answer on the first ring or if a voice answering machine is connected to the line, or if there are many delays through the network, -the delay before answer can be much longer than 35 seconds. +the delay before answer can be much longer than 35 seconds. Fax units that support error correction mode (ECM) can respond to a post-image handshake message with a receiver not ready (RNR) message. The calling unit then @@ -95,7 +95,7 @@ answering unit is still busy (printing for example), it will repeat the RNR message. According to the T.30 standard, this sequence (RR/RNR RR/RNR) can be repeated for up to the end of T5 (60+-5s). However, many fax systems ignore the time-out and will continue the sequence indefinitely, unless the user -manually overrides. +manually overrides. All the time-outs are subject to alteration, and sometimes misuse. Good T.30 implementations must do the right thing, and tolerate others doing the wrong thing. @@ -109,7 +109,7 @@ violate this requirement, especially for the silent period between DCS and TCF. This may be stretched to well over 100ms. If this period is too long, it can interfere with handshake signal error recovery, should a packet be corrupted on the line. Systems should ensure they stay within the prescribed T.30 limits, and be tolerant of others -being out of spec.. +being out of spec.. \subsection t30_page_sec_2d Other timing variations @@ -118,7 +118,7 @@ variations in the duration of pauses between unacknowledged handshake message repetitions, and also in the pauses between the receipt of a handshake command and the start of a response to that command. In order to reduce the total transmission time, many fax systems start sending a response message before the -end of the command has been received. +end of the command has been received. \subsection t30_page_sec_2e Other deviations from the T.30 standard @@ -284,11 +284,11 @@ enum T30_ERR_BADTAG, /*! Incorrect values for TIFF/F tags */ T30_ERR_BADTIFFHDR, /*! Bad TIFF/F header - incorrect values in fields */ T30_ERR_NOMEM, /*! Cannot allocate memory for more pages */ - + /* General problems */ T30_ERR_RETRYDCN, /*! Disconnected after permitted retries */ T30_ERR_CALLDROPPED, /*! The call dropped prematurely */ - + /* Feature negotiation issues */ T30_ERR_NOPOLL, /*! Poll not accepted */ T30_ERR_IDENT_UNACCEPTABLE, /*! Far end's ident is not acceptable */ diff --git a/libs/spandsp/src/spandsp/t31.h b/libs/spandsp/src/spandsp/t31.h index 37dba4846b..4e8452e497 100644 --- a/libs/spandsp/src/spandsp/t31.h +++ b/libs/spandsp/src/spandsp/t31.h @@ -56,7 +56,7 @@ SPAN_DECLARE(void) t31_call_event(t31_state_t *s, int event); \param s The T.31 modem context. \return The number of bytes of free space. */ SPAN_DECLARE(int) t31_at_rx_free_space(t31_state_t *s); - + SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len); /*! Process a block of received T.31 modem audio samples. diff --git a/libs/spandsp/src/spandsp/t38_non_ecm_buffer.h b/libs/spandsp/src/spandsp/t38_non_ecm_buffer.h index 744643aa40..0b1bee6af6 100644 --- a/libs/spandsp/src/spandsp/t38_non_ecm_buffer.h +++ b/libs/spandsp/src/spandsp/t38_non_ecm_buffer.h @@ -68,7 +68,7 @@ successive EOL markers, with no pixel data between them. */ /*! The buffer length much be a power of two. The chosen length is big enough for - over 9s of data at the V.17 14,400bps rate. */ + over 9s of data at the V.17 14,400bps rate. */ #define T38_NON_ECM_TX_BUF_LEN 16384 /*! \brief A flow controlled non-ECM image data buffer, for buffering T.38 to analogue diff --git a/libs/spandsp/src/spandsp/tone_generate.h b/libs/spandsp/src/spandsp/tone_generate.h index d6ed8f2bc3..7fe140c216 100644 --- a/libs/spandsp/src/spandsp/tone_generate.h +++ b/libs/spandsp/src/spandsp/tone_generate.h @@ -31,7 +31,7 @@ /*! \page tone_generation_page Tone generation \section tone_generation_page_sec_1 What does it do? The tone generation module provides for the generation of cadenced tones, -suitable for a wide range of telephony applications. +suitable for a wide range of telephony applications. \section tone_generation_page_sec_2 How does it work? Oscillators are a problem. They oscillate due to instability, and yet we need @@ -40,7 +40,7 @@ on this subject. Many describe rather complex solutions to the problem. However, we are only concerned with telephony applications. It is possible to generate the tones we need with a very simple efficient scheme. It is also practical to use an exhaustive test to prove the oscillator is stable under all the -conditions in which we will use it. +conditions in which we will use it. */ typedef struct tone_gen_tone_descriptor_s tone_gen_tone_descriptor_t; diff --git a/libs/spandsp/src/spandsp/v17rx.h b/libs/spandsp/src/spandsp/v17rx.h index 935d542853..21c34f5b29 100644 --- a/libs/spandsp/src/spandsp/v17rx.h +++ b/libs/spandsp/src/spandsp/v17rx.h @@ -34,7 +34,7 @@ The V.17 receiver implements the receive side of a V.17 modem. This can operate at data rates of 14400, 12000, 9600 and 7200 bits/second. The audio input is a stream of 16 bit samples, at 8000 samples/second. The transmit and receive side of V.17 modems operate independantly. V.17 is mostly used for FAX transmission over PSTN -lines, where it provides the standard 14400 bits/second rate. +lines, where it provides the standard 14400 bits/second rate. \section v17rx_page_sec_2 How does it work? V.17 uses QAM modulation, at 2400 baud, and trellis coding. Constellations with @@ -93,7 +93,7 @@ into line. From this point on, a heavily damped integrate and dump approach, based on the angular difference between each received constellation position and its expected position, is sufficient to track the carrier, and maintain phase alignment. A fast rough approximator for the arc-tangent function is adequate -for the estimation of the angular error. +for the estimation of the angular error. The next phase of the training sequence is a scrambled sequence of two particular symbols. We train the T/2 adaptive equalizer using this sequence. The @@ -102,7 +102,7 @@ converges to the proper generalised solution. At the end of this sequence, the equalizer should be sufficiently well adapted that is can correctly resolve the full QAM constellation. However, the equalizer continues to adapt throughout operation of the modem, fine tuning on the more complex data patterns of the -full QAM constellation. +full QAM constellation. In the last phase of the training sequence, the modem enters normal data operation, with a short defined period of all ones as data. As in most high diff --git a/libs/spandsp/src/spandsp/v17tx.h b/libs/spandsp/src/spandsp/v17tx.h index 91fd595149..0d98cc7010 100644 --- a/libs/spandsp/src/spandsp/v17tx.h +++ b/libs/spandsp/src/spandsp/v17tx.h @@ -34,7 +34,7 @@ The V.17 transmitter implements the transmit side of a V.17 modem. This can operate at data rates of 14400, 12000, 9600 and 7200 bits/second. The audio output is a stream of 16 bit samples, at 8000 samples/second. The transmit and receive side of V.17 modems operate independantly. V.17 is mostly used for FAX -transmission, where it provides the standard 14400 bits/second rate. +transmission, where it provides the standard 14400 bits/second rate. \section v17tx_page_sec_2 How does it work? V.17 uses QAM modulation and trellis coding. The data to be transmitted is @@ -53,7 +53,7 @@ The standard method of producing a QAM modulated signal is to use a sampling rate which is a multiple of the baud rate. The raw signal is then a series of complex pulses, each an integer number of samples long. These can be shaped, using a suitable complex filter, and multiplied by a complex carrier signal -to produce the final QAM signal for transmission. +to produce the final QAM signal for transmission. The pulse shaping filter is only vaguely defined by the V.17 spec. Some of the other ITU modem specs. fully define the filter, typically specifying a root @@ -76,7 +76,7 @@ The carrier is generated using the DDS method. Using two second order resonators started in quadrature, might be more efficient, as it would have less impact on the processor cache than a table lookup approach. However, the DDS approach suits the receiver better, so the same signal generator is also used for the -transmitter. +transmitter. */ /*! diff --git a/libs/spandsp/src/spandsp/v18.h b/libs/spandsp/src/spandsp/v18.h index 08219ec0be..fbd4994a59 100644 --- a/libs/spandsp/src/spandsp/v18.h +++ b/libs/spandsp/src/spandsp/v18.h @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ /*! \page v18_page The V.18 text telephony protocols diff --git a/libs/spandsp/src/spandsp/v27ter_rx.h b/libs/spandsp/src/spandsp/v27ter_rx.h index a6055844d6..5881f4cf02 100644 --- a/libs/spandsp/src/spandsp/v27ter_rx.h +++ b/libs/spandsp/src/spandsp/v27ter_rx.h @@ -35,7 +35,7 @@ The V.27ter receiver implements the receive side of a V.27ter modem. This can op at data rates of 4800 and 2400 bits/s. The audio input is a stream of 16 bit samples, at 8000 samples/second. The transmit and receive side of V.27ter modems operate independantly. V.27ter is mostly used for FAX transmission, where it provides the -standard 4800 bits/s rate (the 2400 bits/s mode is not used for FAX). +standard 4800 bits/s rate (the 2400 bits/s mode is not used for FAX). \section v27ter_rx_page_sec_2 How does it work? V.27ter defines two modes of operation. One uses 8-PSK at 1600 baud, giving 4800bps. diff --git a/libs/spandsp/src/spandsp/v27ter_tx.h b/libs/spandsp/src/spandsp/v27ter_tx.h index 8a04e2018c..e785c889ec 100644 --- a/libs/spandsp/src/spandsp/v27ter_tx.h +++ b/libs/spandsp/src/spandsp/v27ter_tx.h @@ -34,17 +34,17 @@ The V.27ter transmitter implements the transmit side of a V.27ter modem. This can operate at data rates of 4800 and 2400 bits/s. The audio output is a stream of 16 bit samples, at 8000 samples/second. The transmit and receive side of V.27ter modems operate independantly. V.27ter is used for FAX transmission, -where it provides the standard 4800 and 2400 bits/s rates. +where it provides the standard 4800 and 2400 bits/s rates. \section v27ter_tx_page_sec_2 How does it work? V.27ter uses DPSK modulation. A common method of producing a DPSK modulated signal is to use a sampling rate which is a multiple of the baud rate. The raw signal is then a series of complex pulses, each an integer number of samples long. These can be shaped, using a suitable complex filter, and multiplied by a -complex carrier signal to produce the final DPSK signal for transmission. +complex carrier signal to produce the final DPSK signal for transmission. The pulse shaping filter for V.27ter is defined in the spec. It is a root raised -cosine filter with 50% excess bandwidth. +cosine filter with 50% excess bandwidth. The sampling rate for our transmitter is defined by the channel - 8000 samples/s. This is a multiple of the baud rate at 4800 bits/s (8-PSK at 1600 baud, 5 samples per diff --git a/libs/spandsp/src/spandsp/v29rx.h b/libs/spandsp/src/spandsp/v29rx.h index bb52e624dc..ec3a945ad4 100644 --- a/libs/spandsp/src/spandsp/v29rx.h +++ b/libs/spandsp/src/spandsp/v29rx.h @@ -35,7 +35,7 @@ at data rates of 9600, 7200 and 4800 bits/s. The audio input is a stream of 16 bit samples, at 8000 samples/second. The transmit and receive side of V.29 modems operate independantly. V.29 is mostly used for FAX transmission, where it provides the standard 9600 and 7200 bits/s rates (the 4800 bits/s mode is not -used for FAX). +used for FAX). \section v29rx_page_sec_2 How does it work? V.29 operates at 2400 baud for all three bit rates. It uses 16-QAM modulation for @@ -92,7 +92,7 @@ into line. From this point on, a heavily damped integrate and dump approach, based on the angular difference between each received constellation position and its expected position, is sufficient to track the carrier, and maintain phase alignment. A fast rough approximator for the arc-tangent function is adequate -for the estimation of the angular error. +for the estimation of the angular error. The next phase of the training sequence is a scrambled sequence of two particular symbols. We train the T/2 adaptive equalizer using this sequence. The @@ -101,7 +101,7 @@ converges to the proper generalised solution. At the end of this sequence, the equalizer should be sufficiently well adapted that is can correctly resolve the full QAM constellation. However, the equalizer continues to adapt throughout operation of the modem, fine tuning on the more complex data patterns of the -full QAM constellation. +full QAM constellation. In the last phase of the training sequence, the modem enters normal data operation, with a short defined period of all ones as data. As in most high @@ -115,7 +115,7 @@ application, and the receive modem is up and running. Unfortunately, some transmit side of some real V.29 modems fail to initialise their scrambler before sending the ones. This means the first 23 received bits (the length of the scrambler register) cannot be trusted for the test. The receive modem, -therefore, only tests that bits starting at bit 24 are really ones. +therefore, only tests that bits starting at bit 24 are really ones. */ #if defined(SPANDSP_USE_FIXED_POINT) diff --git a/libs/spandsp/src/spandsp/v29tx.h b/libs/spandsp/src/spandsp/v29tx.h index 3cb14fea94..86737d1ba3 100644 --- a/libs/spandsp/src/spandsp/v29tx.h +++ b/libs/spandsp/src/spandsp/v29tx.h @@ -35,14 +35,14 @@ operate at data rates of 9600, 7200 and 4800 bits/s. The audio output is a stream of 16 bit samples, at 8000 samples/second. The transmit and receive side of V.29 modems operate independantly. V.29 is mostly used for FAX transmission, where it provides the standard 9600 and 7200 bits/s rates (the 4800 bits/s mode -is not used for FAX). +is not used for FAX). \section v29tx_page_sec_2 How does it work? V.29 uses QAM modulation. The standard method of producing a QAM modulated signal is to use a sampling rate which is a multiple of the baud rate. The raw signal is then a series of complex pulses, each an integer number of samples long. These can be shaped, using a suitable complex filter, and multiplied by a -complex carrier signal to produce the final QAM signal for transmission. +complex carrier signal to produce the final QAM signal for transmission. The pulse shaping filter is only vaguely defined by the V.29 spec. Some of the other ITU modem specs. fully define the filter, typically specifying a root @@ -65,7 +65,7 @@ The carrier is generated using the DDS method. Using two second order resonators started in quadrature, might be more efficient, as it would have less impact on the processor cache than a table lookup approach. However, the DDS approach suits the receiver better, so the same signal generator is also used for the -transmitter. +transmitter. The equation defining QAM modulation is: @@ -76,16 +76,16 @@ where phi(n) is the phase of the information, and A is the amplitude of the info using the identity cos(x + y) = cos(x)*cos(y) - sin(x)*sin(y) - + we get s(n) = A {cos(2*pi*f*n)*cos(phi(n)) - sin(2*pi*f*n)*sin(phi(n))} - + substituting with the constellation positions I(n) = A*cos(phi(n)) Q(n) = A*sin(phi(n)) - + gives s(n) = I(n)*cos(2*pi*f*n) - Q(n)*sin(2*pi*f*n) diff --git a/libs/spandsp/src/spandsp/v42.h b/libs/spandsp/src/spandsp/v42.h index 5ab26262dd..6332e5cd61 100644 --- a/libs/spandsp/src/spandsp/v42.h +++ b/libs/spandsp/src/spandsp/v42.h @@ -79,7 +79,7 @@ SPAN_DECLARE(logging_state_t *) v42_get_logging_state(v42_state_t *s); /*! Initialise a V.42 context. \param s The V.42 context. \param calling_party TRUE if caller mode, else answerer mode. - \param detect TRUE to perform the V.42 detection, else go straight into LAP.M + \param detect TRUE to perform the V.42 detection, else go straight into LAP.M \param iframe_get A callback function to handle received frames of data. \param iframe_put A callback function to get frames of data for transmission. \param user_data An opaque pointer passed to the frame handler routines. diff --git a/libs/spandsp/src/spandsp/v42bis.h b/libs/spandsp/src/spandsp/v42bis.h index bf6f6e6f1a..1f9ae98fa1 100644 --- a/libs/spandsp/src/spandsp/v42bis.h +++ b/libs/spandsp/src/spandsp/v42bis.h @@ -85,7 +85,7 @@ SPAN_DECLARE(int) v42bis_compress_flush(v42bis_state_t *s); \param len The length of the data buffer. \return 0 */ SPAN_DECLARE(int) v42bis_decompress(v42bis_state_t *s, const uint8_t buf[], int len); - + /*! Flush out any data remaining in the decompression buffer. \param s The V.42bis context. \return 0 */ diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index ddb0337834..7e9e4c333f 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -1111,7 +1111,7 @@ static int send_csa_frame(t30_state_t *s) static int send_pps_frame(t30_state_t *s) { uint8_t frame[7]; - + frame[0] = ADDRESS_FIELD; frame[1] = CONTROL_FIELD_FINAL_FRAME; frame[2] = (uint8_t) (T30_PPS | s->dis_received); @@ -1238,7 +1238,7 @@ int t30_build_dis_or_dtc(t30_state_t *s) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE); if ((s->supported_resolutions & (T30_SUPPORT_400_400_RESOLUTION | T30_SUPPORT_R16_RESOLUTION))) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE); - /* Metric */ + /* Metric */ set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED); /* Superfine minimum scan line time pattern follows fine */ if ((s->supported_t30_features & T30_SUPPORT_SELECTIVE_POLLING)) @@ -2510,7 +2510,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) } /* Start document reception */ span_log(&s->logging, - SPAN_LOG_FLOW, + SPAN_LOG_FLOW, "Get document at %dbps, modem %d\n", fallback_sequence[s->current_fallback].bit_rate, fallback_sequence[s->current_fallback].modem_type); @@ -2692,7 +2692,7 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) s->ecm_len[frame_no] = -1; } } - } + } if (s->ecm_len[frame_no] < 0) { s->ecm_frame_map[i + 3] |= (1 << j); @@ -2794,7 +2794,7 @@ static void process_rx_ppr(t30_state_t *s, const uint8_t *msg, int len) span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for PPR bits - %d\n", (len - 3)*8); /* This frame didn't get corrupted in transit, because its CRC is OK. It was sent bad and there is little possibility that causing a retransmission will help. It is best - to just give up. */ + to just give up. */ t30_set_status(s, T30_ERR_TX_ECMPHD); disconnect(s); return; @@ -3509,7 +3509,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t * { uint8_t fcf; uint8_t fcf2; - + /* This actually handles 2 states - _DOC_ECM and _POST_DOC_ECM - as they are very similar */ fcf = msg[2] & 0xFE; switch (fcf) @@ -5150,7 +5150,7 @@ static void timer_t4b_start(t30_state_t *s) static void timer_t2_t4_stop(t30_state_t *s) { const char *tag; - + switch (s->timer_t2_t4_is) { case TIMER_IS_IDLE: @@ -5433,7 +5433,7 @@ static void decode_url_msg(t30_state_t *s, char *msg, const uint8_t *pkt, int le static int decode_nsf_nss_nsc(t30_state_t *s, uint8_t *msg[], const uint8_t *pkt, int len) { uint8_t *t; - + if ((t = malloc(len - 1)) == NULL) return 0; memcpy(t, pkt + 1, len - 1); @@ -5889,7 +5889,7 @@ SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t *msg, i SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status) { t30_state_t *s; - + s = (t30_state_t *) user_data; switch (status) diff --git a/libs/spandsp/src/t30_logging.c b/libs/spandsp/src/t30_logging.c index e951df85bd..33efcb9c03 100644 --- a/libs/spandsp/src/t30_logging.c +++ b/libs/spandsp/src/t30_logging.c @@ -425,7 +425,7 @@ static void octet_reserved_bit(logging_state_t *log, char s[10] = ".... ...."; int bit; uint8_t octet; - + /* Break out the octet and the bit number within it. */ octet = msg[((bit_no - 1) >> 3) + 3]; bit_no = (bit_no - 1) & 7; @@ -488,7 +488,7 @@ static void octet_field(logging_state_t *log, int i; uint8_t octet; const char *tag; - + /* Break out the octet and the bit number range within it. */ octet = msg[((start - 1) >> 3) + 3]; start = (start - 1) & 7; @@ -646,7 +646,7 @@ SPAN_DECLARE(void) t30_decode_dis_dtc_dcs(t30_state_t *s, const uint8_t *pkt, in span_log(log, SPAN_LOG_FLOW, " Frame is short\n"); return; } - + span_log(log, SPAN_LOG_FLOW, "%s:\n", t30_frametype(pkt[2])); if (len <= 3) { @@ -674,7 +674,7 @@ SPAN_DECLARE(void) t30_decode_dis_dtc_dcs(t30_state_t *s, const uint8_t *pkt, in span_log(log, SPAN_LOG_FLOW, " Frame is short\n"); return; } - + if (frame_type == T30_DCS) { octet_reserved_bit(log, pkt, 9, 0); diff --git a/libs/spandsp/src/t31.c b/libs/spandsp/src/t31.c index 20e7666bd9..6a9f08d382 100644 --- a/libs/spandsp/src/t31.c +++ b/libs/spandsp/src/t31.c @@ -259,7 +259,7 @@ static int extra_bits_in_stuffed_frame(const uint8_t buf[], int len) int stuffed; int i; int j; - + bitstream = 0; ones = 0; stuffed = 0; @@ -307,7 +307,7 @@ static int extra_bits_in_stuffed_frame(const uint8_t buf[], int len) static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_no, int expected_seq_no) { t31_state_t *s; - + s = (t31_state_t *) user_data; s->t38_fe.rx_data_missing = TRUE; return 0; @@ -649,7 +649,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the end of non-ECM data. We need to tolerate this. We use the generic receive complete indication, rather than the specific HDLC carrier down. */ - /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - + /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */ fe->hdlc_rx.len = 0; @@ -1354,7 +1354,7 @@ SPAN_DECLARE(int) t31_t38_send_timeout(t31_state_t *s, int samples) static int t31_modem_control_handler(at_state_t *s, void *user_data, int op, const char *num) { t31_state_t *t; - + t = (t31_state_t *) user_data; switch (op) { @@ -2800,7 +2800,7 @@ SPAN_DECLARE_NONSTD(int) t31_rx(t31_state_t *s, int16_t amp[], int len) s->audio.silence_heard = 0; } else - { + { if (s->audio.silence_heard <= ms_to_samples(255*10)) s->audio.silence_heard++; /*endif*/ @@ -2893,7 +2893,7 @@ SPAN_DECLARE_NONSTD(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len) { /* Pad to the requested length with silence */ memset(amp + len, 0, (max_len - len)*sizeof(int16_t)); - len = max_len; + len = max_len; } /*endif*/ return len; @@ -2970,7 +2970,7 @@ static int t31_t38_fe_init(t31_state_t *t, void *tx_packet_user_data) { t31_t38_front_end_state_t *s; - + s = &t->t38_fe; t38_core_init(&s->t38, diff --git a/libs/spandsp/src/t35.c b/libs/spandsp/src/t35.c index ad10d96881..4186504a4c 100644 --- a/libs/spandsp/src/t35.c +++ b/libs/spandsp/src/t35.c @@ -32,23 +32,23 @@ * Copyright (c) 1994-1996 Silicon Graphics, Inc. * HylaFAX is a trademark of Silicon Graphics * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -108,7 +108,7 @@ static const model_data_t Canon[] = {5, "\x80\x00\x8A\x49\x10", "Laser Class 9000 Series"}, {5, "\x80\x00\x8A\x48\x00", "Laser Class 2060"}, {0, NULL, NULL} -}; +}; static const model_data_t Brother[] = { @@ -215,13 +215,13 @@ static const model_data_t JetFax[] = {0, NULL, NULL} }; -static const model_data_t PitneyBowes[] = +static const model_data_t PitneyBowes[] = { {6, "\x79\x91\xB1\xB8\x7A\xD8", "9550"}, {0, NULL, NULL} }; -static const model_data_t Dialogic[] = +static const model_data_t Dialogic[] = { {8, "\x56\x8B\x06\x55\x00\x15\x00\x00", "VFX/40ESC"}, {0, NULL, NULL} @@ -247,7 +247,7 @@ static const model_data_t Muratec48[] = * identified by a single manufacturer byte. * * T.30 5.3.6.2.7 (2003) states that the NSF FIF is transmitted - * in MSB2LSB order. Revisions of T.30 prior to 2003 did not + * in MSB2LSB order. Revisions of T.30 prior to 2003 did not * contain explicit specification as to the transmit bit order. * (Although it did otherwise state that all HDLC frame data should * be in MSB order except as noted.) Because CSI, TSI, and other @@ -259,7 +259,7 @@ static const model_data_t Muratec48[] = * * Thus, country code x61 (Korea) turns into x86 (Papua New Guinea), * code xB5 (USA) turns into xAD (Tunisia), code x26 (China) turns - * into x64 (Lebanon), code x04 (Germany) turns into x20 (Canada), + * into x64 (Lebanon), code x04 (Germany) turns into x20 (Canada), * and code x3D (France) turns into xBC (Vietnam). * * For the most part it should be safe to identify a manufacturer @@ -800,7 +800,7 @@ SPAN_DECLARE(int) t35_real_country_code(int country_code, int country_code_exten } /* We need to apply realism over accuracy, though it blocks out some countries. It is very rare to find a machine from any country but the following: - + Japan 0x00 (no confusion) Germany 0x04 (0x20) (Canada/Germany confusion) China 0x26 (0x64) (China/Lebanon confusion) @@ -860,7 +860,7 @@ SPAN_DECLARE(const char *) t35_country_code_to_str(int country_code, int country /* Right now there are no extension codes defined by the ITU */ return NULL; } - + return t35_country_codes[country_code].name; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/t38_core.c b/libs/spandsp/src/t38_core.c index 665bed2313..ae6526f7e8 100644 --- a/libs/spandsp/src/t38_core.c +++ b/libs/spandsp/src/t38_core.c @@ -635,7 +635,7 @@ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8 - 3. the result of a hop in the sequence numbers cause by something weird from the other end. Stream switching might cause this - 4. missing packets. - + In cases 1 and 2 we need to drop this packet. In case 2 it might make sense to try to do something with it in the terminal case. Currently we don't. For gateway operation it will be too late to do anything useful. diff --git a/libs/spandsp/src/t38_gateway.c b/libs/spandsp/src/t38_gateway.c index 7955b3e5a8..7656332e80 100644 --- a/libs/spandsp/src/t38_gateway.c +++ b/libs/spandsp/src/t38_gateway.c @@ -779,7 +779,7 @@ static void queue_missing_indicator(t38_gateway_state_t *s, int data_type) t38_core_state_t *t; int expected; int expected_alt; - + t = &s->t38x.t38; expected = -1; expected_alt = -1; @@ -861,7 +861,7 @@ static void queue_missing_indicator(t38_gateway_state_t *s, int data_type) static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_no, int expected_seq_no) { t38_gateway_state_t *s; - + s = (t38_gateway_state_t *) user_data; s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].flags |= HDLC_FLAG_MISSING_DATA; return 0; @@ -1030,7 +1030,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, { xx->t38.v34_rate = t38_v34rate_to_bps(buf, len); span_log(&s->logging, SPAN_LOG_FLOW, "V.34 rate %d bps\n", xx->t38.v34_rate); - } + } else { span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for V34rate message - %d\n", len); @@ -1284,7 +1284,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, } else { - /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - + /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. In this case we just clear out any partial frame data that might be in the buffer. */ @@ -1400,7 +1400,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, static void set_octets_per_data_packet(t38_gateway_state_t *s, int bit_rate) { int octets; - + octets = s->core.ms_per_tx_chunk*bit_rate/(8*1000); if (octets < 1) octets = 1; @@ -1751,7 +1751,7 @@ static void rx_flag_or_abort(hdlc_rx_state_t *t) t38_gateway_state_t *s; t38_gateway_to_t38_state_t *u; int category; - + s = (t38_gateway_state_t *) t->frame_user_data; u = &s->core.to_t38; if ((t->raw_bit_stream & 0x80)) @@ -2096,7 +2096,7 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], i int len; #if defined(LOG_FAX_AUDIO) int required_len; - + required_len = max_len; #endif if ((len = s->audio.modems.tx_handler(s->audio.modems.tx_user_data, amp, max_len)) < max_len) @@ -2119,7 +2119,7 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], i { /* Pad to the requested length with silence */ memset(amp + len, 0, (max_len - len)*sizeof(int16_t)); - len = max_len; + len = max_len; } /*endif*/ #if defined(LOG_FAX_AUDIO) diff --git a/libs/spandsp/src/t38_non_ecm_buffer.c b/libs/spandsp/src/t38_non_ecm_buffer.c index ddf5b49f7a..cc339a0581 100644 --- a/libs/spandsp/src/t38_non_ecm_buffer.c +++ b/libs/spandsp/src/t38_non_ecm_buffer.c @@ -153,12 +153,12 @@ SPAN_DECLARE(void) t38_non_ecm_buffer_inject(t38_non_ecm_buffer_state_t *s, cons An EOL 11 zeros followed by a one in a T.4 1D image or 11 zeros followed by a one followed by a one or a zero in a T.4 2D image. An RTC consists of 6 EOLs in succession, with no pixel data between them. - + We can stuff with ones until we get the first EOL into our buffer, then we can stuff with zeros in front of each EOL at any point up the the RTC. We should not pad between the EOLs which make up the RTC. Most FAX machines don't care about this, but a few will not recognise the RTC if here is padding between the EOLs. - + We need to buffer whole rows before we output their beginning, so there is no possibility of underflow mid-row. */ diff --git a/libs/spandsp/src/t38_terminal.c b/libs/spandsp/src/t38_terminal.c index ca000e1ac7..66938d8d24 100644 --- a/libs/spandsp/src/t38_terminal.c +++ b/libs/spandsp/src/t38_terminal.c @@ -164,7 +164,7 @@ static int extra_bits_in_stuffed_frame(const uint8_t buf[], int len) int stuffed; int i; int j; - + bitstream = 0; ones = 0; stuffed = 0; @@ -212,7 +212,7 @@ static int extra_bits_in_stuffed_frame(const uint8_t buf[], int len) static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_no, int expected_seq_no) { t38_terminal_state_t *s; - + s = (t38_terminal_state_t *) user_data; s->t38_fe.rx_data_missing = TRUE; return 0; @@ -223,7 +223,7 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica { t38_terminal_state_t *s; t38_terminal_front_end_state_t *fe; - + s = (t38_terminal_state_t *) user_data; fe = &s->t38_fe; @@ -547,7 +547,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the end of non-ECM data. We need to tolerate this. We use the generic receive complete indication, rather than the specific HDLC carrier down. */ - /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - + /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */ fe->hdlc_rx.len = 0; @@ -1447,7 +1447,7 @@ SPAN_DECLARE(t38_core_state_t *) t38_terminal_get_t38_core_state(t38_terminal_st static int t38_terminal_t38_fe_restart(t38_terminal_state_t *t) { t38_terminal_front_end_state_t *s; - + s = &t->t38_fe; t38_core_restart(&s->t38); @@ -1471,7 +1471,7 @@ static int t38_terminal_t38_fe_init(t38_terminal_state_t *t, void *tx_packet_user_data) { t38_terminal_front_end_state_t *s; - + s = &t->t38_fe; t38_core_init(&s->t38, process_rx_indicator, diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index a331225ddf..eae361941b 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -174,12 +174,10 @@ static int set_tiff_directory_info(t4_rx_state_t *s) case COMPRESSION_CCITT_T4: TIFFSetField(t->tiff_file, TIFFTAG_T4OPTIONS, output_t4_options); TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); - TIFFSetField(t->tiff_file, TIFFTAG_ROWSPERSTRIP, -1L); break; case COMPRESSION_CCITT_T6: TIFFSetField(t->tiff_file, TIFFTAG_T6OPTIONS, 0); TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); - TIFFSetField(t->tiff_file, TIFFTAG_ROWSPERSTRIP, -1L); break; case COMPRESSION_T85: TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); diff --git a/libs/spandsp/src/t85_decode.c b/libs/spandsp/src/t85_decode.c index 8193c10a0d..93efc06e81 100644 --- a/libs/spandsp/src/t85_decode.c +++ b/libs/spandsp/src/t85_decode.c @@ -722,7 +722,7 @@ SPAN_DECLARE(int) t85_decode_new_plane(t85_decode_state_t *s) { if (s->current_bit_plane >= s->bit_planes - 1) return -1; - + s->current_bit_plane++; s->tx = 0; memset(s->buffer, 0, sizeof(s->buffer)); diff --git a/libs/spandsp/src/t85_encode.c b/libs/spandsp/src/t85_encode.c index d9c4d200e2..6ce2cae6fb 100644 --- a/libs/spandsp/src/t85_encode.c +++ b/libs/spandsp/src/t85_encode.c @@ -206,7 +206,7 @@ static void generate_bih(t85_encode_state_t *s, uint8_t *buf) buf[19] = s->options; } /*- End of function --------------------------------------------------------*/ - + SPAN_DECLARE(void) t85_encode_set_options(t85_encode_state_t *s, uint32_t l0, int mx, @@ -713,7 +713,7 @@ SPAN_DECLARE(t85_encode_state_t *) t85_encode_init(t85_encode_state_t *s, s->current_bit_plane = 0; t85_encode_restart(s, image_width, image_length); - + return s; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/tone_generate.c b/libs/spandsp/src/tone_generate.c index 487bb69833..21285f6a96 100644 --- a/libs/spandsp/src/tone_generate.c +++ b/libs/spandsp/src/tone_generate.c @@ -107,7 +107,7 @@ SPAN_DECLARE(tone_gen_descriptor_t *) tone_gen_descriptor_init(tone_gen_descript s->duration[3] = d4*SAMPLE_RATE/1000; s->repeat = repeat; - + return s; } /*- End of function --------------------------------------------------------*/ @@ -137,7 +137,7 @@ SPAN_DECLARE_NONSTD(int) tone_gen(tone_gen_state_t *s, int16_t amp[], int max_sa limit = samples + s->duration[s->current_section] - s->current_position; if (limit > max_samples) limit = max_samples; - + s->current_position += (limit - samples); if (s->current_section & 1) { diff --git a/libs/spandsp/src/v17rx.c b/libs/spandsp/src/v17rx.c index b275270b49..46480ee19b 100644 --- a/libs/spandsp/src/v17rx.c +++ b/libs/spandsp/src/v17rx.c @@ -1228,7 +1228,7 @@ static __inline__ int signal_detect(v17_rx_state_t *s, int16_t amp) } } else - { + { s->low_samples = 0; if (diff > s->high_sample) s->high_sample = diff; @@ -1560,7 +1560,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai s->baud_phase = 0.0f; #endif s->baud_half = 0; - + s->total_baud_timing_correction = 0; return 0; diff --git a/libs/spandsp/src/v18.c b/libs/spandsp/src/v18.c index e1cfdc005a..3529fe6f0d 100644 --- a/libs/spandsp/src/v18.c +++ b/libs/spandsp/src/v18.c @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ #if defined(HAVE_CONFIG_H) @@ -72,7 +72,7 @@ /* Ways in which a V.18 call may start ----------------------------------- - + Originate: ANS Silence for 0.5s then send TXP @@ -643,7 +643,7 @@ static int v18_tdd_get_async_byte(void *user_data) { v18_state_t *s; int ch; - + s = (v18_state_t *) user_data; if ((ch = queue_read_byte(&s->queue.queue)) >= 0) return ch; @@ -666,7 +666,7 @@ static void v18_tdd_put_async_byte(void *user_data, int byte) { v18_state_t *s; uint8_t octet; - + s = (v18_state_t *) user_data; if (byte < 0) { diff --git a/libs/spandsp/src/v22bis_rx.c b/libs/spandsp/src/v22bis_rx.c index d124d7bcd8..c4898cf1cd 100644 --- a/libs/spandsp/src/v22bis_rx.c +++ b/libs/spandsp/src/v22bis_rx.c @@ -110,7 +110,7 @@ The basic method used by the V.22bis receiver is: Tune the local carrier, based on the angular mismatch between the actual signal and the decision. - + Tune the equalizer, based on the mismatch between the actual signal and the decision. Descramble and output the bits represented by the decision. @@ -800,7 +800,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l for (i = 0; i < len; i++) { /* Complex bandpass filter the signal, using a pair of FIRs, and RRC coeffs shifted - to centre at 1200Hz or 2400Hz. The filters support 12 fractional phase shifts, to + to centre at 1200Hz or 2400Hz. The filters support 12 fractional phase shifts, to permit signal extraction very close to the middle of a symbol. */ s->rx.rrc_filter[s->rx.rrc_filter_step] = amp[i]; if (++s->rx.rrc_filter_step >= V22BIS_RX_FILTER_STEPS) diff --git a/libs/spandsp/src/v22bis_tx.c b/libs/spandsp/src/v22bis_tx.c index 5cbef4d7d8..8b5068803e 100644 --- a/libs/spandsp/src/v22bis_tx.c +++ b/libs/spandsp/src/v22bis_tx.c @@ -151,7 +151,7 @@ c) On detection of scrambled binary 1 in the high channel at 1200 bit/s for 270 d) 765 +-10 ms after circuit 109 has been turned ON, circuit 106 shall be conditioned to respond to circuit 105 and the modem shall be ready to transmit data at 1200 bit/s. - + 6.3.1.2.2 Answering modem a) On connection to line the answering modem shall be conditioned to transmit signals in the high @@ -289,7 +289,7 @@ static __inline__ int scramble(v22bis_state_t *s, int bit) } out_bit = (bit ^ (s->tx.scramble_reg >> 13) ^ (s->tx.scramble_reg >> 16)) & 1; s->tx.scramble_reg = (s->tx.scramble_reg << 1) | out_bit; - + if (out_bit == 1) s->tx.scrambler_pattern_count++; else diff --git a/libs/spandsp/src/v27ter_rx.c b/libs/spandsp/src/v27ter_rx.c index a4a9f5eeb9..ce0537b560 100644 --- a/libs/spandsp/src/v27ter_rx.c +++ b/libs/spandsp/src/v27ter_rx.c @@ -135,7 +135,7 @@ SPAN_DECLARE(float) v27ter_rx_carrier_frequency(v27ter_rx_state_t *s) SPAN_DECLARE(float) v27ter_rx_symbol_timing_correction(v27ter_rx_state_t *s) { int steps_per_symbol; - + steps_per_symbol = (s->bit_rate == 4800) ? RX_PULSESHAPER_4800_COEFF_SETS*5 : RX_PULSESHAPER_2400_COEFF_SETS*20/3; return (float) s->total_baud_timing_correction/(float) steps_per_symbol; } @@ -538,7 +538,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t s->eq_buf[s->eq_step] = *sample; if (++s->eq_step >= V27TER_EQUALIZER_LEN) s->eq_step = 0; - + /* On alternate insertions we have a whole baud, and must process it. */ if ((s->baud_half ^= 1)) return; @@ -773,7 +773,7 @@ static __inline__ int signal_detect(v27ter_rx_state_t *s, int16_t amp) } } else - { + { s->low_samples = 0; if (diff > s->high_sample) s->high_sample = diff; diff --git a/libs/spandsp/src/v27ter_tx.c b/libs/spandsp/src/v27ter_tx.c index 7c05aa2f6e..6b0706aaf3 100644 --- a/libs/spandsp/src/v27ter_tx.c +++ b/libs/spandsp/src/v27ter_tx.c @@ -121,7 +121,7 @@ static __inline__ int scramble(v27ter_tx_state_t *s, int in_bit) static __inline__ int get_scrambled_bit(v27ter_tx_state_t *s) { int bit; - + if ((bit = s->current_get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA) { /* End of real data. Switch to the fake get_bit routine, until we diff --git a/libs/spandsp/src/v29rx.c b/libs/spandsp/src/v29rx.c index dec0c1f277..33e4d0b161 100644 --- a/libs/spandsp/src/v29rx.c +++ b/libs/spandsp/src/v29rx.c @@ -342,7 +342,7 @@ static __inline__ void track_carrier(v29_rx_state_t *s, const complexf_t *z, con got us in the right ballpark. Now we need to fine tune fairly quickly, to get the receovered carrier more precisely on target. Then we need to fine tune in a more damped way to keep us on target. The goal is to have - things running really well by the time the training is complete. + things running really well by the time the training is complete. We assume the frequency of the oscillators at the two ends drift only very slowly. The PSTN has rather limited doppler problems. :-) Any remaining FDM in the network should also drift slowly. */ @@ -860,7 +860,7 @@ static __inline__ int signal_detect(v29_rx_state_t *s, int16_t amp) } } else - { + { s->low_samples = 0; if (diff > s->high_sample) s->high_sample = diff; diff --git a/libs/spandsp/src/vector_int.c b/libs/spandsp/src/vector_int.c index 807b72b2b3..66166e52eb 100644 --- a/libs/spandsp/src/vector_int.c +++ b/libs/spandsp/src/vector_int.c @@ -314,15 +314,15 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq (%%rsi),%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " movq %%mm3,%%mm4;\n" " pand %%mm2,%%mm3;\n" /* mm3 is mm2 masked to new max's */ " pandn %%mm0,%%mm4;\n" /* mm4 is mm0 masked to its max's */ " por %%mm3,%%mm4;\n" " movq %%mm4,%%mm0;\n" /* Now mm0 is updated max's */ - + " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" @@ -338,7 +338,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm0,%%mm2;\n" " psrlq $32,%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new max's */ " pandn %%mm0,%%mm3;\n" /* mm3 is mm0 masked to its max's */ " por %%mm3,%%mm2;\n" @@ -347,7 +347,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm1,%%mm2;\n" " psrlq $32,%%mm2;\n" " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" @@ -362,7 +362,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movd (%%rsi),%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " movq %%mm3,%%mm4;\n" " pand %%mm2,%%mm3;\n" /* mm3 is mm2 masked to new max's */ " pandn %%mm0,%%mm4;\n" /* mm4 is mm0 masked to its max's */ @@ -370,7 +370,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm4,%%mm0;\n" /* now mm0 is updated max's */ " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" @@ -384,7 +384,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm0,%%mm2;\n" " psrlq $16,%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new max's */ " pandn %%mm0,%%mm3;\n" /* mm3 is mm0 masked to its max's */ " por %%mm3,%%mm2;\n" @@ -393,12 +393,12 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm1,%%mm2;\n" " psrlq $16,%%mm2;\n" " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" " movd %%mm2,%%eax;\n" /* ax is min so far */ - + " addq $2,%%rdx;\n" /* now dx = top-2 */ " cmpq %%rdx,%%rsi;\n" " ja 6f;\n" @@ -467,15 +467,15 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq (%%esi),%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " movq %%mm3,%%mm4;\n" " pand %%mm2,%%mm3;\n" /* mm3 is mm2 masked to new max's */ " pandn %%mm0,%%mm4;\n" /* mm4 is mm0 masked to its max's */ " por %%mm3,%%mm4;\n" " movq %%mm4,%%mm0;\n" /* Now mm0 is updated max's */ - + " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" @@ -491,7 +491,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm0,%%mm2;\n" " psrlq $32,%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new max's */ " pandn %%mm0,%%mm3;\n" /* mm3 is mm0 masked to its max's */ " por %%mm3,%%mm2;\n" @@ -500,7 +500,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm1,%%mm2;\n" " psrlq $32,%%mm2;\n" " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" @@ -515,7 +515,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movd (%%esi),%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " movq %%mm3,%%mm4;\n" " pand %%mm2,%%mm3;\n" /* mm3 is mm2 masked to new max's */ " pandn %%mm0,%%mm4;\n" /* mm4 is mm0 masked to its max's */ @@ -523,7 +523,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm4,%%mm0;\n" /* now mm0 is updated max's */ " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" @@ -537,7 +537,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm0,%%mm2;\n" " psrlq $16,%%mm2;\n" " movq %%mm2,%%mm3;\n" - " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ + " pcmpgtw %%mm0,%%mm3;\n" /* mm3 is bitmask for words where mm2 > mm0 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new max's */ " pandn %%mm0,%%mm3;\n" /* mm3 is mm0 masked to its max's */ " por %%mm3,%%mm2;\n" @@ -546,12 +546,12 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) " movq %%mm1,%%mm2;\n" " psrlq $16,%%mm2;\n" " movq %%mm1,%%mm3;\n" - " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ + " pcmpgtw %%mm2,%%mm3;\n" /* mm3 is bitmask for words where mm2 < mm1 */ " pand %%mm3,%%mm2;\n" /* mm2 is mm2 masked to new min's */ " pandn %%mm1,%%mm3;\n" /* mm3 is mm1 masked to its min's */ " por %%mm3,%%mm2;\n" " movd %%mm2,%%eax;\n" /* ax is min so far */ - + " addl $2,%%edx;\n" /* now dx = top-2 */ " cmpl %%edx,%%esi;\n" " ja 6f;\n" @@ -597,7 +597,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) int16_t max; int16_t temp; int32_t z; - + max = INT16_MIN; min = INT16_MAX; for (i = 0; i < n; i++) diff --git a/libs/spandsp/tests/bell_mf_rx_tests.c b/libs/spandsp/tests/bell_mf_rx_tests.c index 352a0f1f5d..68c9a7a05b 100644 --- a/libs/spandsp/tests/bell_mf_rx_tests.c +++ b/libs/spandsp/tests/bell_mf_rx_tests.c @@ -168,7 +168,7 @@ static void codec_munge(int16_t amp[], int len) { int i; uint8_t alaw; - + for (i = 0; i < len; i++) { alaw = linear_to_alaw (amp[i]); @@ -288,11 +288,11 @@ int main(int argc, char *argv[]) RRB% = (N+ + N-)/10 Receiver Center Frequency Offset (RCFO) is calculated as follows: RCFO% = X + (N+ - N-)/20 - + Note that this test doesn't test what it says it is testing at all, and the results are quite inaccurate, if not a downright lie! However, it follows the Mitel procedure, so how can it be bad? :) - + The spec calls for +-1.5% +-10Hz of bandwidth. */ printf ("Test 3: Recognition bandwidth and channel centre frequency check\n"); @@ -411,11 +411,11 @@ int main(int argc, char *argv[]) printf(" Passed\n"); /* Test 5: Dynamic range - This test sends all possible digits, with gradually increasing + This test sends all possible digits, with gradually increasing amplitude. We determine the span over which we achieve reliable detection. The spec says we should detect between -14dBm and 0dBm, but the tones clip above -3dBm, so this cannot really work. */ - + printf("Test 5: Dynamic range\n"); for (nplus = nminus = -1000, i = -50; i <= 3; i++) { @@ -450,7 +450,7 @@ int main(int argc, char *argv[]) printf(" Passed\n"); /* Test 6: Guard time - This test sends all possible digits, with a gradually reducing + This test sends all possible digits, with a gradually reducing duration. The spec defines a narrow range of tone duration times we can expect, so as long as we detect reliably at the specified minimum we should be OK. However, the spec also says diff --git a/libs/spandsp/tests/bert_tests.c b/libs/spandsp/tests/bert_tests.c index a981795bce..6818f61889 100644 --- a/libs/spandsp/tests/bert_tests.c +++ b/libs/spandsp/tests/bert_tests.c @@ -172,7 +172,7 @@ int main(int argc, char *argv[]) printf("Test failed.\n"); exit(2); } - + tx_bert = bert_init(NULL, 0, BERT_PATTERN_7_TO_1, 300, 20); rx_bert = bert_init(NULL, 0, BERT_PATTERN_7_TO_1, 300, 20); for (i = 0; i < 511*2; i++) @@ -447,7 +447,7 @@ int main(int argc, char *argv[]) // bert_put_bit(bert, bit); bert_put_bit(bert, bit); } - + printf("Tests passed.\n"); return 0; } diff --git a/libs/spandsp/tests/bit_operations_tests.c b/libs/spandsp/tests/bit_operations_tests.c index 53cd997023..bb11c8d857 100644 --- a/libs/spandsp/tests/bit_operations_tests.c +++ b/libs/spandsp/tests/bit_operations_tests.c @@ -49,7 +49,7 @@ uint8_t to[1000000]; static __inline__ int top_bit_dumb(unsigned int data) { int i; - + if (data == 0) return -1; for (i = 31; i >= 0; i--) @@ -64,7 +64,7 @@ static __inline__ int top_bit_dumb(unsigned int data) static __inline__ int bottom_bit_dumb(unsigned int data) { int i; - + if (data == 0) return -1; for (i = 0; i < 32; i++) @@ -80,11 +80,11 @@ static __inline__ uint8_t bit_reverse8_dumb(uint8_t data) { int i; int result; - + result = 0; for (i = 0; i < 8; i++) { - result = (result << 1) | (data & 1); + result = (result << 1) | (data & 1); data >>= 1; } return result; @@ -95,11 +95,11 @@ static __inline__ uint32_t bit_reverse_4bytes_dumb(uint32_t data) { int i; uint32_t result; - + result = 0; for (i = 0; i < 8; i++) { - result = (result << 1) | (data & 0x01010101); + result = (result << 1) | (data & 0x01010101); data >>= 1; } return result; @@ -110,11 +110,11 @@ static __inline__ uint16_t bit_reverse16_dumb(uint16_t data) { int i; uint16_t result; - + result = 0; for (i = 0; i < 16; i++) { - result = (result << 1) | (data & 1); + result = (result << 1) | (data & 1); data >>= 1; } return result; @@ -125,11 +125,11 @@ static __inline__ uint32_t bit_reverse32_dumb(uint32_t data) { int i; uint32_t result; - + result = 0; for (i = 0; i < 32; i++) { - result = (result << 1) | (data & 1); + result = (result << 1) | (data & 1); data >>= 1; } return result; @@ -154,7 +154,7 @@ static __inline__ int one_bits32_dumb(uint32_t x) { int i; int bits; - + bits = 0; for (i = 0; i < 32; i++) { @@ -165,7 +165,7 @@ static __inline__ int one_bits32_dumb(uint32_t x) return bits; } /*- End of function --------------------------------------------------------*/ - + int main(int argc, char *argv[]) { int i; diff --git a/libs/spandsp/tests/bitstream_tests.c b/libs/spandsp/tests/bitstream_tests.c index e8ee4f0aab..2d70cd0029 100644 --- a/libs/spandsp/tests/bitstream_tests.c +++ b/libs/spandsp/tests/bitstream_tests.c @@ -153,7 +153,7 @@ int main(int argc, char *argv[]) } bitstream_flush(s, &w); printf("%d bits written\n", total_bits); - + for (cc = buffer; cc < w; cc++) printf("%02X ", *cc); printf("\n"); diff --git a/libs/spandsp/tests/crc_tests.c b/libs/spandsp/tests/crc_tests.c index a2d77ec3c4..3cb9221055 100644 --- a/libs/spandsp/tests/crc_tests.c +++ b/libs/spandsp/tests/crc_tests.c @@ -79,7 +79,7 @@ int main(int argc, char *argv[]) printf("CRC module tests\n"); /* TODO: This doesn't check every function in the module */ - + /* Try a few random messages through the CRC logic. */ printf("Testing the CRC-16 routines\n"); for (i = 0; i < 100; i++) @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) } } printf("Test passed.\n\n"); - + printf("Testing the CRC-16 byte by byte and bit by bit routines\n"); for (i = 0; i < 100; i++) { @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) } } printf("Test passed.\n\n"); - + printf("Testing the CRC-32 routines\n"); for (i = 0; i < 100; i++) { diff --git a/libs/spandsp/tests/echo_monitor.cpp b/libs/spandsp/tests/echo_monitor.cpp index 541aa03a64..690bc5da8c 100644 --- a/libs/spandsp/tests/echo_monitor.cpp +++ b/libs/spandsp/tests/echo_monitor.cpp @@ -216,7 +216,7 @@ int echo_can_monitor_line_spectrum_update(const int16_t amp[], int len) #endif } s->in_ptr = 0; -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) fftw_execute(s->p); #else fftw_one(s->p, s->in, s->out); @@ -227,7 +227,7 @@ int echo_can_monitor_line_spectrum_update(const int16_t amp[], int len) for (i = 0; i < 512; i++) { s->spec_re_plot[2*i] = i*4000.0/512.0; -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i][0]*s->out[i][0] + s->out[i][1]*s->out[i][1])/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14; #else s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i].re*s->out[i].re + s->out[i].im*s->out[i].im)/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14; @@ -394,7 +394,7 @@ int start_echo_can_monitor(int len) s->w->end(); s->w->show(); -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) s->p = fftw_plan_dft_1d(1024, s->in, s->out, FFTW_BACKWARD, FFTW_ESTIMATE); for (i = 0; i < 1024; i++) { @@ -416,7 +416,7 @@ int start_echo_can_monitor(int len) } /*- End of function --------------------------------------------------------*/ -void echo_can_monitor_wait_to_end(void) +void echo_can_monitor_wait_to_end(void) { fd_set rfds; int res; @@ -437,7 +437,7 @@ void echo_can_monitor_wait_to_end(void) } /*- End of function --------------------------------------------------------*/ -void echo_can_monitor_update_display(void) +void echo_can_monitor_update_display(void) { Fl::check(); Fl::check(); diff --git a/libs/spandsp/tests/fax_tester.h b/libs/spandsp/tests/fax_tester.h index 0d1f77f0bb..45054ec7ec 100644 --- a/libs/spandsp/tests/fax_tester.h +++ b/libs/spandsp/tests/fax_tester.h @@ -106,7 +106,7 @@ struct faxtester_state_s int current_tx_type; int wait_for_silence; - + int tone_state; int64_t tone_on_time; diff --git a/libs/spandsp/tests/line_model_monitor.cpp b/libs/spandsp/tests/line_model_monitor.cpp index 8e57fe8a94..a517c62e5b 100644 --- a/libs/spandsp/tests/line_model_monitor.cpp +++ b/libs/spandsp/tests/line_model_monitor.cpp @@ -417,7 +417,7 @@ int start_line_model_monitor(int len) } /*- End of function --------------------------------------------------------*/ -void line_model_monitor_wait_to_end(void) +void line_model_monitor_wait_to_end(void) { fd_set rfds; int res; @@ -438,7 +438,7 @@ void line_model_monitor_wait_to_end(void) } /*- End of function --------------------------------------------------------*/ -void line_model_monitor_update_display(void) +void line_model_monitor_update_display(void) { Fl::check(); Fl::check(); diff --git a/libs/spandsp/tests/line_model_tests.c b/libs/spandsp/tests/line_model_tests.c index db998ba0df..8f2091e3fb 100644 --- a/libs/spandsp/tests/line_model_tests.c +++ b/libs/spandsp/tests/line_model_tests.c @@ -115,13 +115,13 @@ static void test_one_way_model(int line_model_no, int speech_test) int i; int j; awgn_state_t noise1; - + if ((model = one_way_line_model_init(line_model_no, -50, channel_codec, rbs_pattern)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } - + awgn_init_dbm0(&noise1, 1234567, -10.0f); if (speech_test) @@ -157,7 +157,7 @@ static void test_one_way_model(int line_model_no, int speech_test) } for (j = 0; j < samples; j++) { - one_way_line_model(model, + one_way_line_model(model, &output1[j], &input1[j], 1); @@ -204,7 +204,7 @@ static void test_both_ways_model(int line_model_no, int speech_test) int j; awgn_state_t noise1; awgn_state_t noise2; - + if ((model = both_ways_line_model_init(line_model_no, -50, -15.0f, @@ -219,7 +219,7 @@ static void test_both_ways_model(int line_model_no, int speech_test) fprintf(stderr, " Failed to create line model\n"); exit(2); } - + awgn_init_dbm0(&noise1, 1234567, -10.0f); awgn_init_dbm0(&noise2, 1234567, -10.0f); @@ -268,7 +268,7 @@ static void test_both_ways_model(int line_model_no, int speech_test) } for (j = 0; j < samples; j++) { - both_ways_line_model(model, + both_ways_line_model(model, &output1[j], &input1[j], &output2[j], @@ -339,7 +339,7 @@ static void test_line_filter(int line_model_no) if (++p == 129) p = 0; ptr = p; - + /* Apply the filter */ out = 0.0f; for (j = 0; j < 129; j++) diff --git a/libs/spandsp/tests/lpc10_tests.c b/libs/spandsp/tests/lpc10_tests.c index 975ea3e555..dee9a624e1 100644 --- a/libs/spandsp/tests/lpc10_tests.c +++ b/libs/spandsp/tests/lpc10_tests.c @@ -149,13 +149,13 @@ int main(int argc, char *argv[]) fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); exit(2); } - + if ((lpc10_enc_state = lpc10_encode_init(NULL, TRUE)) == NULL) { fprintf(stderr, " Cannot create encoder\n"); exit(2); } - + if ((lpc10_dec_state = lpc10_decode_init(NULL, TRUE)) == NULL) { fprintf(stderr, " Cannot create decoder\n"); @@ -226,7 +226,7 @@ int main(int argc, char *argv[]) exit(2); } } - + if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); diff --git a/libs/spandsp/tests/media_monitor.cpp b/libs/spandsp/tests/media_monitor.cpp index cc7519bc82..ffdfc75a26 100644 --- a/libs/spandsp/tests/media_monitor.cpp +++ b/libs/spandsp/tests/media_monitor.cpp @@ -114,7 +114,7 @@ void media_monitor_rx(int seq_no, double departure_time, double arrival_time) } s->received_delays = new Ca_Line(2000, s->received_delays_plot, 0, 0, FL_BLUE, CA_NO_POINT); - + if (s->sent_re) delete s->sent_re; @@ -126,7 +126,7 @@ void media_monitor_rx(int seq_no, double departure_time, double arrival_time) s->sent_re_plot[2*(i%500) + 1] = 0.0; } s->sent_re_plot[2*(seq_no%500) + 1] = fdiff; - + if (fdiff > s->sent_re_plot_max) { s->sent_re_plot_max = fdiff; @@ -157,7 +157,7 @@ int start_media_monitor(void) float y; int i; int len; - + len = 128; s->w = new Fl_Double_Window(465, 400, "IP streaming media monitor"); @@ -255,7 +255,7 @@ int start_media_monitor(void) s->received_delays_plot_max = 0.0; s->min_diff = 2000; s->max_diff = 0; - + s->received_delays = NULL; s->highest_seq_no_seen = -1; @@ -278,7 +278,7 @@ int start_media_monitor(void) } /*- End of function --------------------------------------------------------*/ -void media_monitor_wait_to_end(void) +void media_monitor_wait_to_end(void) { fd_set rfds; int res; @@ -299,7 +299,7 @@ void media_monitor_wait_to_end(void) } /*- End of function --------------------------------------------------------*/ -void media_monitor_update_display(void) +void media_monitor_update_display(void) { Fl::check(); Fl::check(); diff --git a/libs/spandsp/tests/modem_monitor.cpp b/libs/spandsp/tests/modem_monitor.cpp index db8a31a22d..0c3c8ce8ab 100644 --- a/libs/spandsp/tests/modem_monitor.cpp +++ b/libs/spandsp/tests/modem_monitor.cpp @@ -61,7 +61,7 @@ struct qam_monitor_s Fl_Group *c_right; Fl_Group *c_eq; Fl_Group *c_symbol_track; - + /* Constellation stuff */ Ca_Canvas *canvas_const; Ca_X_Axis *sig_i; @@ -202,7 +202,7 @@ int qam_monitor_update_equalizer(qam_monitor_t *s, const complexf_t *coeffs, int if (max < coeffs[i].im) max = coeffs[i].im; } - + s->eq_x->minimum(-len/4.0); s->eq_x->maximum(len/4.0); s->eq_y->maximum((max == min) ? max + 0.2 : max); @@ -316,7 +316,7 @@ int qam_monitor_update_audio_level(qam_monitor_t *s, const int16_t amp[], int le int i; char buf[11]; double val; - + for (i = 0; i < len; i++) { s->audio_meter->sample(amp[i]/32768.0); @@ -385,10 +385,10 @@ qam_monitor_t *qam_monitor_init(float constel_width, float constel_scaling, cons float x; float y; qam_monitor_t *s; - + if ((s = (qam_monitor_t *) malloc(sizeof(*s))) == NULL) return NULL; - + s->w = new Fl_Double_Window(905, 400, (tag) ? tag : "QAM monitor"); s->constel_scaling = 1.0/constel_scaling; @@ -567,7 +567,7 @@ qam_monitor_t *qam_monitor_init(float constel_width, float constel_scaling, cons } /*- End of function --------------------------------------------------------*/ -void qam_wait_to_end(qam_monitor_t *s) +void qam_wait_to_end(qam_monitor_t *s) { fd_set rfds; int res; diff --git a/libs/spandsp/tests/t31_pseudo_terminal_tests.c b/libs/spandsp/tests/t31_pseudo_terminal_tests.c index 68e36f9184..c216a901c1 100644 --- a/libs/spandsp/tests/t31_pseudo_terminal_tests.c +++ b/libs/spandsp/tests/t31_pseudo_terminal_tests.c @@ -1,7 +1,7 @@ /* * SpanDSP - a series of DSP components for telephony * - * t31_pseudo_terminal_tests.c - + * t31_pseudo_terminal_tests.c - * * Written by Steve Underwood * @@ -125,7 +125,7 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result) { int i; char tag[20]; - + i = (intptr_t) user_data; snprintf(tag, sizeof(tag), "%c: Phase E", i); printf("Phase E handler on channel %c\n", i); @@ -316,7 +316,7 @@ static int modem_wait_sock(modem_t *modem, int ms, modem_poll_t flags) { if (GetLastError() != ERROR_IO_PENDING) { - /* Something went horribly wrong with WaitCommEvent(), so + /* Something went horribly wrong with WaitCommEvent(), so clear all errors and try again */ ClearCommError(modem->master, &comerrors, 0); } @@ -412,7 +412,7 @@ static int t30_tests(int t38_mode, int use_ecm, int use_gui, int log_audio, int #endif /* Test the T.31 modem against the full FAX machine in spandsp */ - + /* Set up the test environment */ t38_version = 1; without_pacing = FALSE; @@ -580,7 +580,7 @@ static int t30_tests(int t38_mode, int use_ecm, int use_gui, int log_audio, int while (!done) { - /* Deal with call setup, through the AT interface. */ + /* Deal with call setup, through the AT interface. */ if (test_sending) { } diff --git a/libs/spandsp/tests/t31_tests.c b/libs/spandsp/tests/t31_tests.c index ec14fcaca7..6967ee1a67 100644 --- a/libs/spandsp/tests/t31_tests.c +++ b/libs/spandsp/tests/t31_tests.c @@ -312,7 +312,7 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result) { int i; char tag[20]; - + i = (intptr_t) user_data; snprintf(tag, sizeof(tag), "%c: Phase E", i); printf("Phase E handler on channel %c\n", i); @@ -508,7 +508,7 @@ static int t30_tests(int t38_mode, int use_gui, int log_audio, int test_sending, SNDFILE *in_handle; /* Test the T.31 modem against the full FAX machine in spandsp */ - + /* Set up the test environment */ t38_version = 1; without_pacing = FALSE; @@ -668,7 +668,7 @@ static int t30_tests(int t38_mode, int use_gui, int log_audio, int test_sending, { if (countdown) { - /* Deal with call setup, through the AT interface. */ + /* Deal with call setup, through the AT interface. */ if (answered) { countdown = 0; diff --git a/libs/spandsp/tests/t38_core_tests.c b/libs/spandsp/tests/t38_core_tests.c index a282c1204f..094e688827 100644 --- a/libs/spandsp/tests/t38_core_tests.c +++ b/libs/spandsp/tests/t38_core_tests.c @@ -126,7 +126,7 @@ static int rx_data_handler(t38_core_state_t *s, void *user_data, int data_type, static int tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) { t38_core_state_t *t; - + t = (t38_core_state_t *) user_data; span_log(t38_core_get_logging_state(s), SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count); if (t38_core_rx_ifp_packet(t, buf, len, seq_no) < 0) @@ -151,7 +151,7 @@ static int encode_decode_tests(t38_core_state_t *a, t38_core_state_t *b) t38_data_field_t field[MAX_FIELDS]; int i; int j; - + ok_indicator_packets = 0; bad_indicator_packets = 0; ok_data_packets = 0; @@ -296,7 +296,7 @@ static int encode_then_decode_tests(t38_core_state_t *a, t38_core_state_t *b) int len; int i; int j; - + ok_indicator_packets = 0; bad_indicator_packets = 0; ok_data_packets = 0; diff --git a/libs/spandsp/tests/t38_decode.c b/libs/spandsp/tests/t38_decode.c index 7272cf9471..67660fe937 100644 --- a/libs/spandsp/tests/t38_decode.c +++ b/libs/spandsp/tests/t38_decode.c @@ -224,7 +224,7 @@ static int t38_gateway_timing_update(void *user_data, struct timeval *ts) } if (t38_gateway_rx(t38_gateway_state, t30_amp, t30_len)) break; - + t38_len = t38_gateway_tx(t38_gateway_state, t38_amp, partial); if (!use_transmit_on_idle) { @@ -295,7 +295,7 @@ static uint32_t parse_inet_addr(const char *s) uint32_t b; uint32_t c; uint32_t d; - + a = 0; b = 0; c = 0; diff --git a/libs/spandsp/tests/t38_non_ecm_buffer_tests.c b/libs/spandsp/tests/t38_non_ecm_buffer_tests.c index add5fb86f1..c9fa046cb4 100644 --- a/libs/spandsp/tests/t38_non_ecm_buffer_tests.c +++ b/libs/spandsp/tests/t38_non_ecm_buffer_tests.c @@ -645,7 +645,7 @@ int main(int argc, char *argv[]) } } printf(" Initial ones from an empty TCF buffer OK\n"); - + /* Now send some initial ones, and see that we continue to get all ones as the stuffing. */ memset(buf, 0xFF, 500); diff --git a/libs/spandsp/tests/t4_tests.c b/libs/spandsp/tests/t4_tests.c index 8b96f390f1..afded4ec2b 100644 --- a/libs/spandsp/tests/t4_tests.c +++ b/libs/spandsp/tests/t4_tests.c @@ -288,10 +288,10 @@ int main(int argc, char *argv[]) #if defined(SPANDSP_SUPPORT_T42x) T4_COMPRESSION_ITU_T42, T4_COMPRESSION_ITU_SYCC_T42, -#endif +#endif #if defined(SPANDSP_SUPPORT_T43x) T4_COMPRESSION_ITU_T43, -#endif +#endif T4_COMPRESSION_ITU_T85, T4_COMPRESSION_ITU_T85_L0, //T4_COMPRESSION_ITU_T45, diff --git a/libs/spandsp/tests/tsb85_tests.c b/libs/spandsp/tests/tsb85_tests.c index ddef770779..9d431f4f3f 100644 --- a/libs/spandsp/tests/tsb85_tests.c +++ b/libs/spandsp/tests/tsb85_tests.c @@ -99,7 +99,7 @@ static int phase_b_handler(t30_state_t *s, void *user_data, int result) int i; int status; const char *u; - + i = (intptr_t) user_data; status = T30_ERR_OK; if ((u = t30_get_rx_ident(s))) @@ -256,10 +256,10 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result) { int i; char tag[20]; - + i = (intptr_t) user_data; snprintf(tag, sizeof(tag), "%c: Phase E", i); - printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result)); + printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result)); fax_log_final_transfer_statistics(s, tag); fax_log_tx_parameters(s, tag); fax_log_rx_parameters(s, tag); @@ -289,7 +289,7 @@ static void t30_real_time_frame_handler(t30_state_t *s, static int document_handler(t30_state_t *s, void *user_data, int event) { int i; - + i = (intptr_t) user_data; fprintf(stderr, "%d: Document handler on channel %d - event %d\n", i, i, event); if (next_tx_file[0]) @@ -498,7 +498,7 @@ static int string_to_msg(uint8_t msg[], uint8_t mask[], const char buf[]) static void string_test2(const uint8_t msg[], int len) { int i; - + if (len > 0) { for (i = 0; i < len - 1; i++) @@ -514,7 +514,7 @@ static void string_test3(const char buf[]) uint8_t mask[1000]; int len; int i; - + len = string_to_msg(msg, mask, buf); printf("Len = %d: ", len); string_test2(msg, abs(len)); @@ -671,7 +671,7 @@ static int next_step(faxtester_state_t *s) s->cur = s->cur->next; span_log(&s->logging, - SPAN_LOG_FLOW, + SPAN_LOG_FLOW, "Dir - %s, type - %s, modem - %s, value - %s, timeout - %s, tag - %s\n", (dir) ? (const char *) dir : "", (type) ? (const char *) type : "", @@ -1111,7 +1111,7 @@ static void exchange(faxtester_state_t *s) span_log_bump_samples(logging, len); span_log_bump_samples(&s->logging, len); - + len = faxtester_tx(s, amp, SAMPLES_PER_CHUNK); if (fax_rx(fax, amp, len)) break; @@ -1207,7 +1207,7 @@ static int get_test_set(faxtester_state_t *s, const char *test_file, const char xmlNodePtr cur; xmlValidCtxt valid; - ns = NULL; + ns = NULL; xmlKeepBlanksDefault(0); xmlCleanupParser(); if ((doc = xmlParseFile(test_file)) == NULL) diff --git a/libs/spandsp/tests/v18_tests.c b/libs/spandsp/tests/v18_tests.c index f29430619d..f084cdeecb 100644 --- a/libs/spandsp/tests/v18_tests.c +++ b/libs/spandsp/tests/v18_tests.c @@ -1639,7 +1639,7 @@ static int test_x_06(void) msg[i] = i + 1; msg[127] = '\0'; printf("%s\n", msg); - + v18_encode_dtmf(NULL, dtmf, msg); printf("%s\n", dtmf); @@ -1780,7 +1780,7 @@ static int test_x_12(void) static void put_v18_msg(void *user_data, const uint8_t *msg, int len) { char buf[1024]; - + memcpy(buf, msg, len); buf[len] = '\0'; printf("Received (%d bytes) '%s'\n", len, buf); diff --git a/libs/spandsp/tests/v22bis_tests.c b/libs/spandsp/tests/v22bis_tests.c index dd3564cdcb..82722e2556 100644 --- a/libs/spandsp/tests/v22bis_tests.c +++ b/libs/spandsp/tests/v22bis_tests.c @@ -87,7 +87,7 @@ endpoint_t endpoint[2]; static void reporter(void *user_data, int reason, bert_results_t *results) { endpoint_t *s; - + s = (endpoint_t *) user_data; switch (reason) { @@ -100,7 +100,7 @@ static void reporter(void *user_data, int reason, bert_results_t *results) memcpy(&s->latest_results, results, sizeof(s->latest_results)); break; default: - fprintf(stderr, + fprintf(stderr, "V.22bis rx %p BERT report %s\n", user_data, bert_event_to_str(reason)); @@ -271,7 +271,7 @@ int main(int argc, char *argv[]) int rbs_pattern; int guard_tone_option; int opt; - + channel_codec = MUNGE_CODEC_NONE; rbs_pattern = 0; test_bps = 2400; @@ -373,7 +373,7 @@ int main(int argc, char *argv[]) bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]); } - + #if defined(ENABLE_GUI) if (use_gui) { @@ -420,7 +420,7 @@ int main(int argc, char *argv[]) } #if 1 - both_ways_line_model(model, + both_ways_line_model(model, model_amp[0], amp[0], model_amp[1], diff --git a/libs/spandsp/tests/v29_tests.c b/libs/spandsp/tests/v29_tests.c index 900121c23c..246c217fd1 100644 --- a/libs/spandsp/tests/v29_tests.c +++ b/libs/spandsp/tests/v29_tests.c @@ -327,7 +327,7 @@ int main(int argc, char *argv[]) int rbs_pattern; int opt; logging_state_t *logging; - + channel_codec = MUNGE_CODEC_NONE; rbs_pattern = 0; test_bps = 9600; @@ -551,7 +551,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Final result %ddBm0/%ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, noise_level, bert_results.total_bits, bert_results.bad_bits, bert_results.resyncs); fprintf(stderr, "Last report %ddBm0/%ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, noise_level, latest_results.total_bits, latest_results.bad_bits, latest_results.resyncs); one_way_line_model_release(line_model); - + if (signal_level > -43) { printf("Tests failed.\n"); diff --git a/libs/spandsp/tests/v42bis_tests.c b/libs/spandsp/tests/v42bis_tests.c index 06381e6e60..cc95967c54 100644 --- a/libs/spandsp/tests/v42bis_tests.c +++ b/libs/spandsp/tests/v42bis_tests.c @@ -57,7 +57,7 @@ int out_octets_to_date = 0; static void frame_handler(void *user_data, const uint8_t *buf, int len) { int ret; - + if ((ret = write((intptr_t) user_data, buf, len)) != len) fprintf(stderr, "Write error %d/%d\n", ret, errno); out_octets_to_date += len; @@ -198,7 +198,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Error opening file '%s'.\n", decompressed_file); exit(2); } - + time(&now); state_b = v42bis_init(NULL, 3, 512, 6, frame_handler, (void *) (intptr_t) v42bis_fd, 512, data_handler, (void *) (intptr_t) out_fd, 512); span_log_set_level(v42bis_get_logging_state(state_b), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); diff --git a/libs/spandsp/tests/v8_tests.c b/libs/spandsp/tests/v8_tests.c index 5961ef5dc6..d9ef7b82b9 100644 --- a/libs/spandsp/tests/v8_tests.c +++ b/libs/spandsp/tests/v8_tests.c @@ -77,7 +77,7 @@ static int select_modulation(int mask) static void handler(void *user_data, v8_parms_t *result) { const char *s; - + s = (const char *) user_data; printf("%s ", s); @@ -362,7 +362,7 @@ static int non_v8_calls_v8_tests(SNDFILE *outhandle) for (i = 0; i < samples; i++) out_amp[2*i] = amp[i]; /*endfor*/ - + samples = v8_tx(v8_answerer, amp, SAMPLES_PER_CHUNK); if (samples < SAMPLES_PER_CHUNK) { @@ -472,7 +472,7 @@ static int v8_calls_non_v8_tests(SNDFILE *outhandle) for (i = 0; i < samples; i++) out_amp[2*i] = amp[i]; /*endfor*/ - + samples = modem_connect_tones_tx(non_v8_answerer_tx, amp, SAMPLES_PER_CHUNK); if (samples < SAMPLES_PER_CHUNK) { diff --git a/libs/spandsp/tests/vector_float_tests.c b/libs/spandsp/tests/vector_float_tests.c index 2d388fc9dc..26df593864 100644 --- a/libs/spandsp/tests/vector_float_tests.c +++ b/libs/spandsp/tests/vector_float_tests.c @@ -37,7 +37,7 @@ static void vec_copyf_dumb(float z[], const float x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = x[i]; } @@ -97,7 +97,7 @@ static int test_vec_copyf(void) static void vec_negatef_dumb(float z[], const float x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = -x[i]; } @@ -157,7 +157,7 @@ static int test_vec_negatef(void) static void vec_zerof_dumb(float z[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = 0.0f; } @@ -215,7 +215,7 @@ static int test_vec_zerof(void) static void vec_setf_dumb(float z[], float x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = x; } diff --git a/libs/spandsp/tests/vector_int_tests.c b/libs/spandsp/tests/vector_int_tests.c index 1b0aa309c1..0ac0c6424c 100644 --- a/libs/spandsp/tests/vector_int_tests.c +++ b/libs/spandsp/tests/vector_int_tests.c @@ -81,7 +81,7 @@ static int32_t vec_min_maxi16_dumb(const int16_t x[], int n, int16_t out[]) int16_t max; int16_t temp; int32_t z; - + max = INT16_MIN; min = INT16_MAX; for (i = 0; i < n; i++) @@ -103,7 +103,7 @@ static int32_t vec_min_maxi16_dumb(const int16_t x[], int n, int16_t out[]) return max; } /*- End of function --------------------------------------------------------*/ - + static int test_vec_min_maxi16(void) { int i; From 77ee3fe10c55430c096d91a87388e29159504e05 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 13 Mar 2013 16:10:36 -0500 Subject: [PATCH 023/113] fix a few rare race conditions that could lead to a lockup --- src/switch_core_sqldb.c | 23 ++++++++++++++++++++++- src/switch_scheduler.c | 12 ++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index cdea61ab25..1b607910c3 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1250,6 +1250,7 @@ struct switch_sql_queue_manager { int thread_running; switch_thread_cond_t *cond; switch_mutex_t *cond_mutex; + switch_mutex_t *cond2_mutex; switch_mutex_t *mutex; char *pre_trans_execute; char *post_trans_execute; @@ -1262,10 +1263,26 @@ struct switch_sql_queue_manager { static int qm_wake(switch_sql_queue_manager_t *qm) { - if (switch_mutex_trylock(qm->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_status_t status; + int tries = 0; + + top: + + status = switch_mutex_trylock(qm->cond_mutex); + + if (status == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(qm->cond); switch_mutex_unlock(qm->cond_mutex); return 1; + } else { + if (switch_mutex_trylock(qm->cond2_mutex) == SWITCH_STATUS_SUCCESS) { + switch_mutex_unlock(qm->cond2_mutex); + } else { + if (++tries < 10) { + switch_cond_next(); + goto top; + } + } } return 0; @@ -1407,6 +1424,7 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_stop(switch_sql_queue_m if (qm->thread) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Stopping SQL thread.\n", qm->name); + qm_wake(qm); switch_thread_join(&status, qm->thread); qm->thread = NULL; status = SWITCH_STATUS_SUCCESS; @@ -1596,6 +1614,7 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_init_name(const char *n qm->max_trans = max_trans; switch_mutex_init(&qm->cond_mutex, SWITCH_MUTEX_NESTED, qm->pool); + switch_mutex_init(&qm->cond2_mutex, SWITCH_MUTEX_NESTED, qm->pool); switch_mutex_init(&qm->mutex, SWITCH_MUTEX_NESTED, qm->pool); switch_thread_cond_create(&qm->cond, qm->pool); @@ -1850,7 +1869,9 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, check: if ((lc = qm_ttl(qm)) == 0) { + switch_mutex_lock(qm->cond2_mutex); switch_thread_cond_wait(qm->cond, qm->cond_mutex); + switch_mutex_unlock(qm->cond2_mutex); } i = 40; diff --git a/src/switch_scheduler.c b/src/switch_scheduler.c index d6f501e453..d59a7608e3 100644 --- a/src/switch_scheduler.c +++ b/src/switch_scheduler.c @@ -37,6 +37,7 @@ struct switch_scheduler_task_container { int64_t executed; int in_thread; int destroyed; + int running; switch_scheduler_func_t func; switch_memory_pool_t *pool; uint32_t flags; @@ -124,7 +125,11 @@ static int task_thread_loop(int done) tp->in_thread = 1; switch_thread_create(&thread, thd_attr, task_own_thread, tp, tp->pool); } else { + tp->running = 1; + switch_mutex_unlock(globals.task_mutex); switch_scheduler_execute(tp); + switch_mutex_lock(globals.task_mutex); + tp->running = 0; } } } @@ -238,6 +243,13 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_del_task_id(uint32_t task_id) tp->task.task_id, tp->task.group); break; } + + if (tp->running) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Attempt made to delete running task #%u (group %s)\n", + tp->task.task_id, tp->task.group); + break; + } + tp->destroyed++; if (switch_event_create(&event, SWITCH_EVENT_DEL_SCHEDULE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id); From 16289ce9a4da11954ae0d68d21de929c741f9cfc Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 13 Mar 2013 22:24:25 -0500 Subject: [PATCH 024/113] FS-5166 --resolve exec for windows --- src/switch_xml.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/switch_xml.c b/src/switch_xml.c index fe67c95169..7c47ebebec 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -1230,11 +1230,27 @@ static char *expand_vars(char *buf, char *ebuf, switch_size_t elen, switch_size_ static FILE *preprocess_exec(const char *cwd, const char *command, FILE *write_fd, int rlevel) { #ifdef WIN32 - char message[] = ""; + FILE *fp = NULL; + char buffer[1024]; - if (fwrite( message, 1, sizeof(message), write_fd) < 0) { - goto end; - } + if (!command || !strlen(command)) goto end; + + if ((fp = _popen(command, "r"))) { + while (fgets(buffer, sizeof(buffer), fp) != NULL) { + if (fwrite(buffer, 1, strlen(buffer), write_fd) <= 0) { + break; + } + } + + if(feof(fp)) { + _pclose(fp); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exec failed to read the pipe of [%s] to the end\n", command); + } + } else { + switch_snprintf(buffer, sizeof(buffer), "", command); + fwrite( buffer, 1, strlen(buffer), write_fd); + } #else int fds[2], pid = 0; From d163c6338e5c2eaa28bf24ec3fb15d89cab41e78 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Thu, 14 Mar 2013 21:22:51 +0800 Subject: [PATCH 025/113] Lots of little cosmetic cleanups --- libs/spandsp/src/complex_filters.c | 2 +- libs/spandsp/src/crc.c | 62 +- libs/spandsp/src/dds_int.c | 2 +- libs/spandsp/src/dtmf.c | 4 +- libs/spandsp/src/echo.c | 12 +- libs/spandsp/src/filter_tools.c | 14 +- libs/spandsp/src/floating_fudge.h | 20 +- libs/spandsp/src/fsk.c | 6 +- libs/spandsp/src/gsm0610_encode.c | 46 +- libs/spandsp/src/gsm0610_local.h | 2 +- libs/spandsp/src/lpc10_encdecs.h | 2 +- libs/spandsp/src/math_fixed.c | 4 +- libs/spandsp/src/modem_connect_tones.c | 6 +- libs/spandsp/src/msvc/config.h | 4 +- libs/spandsp/src/msvc/inttypes.h | 4 +- libs/spandsp/src/msvc/spandsp.h | 4 + libs/spandsp/src/oki_adpcm.c | 6 +- libs/spandsp/src/sig_tone.c | 18 +- libs/spandsp/src/spandsp/complex.h | 6 +- .../src/spandsp/complex_vector_float.h | 18 +- libs/spandsp/src/spandsp/complex_vector_int.h | 6 +- libs/spandsp/src/spandsp/dc_restore.h | 6 +- libs/spandsp/src/spandsp/dtmf.h | 6 +- libs/spandsp/src/spandsp/echo.h | 14 +- libs/spandsp/src/spandsp/fast_convert.h | 17 +- libs/spandsp/src/spandsp/fir.h | 12 +- libs/spandsp/src/spandsp/fsk.h | 10 +- libs/spandsp/src/spandsp/g168models.h | 2 +- libs/spandsp/src/spandsp/hdlc.h | 4 +- libs/spandsp/src/spandsp/noise.h | 2 +- libs/spandsp/src/spandsp/oki_adpcm.h | 2 +- libs/spandsp/src/spandsp/playout.h | 2 +- libs/spandsp/src/spandsp/private/dtmf.h | 2 +- libs/spandsp/src/spandsp/private/echo.h | 14 +- libs/spandsp/src/spandsp/private/hdlc.h | 2 +- libs/spandsp/src/spandsp/private/oki_adpcm.h | 2 +- libs/spandsp/src/spandsp/private/t31.h | 2 +- libs/spandsp/src/spandsp/private/t85.h | 2 +- libs/spandsp/src/spandsp/super_tone_rx.h | 2 +- libs/spandsp/src/spandsp/super_tone_tx.h | 2 +- libs/spandsp/src/spandsp/t38_terminal.h | 2 +- libs/spandsp/src/spandsp/t42.h | 4 +- libs/spandsp/src/spandsp/t4_rx.h | 8 +- libs/spandsp/src/spandsp/t4_t6_encode.h | 4 +- libs/spandsp/src/spandsp/t4_tx.h | 4 +- .../src/spandsp/t81_t82_arith_coding.h | 1 - libs/spandsp/src/spandsp/t85.h | 4 +- libs/spandsp/src/spandsp/tone_detect.h | 2 +- libs/spandsp/src/spandsp/v8.h | 2 +- libs/spandsp/src/spandsp/vector_int.h | 8 +- libs/spandsp/src/super_tone_tx.c | 5 +- libs/spandsp/src/swept_tone.c | 2 +- libs/spandsp/src/t35.c | 4 +- libs/spandsp/src/t42.c | 16 +- libs/spandsp/src/t4_t6_decode.c | 20 +- libs/spandsp/src/t4_t6_encode.c | 32 +- libs/spandsp/src/t4_tx.c | 8 +- libs/spandsp/src/testcpuid.c | 75 +- libs/spandsp/src/time_scale.c | 2 +- libs/spandsp/src/tone_detect.c | 2 +- libs/spandsp/src/v27ter_tx.c | 2 +- libs/spandsp/src/v42.c | 8 +- libs/spandsp/src/v42bis.c | 10 +- libs/spandsp/src/v8.c | 18 +- libs/spandsp/src/vector_float.c | 52 +- .../etsi/fax/generate_etsi_300_242_pages.c | 6 +- .../test-data/itu/fax/generate_dithered_tif.c | 2 +- .../test-data/itu/fax/generate_sized_pages.c | 64 +- libs/spandsp/tests/ademco_contactid_tests.c | 2 +- libs/spandsp/tests/adsi_tests.c | 4 +- libs/spandsp/tests/async_tests.c | 6 +- libs/spandsp/tests/at_interpreter_tests.c | 12 +- libs/spandsp/tests/awgn_tests.c | 2 +- libs/spandsp/tests/bell_mf_rx_tests.c | 58 +- libs/spandsp/tests/dc_restore_tests.c | 2 +- libs/spandsp/tests/dtmf_rx_tests.c | 26 +- libs/spandsp/tests/echo_tests.c | 64 +- libs/spandsp/tests/fax_decode.c | 4 +- libs/spandsp/tests/fax_tester.c | 10 +- libs/spandsp/tests/fax_tests.c | 13 +- libs/spandsp/tests/fax_utils.c | 2 +- libs/spandsp/tests/fsk_tests.c | 10 +- libs/spandsp/tests/g711_tests.c | 6 +- libs/spandsp/tests/g722_tests.c | 10 +- libs/spandsp/tests/g726_tests.c | 8 +- libs/spandsp/tests/gsm0610_tests.c | 28 +- libs/spandsp/tests/hdlc_tests.c | 2 +- libs/spandsp/tests/ima_adpcm_tests.c | 4 +- libs/spandsp/tests/image_translate_tests.c | 2 +- libs/spandsp/tests/make_g168_css.c | 2 +- .../spandsp/tests/modem_connect_tones_tests.c | 2 +- libs/spandsp/tests/modem_echo_tests.c | 18 +- libs/spandsp/tests/noise_tests.c | 4 +- libs/spandsp/tests/pcap_parse.c | 5 +- libs/spandsp/tests/playout_tests.c | 2 +- libs/spandsp/tests/power_meter_tests.c | 4 +- libs/spandsp/tests/queue_tests.c | 2 +- libs/spandsp/tests/r2_mf_rx_tests.c | 102 +- libs/spandsp/tests/rfc2198_sim_tests.c | 2 +- libs/spandsp/tests/saturated_tests.c | 2 +- libs/spandsp/tests/schedule_tests.c | 2 +- libs/spandsp/tests/sig_tone_tests.c | 10 +- libs/spandsp/tests/super_tone_rx_tests.c | 14 +- libs/spandsp/tests/super_tone_tx_tests.c | 2 +- .../spandsp/tests/t31_pseudo_terminal_tests.c | 104 +- libs/spandsp/tests/t85_tests.c | 4 +- libs/spandsp/tests/tone_generate_tests.c | 6 +- libs/spandsp/tests/udptl.c | 31 +- libs/spandsp/tests/v18_tests.c | 6707 ++++++++++++++++- libs/spandsp/tests/v22bis_tests.c | 1 - 110 files changed, 7259 insertions(+), 762 deletions(-) diff --git a/libs/spandsp/src/complex_filters.c b/libs/spandsp/src/complex_filters.c index 36af84b36a..d54e55818a 100644 --- a/libs/spandsp/src/complex_filters.c +++ b/libs/spandsp/src/complex_filters.c @@ -101,7 +101,7 @@ SPAN_DECLARE(void) cfilter_delete(cfilter_t *cfi) SPAN_DECLARE(complexf_t) cfilter_step(cfilter_t *cfi, const complexf_t *z) { complexf_t cc; - + cc.re = filter_step(cfi->ref, z->re); cc.im = filter_step(cfi->imf, z->im); return cc; diff --git a/libs/spandsp/src/crc.c b/libs/spandsp/src/crc.c index f970fe8a2c..f7407eda1f 100644 --- a/libs/spandsp/src/crc.c +++ b/libs/spandsp/src/crc.c @@ -39,37 +39,37 @@ static const uint32_t crc_itu32_table[] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; diff --git a/libs/spandsp/src/dds_int.c b/libs/spandsp/src/dds_int.c index ad126f620a..3f1734b88b 100644 --- a/libs/spandsp/src/dds_int.c +++ b/libs/spandsp/src/dds_int.c @@ -348,7 +348,7 @@ SPAN_DECLARE(int16_t) dds_lookup(uint32_t phase) step = DDS_STEPS - step; amp = sine_table[step]; if ((phase & (2*DDS_STEPS))) - amp = -amp; + amp = -amp; return amp; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/dtmf.c b/libs/spandsp/src/dtmf.c index 196e3d3eca..6884d2b770 100644 --- a/libs/spandsp/src/dtmf.c +++ b/libs/spandsp/src/dtmf.c @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ #if defined(HAVE_CONFIG_H) @@ -129,7 +129,7 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples) limit = sample + (DTMF_SAMPLES_PER_BLOCK - s->current_sample); else limit = samples; - /* The following unrolled loop takes only 35% (rough estimate) of the + /* The following unrolled loop takes only 35% (rough estimate) of the time of a rolled loop on the machine on which it was developed */ for (j = sample; j < limit; j++) { diff --git a/libs/spandsp/src/echo.c b/libs/spandsp/src/echo.c index 0b1aaac2aa..84926fa3c4 100644 --- a/libs/spandsp/src/echo.c +++ b/libs/spandsp/src/echo.c @@ -50,13 +50,13 @@ /* The FIR taps must be adapted as 32 bit values, to get the necessary finesse in the adaption process. However, they are applied as 16 bit values (bits 30-15 of the 32 bit values) in the FIR. For the working 16 bit values, we need 4 sets. - + 3 of the 16 bit sets are used on a rotating basis. Normally the canceller steps round these 3 sets at regular intervals. Any time we detect double talk, we can go back to the set from two steps ago with reasonable assurance it is a well adapted set. We cannot just go back one step, as we may have rotated the sets just before double talk or tone was detected, and that set may already be somewhat corrupted. - + When narrowband energy is detected we need to continue adapting to it, to echo cancel it. However, the adaption will almost certainly be going astray. Broadband (or even complex sequences of narrowband) energy will normally lead to a well @@ -129,7 +129,7 @@ static int narrowband_detect(echo_can_state_t *ec) int score; int len = 32; int alen = 9; - + k = ec->curr_pos; for (i = 0; i < len; i++) { @@ -292,7 +292,7 @@ SPAN_DECLARE(int) echo_can_release(echo_can_state_t *ec) SPAN_DECLARE(int) echo_can_free(echo_can_state_t *ec) { int i; - + fir16_free(&ec->fir_state); free(ec->fir_taps32); for (i = 0; i < 4; i++) @@ -361,7 +361,7 @@ static __inline__ int16_t echo_can_hpf(int32_t coeff[2], int16_t amp) { int32_t z; - /* + /* Filter DC, 3dB point is 160Hz (I think), note 32 bit precision required otherwise values do not track down to 0. Zero at DC, Pole at (1-Beta) only real axis. Some chip sets (like Si labs) don't need @@ -371,7 +371,7 @@ static __inline__ int16_t echo_can_hpf(int32_t coeff[2], int16_t amp) Note: removes some low frequency from the signal, this reduces the speech quality when listening to samples through headphones but may not be obvious through a telephone handset. - + Note that the 3dB frequency in radians is approx Beta, e.g. for Beta = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz. diff --git a/libs/spandsp/src/filter_tools.c b/libs/spandsp/src/filter_tools.c index 1743747166..88967e93ed 100644 --- a/libs/spandsp/src/filter_tools.c +++ b/libs/spandsp/src/filter_tools.c @@ -25,7 +25,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + #if defined(HAVE_CONFIG_H) #include "config.h" #endif @@ -55,7 +55,7 @@ #define TRUE (!FALSE) #endif -#define MAXPZ 8192 +#define MAXPZ 8192 #define SEQ_LEN 8192 #define MAX_FFT_LEN SEQ_LEN @@ -139,7 +139,7 @@ void compute_raised_cosine_filter(double coeffs[], int i; int j; int h; - + f1 = (1.0 - beta)*alpha; f2 = (1.0 + beta)*alpha; tau = 0.5/alpha; @@ -162,10 +162,10 @@ void compute_raised_cosine_filter(double coeffs[], if (sinc_compensate) { for (i = 1; i <= SEQ_LEN/2; i++) - { + { x = 3.1415926535*(double) i/(double) SEQ_LEN; - vec[i].re *= (x/sin(x)); - } + vec[i].re *= (x/sin(x)); + } } for (i = 0; i <= SEQ_LEN/2; i++) vec[i].re *= tau; @@ -228,7 +228,7 @@ void truncate_coeffs(double coeffs[], int len, int bits, int hilbert) fac = pow(2.0, (double) (bits - 1.0)); h = (len - 1)/2; - max = (hilbert) ? coeffs[h - 1] : coeffs[h]; /* Max coeff */ + max = (hilbert) ? coeffs[h - 1] : coeffs[h]; /* Max coeff */ scale = (fac - 1.0)/(fac*max); for (i = 0; i < len; i++) { diff --git a/libs/spandsp/src/floating_fudge.h b/libs/spandsp/src/floating_fudge.h index 2ef0423399..a2e46db46d 100644 --- a/libs/spandsp/src/floating_fudge.h +++ b/libs/spandsp/src/floating_fudge.h @@ -37,42 +37,42 @@ extern "C" #if !defined(HAVE_SINF) static __inline__ float sinf(float x) { - return (float) sin((double) x); + return (float) sin((double) x); } #endif #if !defined(HAVE_COSF) static __inline__ float cosf(float x) { - return (float) cos((double) x); + return (float) cos((double) x); } #endif #if !defined(HAVE_TANF) static __inline__ float tanf(float x) { - return (float) tan((double) x); + return (float) tan((double) x); } #endif #if !defined(HAVE_ASINF) static __inline__ float asinf(float x) { - return (float) asin((double) x); + return (float) asin((double) x); } #endif #if !defined(HAVE_ACOSF) static __inline__ float acosf(float x) { - return (float) acos((double) x); + return (float) acos((double) x); } #endif #if !defined(HAVE_ATANF) static __inline__ float atanf(float x) { - return (float) atan((double) x); + return (float) atan((double) x); } #endif @@ -80,7 +80,7 @@ static __inline__ float atanf(float x) #if !defined(HAVE_ATAN2F) static __inline__ float atan2f(float y, float x) { - return (float) atan2((double) y, (double) x); + return (float) atan2((double) y, (double) x); } #endif @@ -88,14 +88,14 @@ static __inline__ float atan2f(float y, float x) #if !defined(HAVE_CEILF) static __inline__ float ceilf(float x) { - return (float) ceil((double) x); + return (float) ceil((double) x); } #endif #if !defined(HAVE_FLOORF) static __inline__ float floorf(float x) { - return (float) floor((double) x); + return (float) floor((double) x); } #endif @@ -117,7 +117,7 @@ static __inline__ float expf(float x) #if !defined(HAVE_LOGF) static __inline__ float logf(float x) { - return (float) logf((double) x); + return (float) logf((double) x); } #endif diff --git a/libs/spandsp/src/fsk.c b/libs/spandsp/src/fsk.c index d95f757468..56f155169e 100644 --- a/libs/spandsp/src/fsk.c +++ b/libs/spandsp/src/fsk.c @@ -144,7 +144,7 @@ SPAN_DECLARE(int) fsk_tx_restart(fsk_tx_state_t *s, const fsk_spec_t *spec) s->phase_acc = 0; s->baud_frac = 0; s->current_phase_rate = s->phase_rates[1]; - + s->shutdown = FALSE; return 0; } @@ -273,7 +273,7 @@ SPAN_DECLARE(int) fsk_rx_restart(fsk_rx_state_t *s, const fsk_spec_t *spec, int /* Detect by correlating against the tones we want, over a period of one baud. The correlation must be quadrature. */ - + /* First we need the quadrature tone generators to correlate against. */ s->phase_rate[0] = dds_phase_rate((float) spec->freq_zero); @@ -303,7 +303,7 @@ SPAN_DECLARE(int) fsk_rx_restart(fsk_rx_state_t *s, const fsk_spec_t *spec, int s->frame_state = 0; s->frame_bits = 0; s->last_bit = 0; - + /* Initialise a power detector, so sense when a signal is present. */ power_meter_init(&(s->power), 4); s->signal_present = 0; diff --git a/libs/spandsp/src/gsm0610_encode.c b/libs/spandsp/src/gsm0610_encode.c index c9e5251ef0..2c359688fe 100644 --- a/libs/spandsp/src/gsm0610_encode.c +++ b/libs/spandsp/src/gsm0610_encode.c @@ -170,32 +170,32 @@ SPAN_DECLARE(int) gsm0610_pack_wav49(uint8_t c[], const gsm0610_frame_t *s) uint16_t sr; int i; - sr = 0; - sr = (sr >> 6) | (s->LARc[0] << 10); - sr = (sr >> 6) | (s->LARc[1] << 10); - *c++ = (uint8_t) (sr >> 4); - sr = (sr >> 5) | (s->LARc[2] << 11); - *c++ = (uint8_t) (sr >> 7); - sr = (sr >> 5) | (s->LARc[3] << 11); - sr = (sr >> 4) | (s->LARc[4] << 12); - *c++ = (uint8_t) (sr >> 6); - sr = (sr >> 4) | (s->LARc[5] << 12); - sr = (sr >> 3) | (s->LARc[6] << 13); - *c++ = (uint8_t) (sr >> 7); - sr = (sr >> 3) | (s->LARc[7] << 13); + sr = 0; + sr = (sr >> 6) | (s->LARc[0] << 10); + sr = (sr >> 6) | (s->LARc[1] << 10); + *c++ = (uint8_t) (sr >> 4); + sr = (sr >> 5) | (s->LARc[2] << 11); + *c++ = (uint8_t) (sr >> 7); + sr = (sr >> 5) | (s->LARc[3] << 11); + sr = (sr >> 4) | (s->LARc[4] << 12); + *c++ = (uint8_t) (sr >> 6); + sr = (sr >> 4) | (s->LARc[5] << 12); + sr = (sr >> 3) | (s->LARc[6] << 13); + *c++ = (uint8_t) (sr >> 7); + sr = (sr >> 3) | (s->LARc[7] << 13); for (i = 0; i < 4; i++) { - sr = (sr >> 7) | (s->Nc[i] << 9); - *c++ = (uint8_t) (sr >> 5); - sr = (sr >> 2) | (s->bc[i] << 14); - sr = (sr >> 2) | (s->Mc[i] << 14); - sr = (sr >> 6) | (s->xmaxc[i] << 10); - *c++ = (uint8_t) (sr >> 3); - sr = (sr >> 3) | (s->xMc[i][0] << 13); - *c++ = (uint8_t) (sr >> 8); - sr = (sr >> 3) | (s->xMc[i][1] << 13); - sr = (sr >> 3) | (s->xMc[i][2] << 13); + sr = (sr >> 7) | (s->Nc[i] << 9); + *c++ = (uint8_t) (sr >> 5); + sr = (sr >> 2) | (s->bc[i] << 14); + sr = (sr >> 2) | (s->Mc[i] << 14); + sr = (sr >> 6) | (s->xmaxc[i] << 10); + *c++ = (uint8_t) (sr >> 3); + sr = (sr >> 3) | (s->xMc[i][0] << 13); + *c++ = (uint8_t) (sr >> 8); + sr = (sr >> 3) | (s->xMc[i][1] << 13); + sr = (sr >> 3) | (s->xMc[i][2] << 13); sr = (sr >> 3) | (s->xMc[i][3] << 13); *c++ = (uint8_t) (sr >> 7); sr = (sr >> 3) | (s->xMc[i][4] << 13); diff --git a/libs/spandsp/src/gsm0610_local.h b/libs/spandsp/src/gsm0610_local.h index e3150f62de..84c4c20edc 100644 --- a/libs/spandsp/src/gsm0610_local.h +++ b/libs/spandsp/src/gsm0610_local.h @@ -31,7 +31,7 @@ #define GSM0610_FRAME_LEN 160 -#define GSM0610_MAGIC 0xD +#define GSM0610_MAGIC 0xD #include "spandsp/private/gsm0610.h" diff --git a/libs/spandsp/src/lpc10_encdecs.h b/libs/spandsp/src/lpc10_encdecs.h index f146652ac4..621b15a83a 100644 --- a/libs/spandsp/src/lpc10_encdecs.h +++ b/libs/spandsp/src/lpc10_encdecs.h @@ -62,7 +62,7 @@ void lpc10_voicing(lpc10_encode_state_t *st, int32_t half, float *minamd, float *maxamd, - int32_t *mintau, + int32_t *mintau, float *ivrc, int32_t *obound); diff --git a/libs/spandsp/src/math_fixed.c b/libs/spandsp/src/math_fixed.c index b4d57a917d..f538f106f4 100644 --- a/libs/spandsp/src/math_fixed.c +++ b/libs/spandsp/src/math_fixed.c @@ -180,7 +180,7 @@ SPAN_DECLARE(int16_t) fixed_sin(uint16_t x) } z = fixed_sine_table[step] + ((frac*(fixed_sine_table[step_after] - fixed_sine_table[step])) >> 6); if ((x & 0x8000)) - z = -z; + z = -z; return z; } /*- End of function --------------------------------------------------------*/ @@ -206,7 +206,7 @@ SPAN_DECLARE(int16_t) fixed_cos(uint16_t x) } z = fixed_sine_table[step] + ((frac*(fixed_sine_table[step_after] - fixed_sine_table[step])) >> 6); if ((x & 0x8000)) - z = -z; + z = -z; return z; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/modem_connect_tones.c b/libs/spandsp/src/modem_connect_tones.c index 0ad2b4bda4..76b42a23fc 100644 --- a/libs/spandsp/src/modem_connect_tones.c +++ b/libs/spandsp/src/modem_connect_tones.c @@ -23,7 +23,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ /* CNG is 0.5s+-15% of 1100+-38Hz, 3s+-15% off, repeating. @@ -36,7 +36,7 @@ ANS/ is 3.3+-0.7s of 2100+-15Hz, with phase reversals (180+-10 degrees, hopping in <1ms) every 450+-25ms. - ANSam/ is 2100+-1Hz, with phase reversals (180+-10 degrees, hopping in <1ms) every 450+-25ms, and AM with a sinewave of 15+-0.1Hz. + ANSam/ is 2100+-1Hz, with phase reversals (180+-10 degrees, hopping in <1ms) every 450+-25ms, and AM with a sinewave of 15+-0.1Hz. The modulated envelope ranges in amplitude between (0.8+-0.01) and (1.2+-0.01) times its average amplitude. It lasts up to 5s, but will be stopped early if the V.8 protocol proceeds. */ @@ -702,7 +702,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx_fillin(modem_connect_tones_rx_st SPAN_DECLARE(int) modem_connect_tones_rx_get(modem_connect_tones_rx_state_t *s) { int x; - + x = s->hit; s->hit = MODEM_CONNECT_TONES_NONE; return x; diff --git a/libs/spandsp/src/msvc/config.h b/libs/spandsp/src/msvc/config.h index 42494d345f..876f66f56a 100644 --- a/libs/spandsp/src/msvc/config.h +++ b/libs/spandsp/src/msvc/config.h @@ -54,8 +54,8 @@ #endif #endif // VC8+ - // disable the following warnings - #pragma warning(disable:4100) // The formal parameter is not referenced in the body of the function. The unreferenced parameter is ignored. + // disable the following warnings + #pragma warning(disable:4100) // The formal parameter is not referenced in the body of the function. The unreferenced parameter is ignored. #pragma warning(disable:4200) // Non standard extension C zero sized array #pragma warning(disable:4706) // assignment within conditional expression #pragma warning(disable:4244) // conversion from 'type1' to 'type2', possible loss of data diff --git a/libs/spandsp/src/msvc/inttypes.h b/libs/spandsp/src/msvc/inttypes.h index beb93cae10..032ec3c36c 100644 --- a/libs/spandsp/src/msvc/inttypes.h +++ b/libs/spandsp/src/msvc/inttypes.h @@ -48,10 +48,10 @@ typedef __int64 int64_t; #endif #if !defined(INT16_MAX) -#define INT16_MAX 0x7FFF +#define INT16_MAX 0x7FFF #endif #if !defined(INT16_MIN) -#define INT16_MIN (-INT16_MAX - 1) +#define INT16_MIN (-INT16_MAX - 1) #endif #if !defined(INT32_MAX) diff --git a/libs/spandsp/src/msvc/spandsp.h b/libs/spandsp/src/msvc/spandsp.h index 6ba0b82cec..806c9ce920 100644 --- a/libs/spandsp/src/msvc/spandsp.h +++ b/libs/spandsp/src/msvc/spandsp.h @@ -98,9 +98,13 @@ #include #include #include +#include #include #include #include +#if defined(SPANDSP_SUPPORT_V34) +#include +#endif #include #include #include diff --git a/libs/spandsp/src/oki_adpcm.c b/libs/spandsp/src/oki_adpcm.c index f3fd6d9f95..f6d54b804c 100644 --- a/libs/spandsp/src/oki_adpcm.c +++ b/libs/spandsp/src/oki_adpcm.c @@ -159,7 +159,7 @@ static int16_t decode(oki_adpcm_state_t *s, uint8_t adpcm) * * x = adpcm & 0x07; * e = (step_size[s->step_index]*(x + x + 1)) >> 3; - * + * * Seems an obvious improvement on a modern machine, but remember * the truncation errors do not come out the same. It would * not, therefore, be an exact match for what this code is doing. @@ -251,7 +251,7 @@ SPAN_DECLARE(oki_adpcm_state_t *) oki_adpcm_init(oki_adpcm_state_t *s, int bit_r } memset(s, 0, sizeof(*s)); s->bit_rate = bit_rate; - + return s; } /*- End of function --------------------------------------------------------*/ @@ -281,7 +281,7 @@ SPAN_DECLARE(int) oki_adpcm_decode(oki_adpcm_state_t *s, int samples; float z; -#if (_MSC_VER >= 1400) +#if (_MSC_VER >= 1400) __analysis_assume(s->phase >= 0 && s->phase <= 4); #endif samples = 0; diff --git a/libs/spandsp/src/sig_tone.c b/libs/spandsp/src/sig_tone.c index ed6b2fa523..5e4e180178 100644 --- a/libs/spandsp/src/sig_tone.c +++ b/libs/spandsp/src/sig_tone.c @@ -117,11 +117,11 @@ static const sig_tone_flat_coeffs_t flat_coeffs[1] = { { #if defined(SPANDSP_USE_FIXED_POINT) - { 12900, -16384, -16384}, + { 12900, -16384, -16384}, { 0, -8578, -11796}, 15, #else - {0.393676f, -0.5f, -0.5f}, + {0.393676f, -0.5f, -0.5f}, {0.0f, -0.261778f, -0.359985f}, #endif } @@ -136,7 +136,7 @@ static const sig_tone_descriptor_t sig_tones[3] = ms_to_samples(400), /* High to low timout - 300ms to 550ms */ ms_to_samples(225), /* Sharp to flat timeout */ ms_to_samples(225), /* Notch insertion timeout */ - + ms_to_samples(3), /* Tone on persistence check */ ms_to_samples(8), /* Tone off persistence check */ @@ -158,7 +158,7 @@ static const sig_tone_descriptor_t sig_tones[3] = ms_to_samples(0), ms_to_samples(0), ms_to_samples(225), - + ms_to_samples(3), ms_to_samples(8), @@ -168,7 +168,7 @@ static const sig_tone_descriptor_t sig_tones[3] = NULL, }, NULL, - + 15.6f, -30.0f, -30.0f @@ -190,7 +190,7 @@ static const sig_tone_descriptor_t sig_tones[3] = ¬ch_coeffs[NOTCH_COEFF_SET_2600HZ] }, NULL, - + 15.6f, -30.0f, -30.0f @@ -299,7 +299,7 @@ SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode, int du { int old_tones; int new_tones; - + old_tones = s->current_tx_tone & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT); new_tones = mode & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT); if (new_tones && old_tones != new_tones) @@ -490,7 +490,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) #endif } flat_power = power_meter_update(&s->flat_power, bandpass_signal); - + /* For the flat receiver we use a simple power threshold! */ if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT))) { @@ -634,7 +634,7 @@ SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int #if !defined(SPANDSP_USE_FIXED_POINT) int j; #endif - + if (sig_update == NULL || tone_type < 1 || tone_type > 3) return NULL; /*endif*/ diff --git a/libs/spandsp/src/spandsp/complex.h b/libs/spandsp/src/spandsp/complex.h index af98c078d1..4958a5898f 100644 --- a/libs/spandsp/src/spandsp/complex.h +++ b/libs/spandsp/src/spandsp/complex.h @@ -381,7 +381,7 @@ static __inline__ complexf_t complex_divf(const complexf_t *x, const complexf_t { complexf_t z; float f; - + f = y->re*y->re + y->im*y->im; z.re = ( x->re*y->re + x->im*y->im)/f; z.im = (-x->re*y->im + x->im*y->re)/f; @@ -393,7 +393,7 @@ static __inline__ complex_t complex_div(const complex_t *x, const complex_t *y) { complex_t z; double f; - + f = y->re*y->re + y->im*y->im; z.re = ( x->re*y->re + x->im*y->im)/f; z.im = (-x->re*y->im + x->im*y->re)/f; @@ -406,7 +406,7 @@ static __inline__ complexl_t complex_divl(const complexl_t *x, const complexl_t { complexl_t z; long double f; - + f = y->re*y->re + y->im*y->im; z.re = ( x->re*y->re + x->im*y->im)/f; z.im = (-x->re*y->im + x->im*y->re)/f; diff --git a/libs/spandsp/src/spandsp/complex_vector_float.h b/libs/spandsp/src/spandsp/complex_vector_float.h index 4dc3569f7a..68e1302778 100644 --- a/libs/spandsp/src/spandsp/complex_vector_float.h +++ b/libs/spandsp/src/spandsp/complex_vector_float.h @@ -34,7 +34,7 @@ extern "C" static __inline__ void cvec_copyf(complexf_t z[], const complexf_t x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = x[i]; } @@ -43,7 +43,7 @@ static __inline__ void cvec_copyf(complexf_t z[], const complexf_t x[], int n) static __inline__ void cvec_copy(complex_t z[], const complex_t x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = x[i]; } @@ -53,7 +53,7 @@ static __inline__ void cvec_copy(complex_t z[], const complex_t x[], int n) static __inline__ void cvec_copyl(complexl_t z[], const complexl_t x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = x[i]; } @@ -63,7 +63,7 @@ static __inline__ void cvec_copyl(complexl_t z[], const complexl_t x[], int n) static __inline__ void cvec_zerof(complexf_t z[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = complex_setf(0.0f, 0.0f); } @@ -72,7 +72,7 @@ static __inline__ void cvec_zerof(complexf_t z[], int n) static __inline__ void cvec_zero(complex_t z[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = complex_set(0.0, 0.0); } @@ -82,7 +82,7 @@ static __inline__ void cvec_zero(complex_t z[], int n) static __inline__ void cvec_zerol(complexl_t z[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = complex_setl(0.0, 0.0); } @@ -92,7 +92,7 @@ static __inline__ void cvec_zerol(complexl_t z[], int n) static __inline__ void cvec_setf(complexf_t z[], complexf_t *x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = *x; } @@ -101,7 +101,7 @@ static __inline__ void cvec_setf(complexf_t z[], complexf_t *x, int n) static __inline__ void cvec_set(complex_t z[], complex_t *x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = *x; } @@ -111,7 +111,7 @@ static __inline__ void cvec_set(complex_t z[], complex_t *x, int n) static __inline__ void cvec_setl(complexl_t z[], complexl_t *x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = *x; } diff --git a/libs/spandsp/src/spandsp/complex_vector_int.h b/libs/spandsp/src/spandsp/complex_vector_int.h index 320457d57f..a77207a63f 100644 --- a/libs/spandsp/src/spandsp/complex_vector_int.h +++ b/libs/spandsp/src/spandsp/complex_vector_int.h @@ -70,7 +70,7 @@ static __inline__ void cvec_zeroi32(complexi32_t z[], int n) static __inline__ void cvec_seti(complexi_t z[], complexi_t *x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = *x; } @@ -79,7 +79,7 @@ static __inline__ void cvec_seti(complexi_t z[], complexi_t *x, int n) static __inline__ void cvec_seti16(complexi16_t z[], complexi16_t *x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = *x; } @@ -88,7 +88,7 @@ static __inline__ void cvec_seti16(complexi16_t z[], complexi16_t *x, int n) static __inline__ void cvec_seti32(complexi32_t z[], complexi32_t *x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = *x; } diff --git a/libs/spandsp/src/spandsp/dc_restore.h b/libs/spandsp/src/spandsp/dc_restore.h index 94ff6c7e70..5579e0c57a 100644 --- a/libs/spandsp/src/spandsp/dc_restore.h +++ b/libs/spandsp/src/spandsp/dc_restore.h @@ -35,7 +35,7 @@ Telecoms signals often contain considerable DC, but DC upsets a lot of signal processing functions. Placing a zero DC restorer at the front of the processing -chain can often simplify the downstream processing. +chain can often simplify the downstream processing. \section dc_restore_page_sec_2 How does it work? @@ -44,10 +44,10 @@ the DC bias in the signal. A 32 bit estimate is used for the 16 bit audio, so the noise introduced by the estimation can be keep in the lower bits, and the 16 bit DC value, which is subtracted from the signal, is fairly clean. The following code fragment shows the algorithm used. dc_bias is a 32 bit integer, -while the sample and the resulting clean_sample are 16 bit integers. +while the sample and the resulting clean_sample are 16 bit integers. dc_bias += ((((int32_t) sample << 15) - dc_bias) >> 14); - clean_sample = sample - (dc_bias >> 15); + clean_sample = sample - (dc_bias >> 15); */ /*! diff --git a/libs/spandsp/src/spandsp/dtmf.h b/libs/spandsp/src/spandsp/dtmf.h index 58ea779088..df9660feee 100644 --- a/libs/spandsp/src/spandsp/dtmf.h +++ b/libs/spandsp/src/spandsp/dtmf.h @@ -31,7 +31,7 @@ The DTMF receiver detects the standard DTMF digits. It is compliant with ITU-T Q.23, ITU-T Q.24, and the local DTMF specifications of most administrations. Its passes the test suites. It also scores *very* well on the standard -talk-off tests. +talk-off tests. The current design uses floating point extensively. It is not tolerant of DC. It is expected that a DC restore stage will be placed before the DTMF detector. @@ -66,7 +66,7 @@ TODO: \section dtmf_tx_page_sec_1 What does it do? The DTMF tone generation module provides for the generation of the -repertoire of 16 DTMF dual tones. +repertoire of 16 DTMF dual tones. \section dtmf_tx_page_sec_2 How does it work? */ @@ -96,7 +96,7 @@ extern "C" \param s The DTMF generator context. \param amp The buffer for the generated signal. \param max_samples The required number of generated samples. - \return The number of samples actually generated. This may be less than + \return The number of samples actually generated. This may be less than max_samples if the input buffer empties. */ SPAN_DECLARE(int) dtmf_tx(dtmf_tx_state_t *s, int16_t amp[], int max_samples); diff --git a/libs/spandsp/src/spandsp/echo.h b/libs/spandsp/src/spandsp/echo.h index ec8c53b023..14f856068f 100644 --- a/libs/spandsp/src/spandsp/echo.h +++ b/libs/spandsp/src/spandsp/echo.h @@ -2,8 +2,8 @@ * SpanDSP - a series of DSP components for telephony * * echo.h - An echo cancellor, suitable for electrical and acoustic - * cancellation. This code does not currently comply with - * any relevant standards (e.g. G.164/5/7/8). + * cancellation. This code does not currently comply with + * any relevant standards (e.g. G.164/5/7/8). * * Written by Steve Underwood * @@ -43,7 +43,7 @@ the duration of that impulse response. The signal transmitted to the telephone l is passed through the FIR filter. Once the FIR is properly adapted, the resulting output is an estimate of the echo signal received from the line. This is subtracted from the received signal. The result is an estimate of the signal which originated -at the far end of the line, free from echos of our own transmitted signal. +at the far end of the line, free from echos of our own transmitted signal. The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and was introduced in 1960. It is the commonest form of filter adaption used in things @@ -67,7 +67,7 @@ complexity filter is adequate for this, so pre-whitening adds little to the compute requirements of the echo canceller. An FIR filter adapted using pre-whitened NLMS performs well, provided certain -conditions are met: +conditions are met: - The transmitted signal has poor self-correlation. - There is no signal being generated within the environment being cancelled. @@ -95,7 +95,7 @@ adaption is only performed when we are transmitting a significant signal level, and the environment is not, things will be OK. Clearly, it is easy to tell when we are sending a significant signal. Telling, if the environment is generating a significant signal, and doing it with sufficient speed that the adaption will -not have diverged too much more we stop it, is a little harder. +not have diverged too much more we stop it, is a little harder. The key problem in detecting when the environment is sourcing significant energy is that we must do this very quickly. Given a reasonably long sample of the @@ -103,13 +103,13 @@ received signal, there are a number of strategies which may be used to assess whether that signal contains a strong far end component. However, by the time that assessment is complete the far end signal will have already caused major mis-convergence in the adaption process. An assessment algorithm is needed which -produces a fairly accurate result from a very short burst of far end energy. +produces a fairly accurate result from a very short burst of far end energy. \section echo_can_page_sec_3 How do I use it? The echo cancellor processes both the transmit and receive streams sample by sample. The processing function is not declared inline. Unfortunately, cancellation requires many operations per sample, so the call overhead is only a -minor burden. +minor burden. */ #include "fir.h" diff --git a/libs/spandsp/src/spandsp/fast_convert.h b/libs/spandsp/src/spandsp/fast_convert.h index 10679eab4d..e6da451f9c 100644 --- a/libs/spandsp/src/spandsp/fast_convert.h +++ b/libs/spandsp/src/spandsp/fast_convert.h @@ -273,16 +273,17 @@ extern "C" __inline float rintf(float flt) { - _asm - { fld flt - frndint - } + _asm + { + fld flt + frndint + } } __inline double rint(double dbl) { - _asm - { + _asm + { fld dbl frndint } @@ -318,12 +319,12 @@ extern "C" __inline long int lrint(double x) { - return (long int)_mm_cvtsd_si64x( _mm_loadu_pd ((const double*)&x) ); + return (long int)_mm_cvtsd_si64x( _mm_loadu_pd ((const double*)&x) ); } __inline long int lrintf(float x) { - return _mm_cvt_ss2si( _mm_load_ss((const float*)&x) ); + return _mm_cvt_ss2si( _mm_load_ss((const float*)&x) ); } __inline long int lfastrint(double x) diff --git a/libs/spandsp/src/spandsp/fir.h b/libs/spandsp/src/spandsp/fir.h index 52aab24db0..74b0bc2d3f 100644 --- a/libs/spandsp/src/spandsp/fir.h +++ b/libs/spandsp/src/spandsp/fir.h @@ -197,7 +197,7 @@ static __inline__ int16_t fir16(fir16_state_t *fir, int16_t sample) y += fir->coeffs[i]*fir->history[i + offset2]; #endif if (fir->curr_pos <= 0) - fir->curr_pos = fir->taps; + fir->curr_pos = fir->taps; fir->curr_pos--; return (int16_t) (y >> 15); } @@ -212,7 +212,7 @@ static __inline__ const int16_t *fir32_create(fir32_state_t *fir, fir->coeffs = coeffs; fir->history = (int16_t *) malloc(taps*sizeof(int16_t)); if (fir->history) - memset(fir->history, '\0', taps*sizeof(int16_t)); + memset(fir->history, '\0', taps*sizeof(int16_t)); return fir->history; } /*- End of function --------------------------------------------------------*/ @@ -245,7 +245,7 @@ static __inline__ int16_t fir32(fir32_state_t *fir, int16_t sample) for ( ; i >= 0; i--) y += fir->coeffs[i]*fir->history[i + offset2]; if (fir->curr_pos <= 0) - fir->curr_pos = fir->taps; + fir->curr_pos = fir->taps; fir->curr_pos--; return (int16_t) (y >> 15); } @@ -253,7 +253,7 @@ static __inline__ int16_t fir32(fir32_state_t *fir, int16_t sample) static __inline__ const float *fir_float_create(fir_float_state_t *fir, const float *coeffs, - int taps) + int taps) { fir->taps = taps; fir->curr_pos = taps - 1; @@ -264,7 +264,7 @@ static __inline__ const float *fir_float_create(fir_float_state_t *fir, return fir->history; } /*- End of function --------------------------------------------------------*/ - + static __inline__ void fir_float_free(fir_float_state_t *fir) { free(fir->history); @@ -288,7 +288,7 @@ static __inline__ int16_t fir_float(fir_float_state_t *fir, int16_t sample) for ( ; i >= 0; i--) y += fir->coeffs[i]*fir->history[i + offset2]; if (fir->curr_pos <= 0) - fir->curr_pos = fir->taps; + fir->curr_pos = fir->taps; fir->curr_pos--; return (int16_t) y; } diff --git a/libs/spandsp/src/spandsp/fsk.h b/libs/spandsp/src/spandsp/fsk.h index 9358b565cb..bcb8df1de7 100644 --- a/libs/spandsp/src/spandsp/fsk.h +++ b/libs/spandsp/src/spandsp/fsk.h @@ -29,7 +29,7 @@ \section fsk_page_sec_1 What does it do? Most of the oldest telephony modems use incoherent FSK modulation. This module can be used to implement both the transmit and receive sides of a number of these -modems. There are integrated definitions for: +modems. There are integrated definitions for: - V.21 - V.23 @@ -38,7 +38,7 @@ modems. There are integrated definitions for: - Weitbrecht (Used for TDD - Telecoms Device for the Deaf) The audio output or input is a stream of 16 bit samples, at 8000 samples/second. -The transmit and receive sides can be used independantly. +The transmit and receive sides can be used independantly. \section fsk_page_sec_2 The transmitter @@ -48,7 +48,7 @@ switched, producing a clean spectrum. The symbols are not generally an integer number of samples long. However, the symbol time for the fastest data rate generally used (1200bps) is more than 7 samples long. The jitter resulting from switching at the nearest sample is, therefore, acceptable. No interpolation is -used. +used. \section fsk_page_sec_3 The receiver @@ -60,7 +60,7 @@ one that matches the frequency being transmitted during the correlation interval. Because the transmission is totally asynchronous, the demodulation process must run sample by sample to find the symbol transitions. The correlation is performed on a sliding window basis, so the computational load of -demodulating sample by sample is not great. +demodulating sample by sample is not great. Two modes of symbol synchronisation are provided: @@ -159,7 +159,7 @@ SPAN_DECLARE(fsk_tx_state_t *) fsk_tx_init(fsk_tx_state_t *s, void *user_data); SPAN_DECLARE(int) fsk_tx_restart(fsk_tx_state_t *s, const fsk_spec_t *spec); - + SPAN_DECLARE(int) fsk_tx_release(fsk_tx_state_t *s); SPAN_DECLARE(int) fsk_tx_free(fsk_tx_state_t *s); diff --git a/libs/spandsp/src/spandsp/g168models.h b/libs/spandsp/src/spandsp/g168models.h index 4e71112eef..686925c369 100644 --- a/libs/spandsp/src/spandsp/g168models.h +++ b/libs/spandsp/src/spandsp/g168models.h @@ -2,7 +2,7 @@ * SpanDSP - a series of DSP components for telephony * * g168models.h - line models for echo cancellation tests against the G.168 - * spec. + * spec. * * Written by Steve Underwood * diff --git a/libs/spandsp/src/spandsp/hdlc.h b/libs/spandsp/src/spandsp/hdlc.h index ce37a701fc..cf5efe4330 100644 --- a/libs/spandsp/src/spandsp/hdlc.h +++ b/libs/spandsp/src/spandsp/hdlc.h @@ -40,10 +40,10 @@ HDLC may not be a DSP function, but is needed to accompany several DSP component #if !defined(_SPANDSP_HDLC_H_) #define _SPANDSP_HDLC_H_ -/*! +/*! HDLC_MAXFRAME_LEN is the maximum length of a stuffed HDLC frame, excluding the CRC. */ -#define HDLC_MAXFRAME_LEN 400 +#define HDLC_MAXFRAME_LEN 400 typedef void (*hdlc_frame_handler_t)(void *user_data, const uint8_t *pkt, int len, int ok); typedef void (*hdlc_underflow_handler_t)(void *user_data); diff --git a/libs/spandsp/src/spandsp/noise.h b/libs/spandsp/src/spandsp/noise.h index 9014e482ef..ef867e3f02 100644 --- a/libs/spandsp/src/spandsp/noise.h +++ b/libs/spandsp/src/spandsp/noise.h @@ -37,7 +37,7 @@ AWGN. It is designed to be of sufficiently low complexity to generate large volumes of reasonable quality noise, in real time. Hoth noise is used to model indoor ambient noise when evaluating communications -systems such as telephones. It is named after D.F. Hoth, who made the first +systems such as telephones. It is named after D.F. Hoth, who made the first systematic study of this. The official definition of Hoth noise is IEEE standard 269-2001 (revised from 269-1992), "Draft Standard Methods for Measuring Transmission Performance of Analog and Digital Telephone Sets, Handsets and Headsets." diff --git a/libs/spandsp/src/spandsp/oki_adpcm.h b/libs/spandsp/src/spandsp/oki_adpcm.h index c3707f07f8..4b99a93358 100644 --- a/libs/spandsp/src/spandsp/oki_adpcm.h +++ b/libs/spandsp/src/spandsp/oki_adpcm.h @@ -2,7 +2,7 @@ * SpanDSP - a series of DSP components for telephony * * oki_adpcm.h - Conversion routines between linear 16 bit PCM data and - * OKI (Dialogic) ADPCM format. + * OKI (Dialogic) ADPCM format. * * Written by Steve Underwood * diff --git a/libs/spandsp/src/spandsp/playout.h b/libs/spandsp/src/spandsp/playout.h index 41d4a0cb46..582fcb2c51 100644 --- a/libs/spandsp/src/spandsp/playout.h +++ b/libs/spandsp/src/spandsp/playout.h @@ -51,7 +51,7 @@ enum /* Frame types */ #define PLAYOUT_TYPE_CONTROL 0 -#define PLAYOUT_TYPE_SILENCE 1 +#define PLAYOUT_TYPE_SILENCE 1 #define PLAYOUT_TYPE_SPEECH 2 typedef int timestamp_t; diff --git a/libs/spandsp/src/spandsp/private/dtmf.h b/libs/spandsp/src/spandsp/private/dtmf.h index eae20ad4d5..c773ee61ee 100644 --- a/libs/spandsp/src/spandsp/private/dtmf.h +++ b/libs/spandsp/src/spandsp/private/dtmf.h @@ -1,7 +1,7 @@ /* * SpanDSP - a series of DSP components for telephony * - * private/dtmf.h - DTMF tone generation and detection + * private/dtmf.h - DTMF tone generation and detection * * Written by Steve Underwood * diff --git a/libs/spandsp/src/spandsp/private/echo.h b/libs/spandsp/src/spandsp/private/echo.h index 98153ef0f8..f280284232 100644 --- a/libs/spandsp/src/spandsp/private/echo.h +++ b/libs/spandsp/src/spandsp/private/echo.h @@ -2,8 +2,8 @@ * SpanDSP - a series of DSP components for telephony * * private/echo.h - An echo cancellor, suitable for electrical and acoustic - * cancellation. This code does not currently comply with - * any relevant standards (e.g. G.164/5/7/8). + * cancellation. This code does not currently comply with + * any relevant standards (e.g. G.164/5/7/8). * * Written by Steve Underwood * @@ -44,11 +44,11 @@ struct echo_can_state_s int nonupdate_dwell; int curr_pos; - + int taps; int tap_mask; int adaption_mode; - + int32_t supp_test1; int32_t supp_test2; int32_t supp1; @@ -78,14 +78,14 @@ struct echo_can_state_s /* DC and near DC blocking filter states */ int32_t tx_hpf[2]; int32_t rx_hpf[2]; - + /* Parameters for the optional Hoth noise generator */ int cng_level; int cng_rndnum; int cng_filter; - + /* Snapshot sample of coeffs used for development */ - int16_t *snapshot; + int16_t *snapshot; }; #endif diff --git a/libs/spandsp/src/spandsp/private/hdlc.h b/libs/spandsp/src/spandsp/private/hdlc.h index b5a677887d..de87394daf 100644 --- a/libs/spandsp/src/spandsp/private/hdlc.h +++ b/libs/spandsp/src/spandsp/private/hdlc.h @@ -129,7 +129,7 @@ struct hdlc_tx_state_s int byte; /*! \brief The number of bits remaining in byte. */ int bits; - + /*! \brief TRUE if transmission should end on buffer underflow .*/ int tx_end; }; diff --git a/libs/spandsp/src/spandsp/private/oki_adpcm.h b/libs/spandsp/src/spandsp/private/oki_adpcm.h index f039213c43..9970b5837c 100644 --- a/libs/spandsp/src/spandsp/private/oki_adpcm.h +++ b/libs/spandsp/src/spandsp/private/oki_adpcm.h @@ -2,7 +2,7 @@ * SpanDSP - a series of DSP components for telephony * * private/oki_adpcm.h - Conversion routines between linear 16 bit PCM data - * and OKI (Dialogic) ADPCM format. + * and OKI (Dialogic) ADPCM format. * * Written by Steve Underwood * diff --git a/libs/spandsp/src/spandsp/private/t31.h b/libs/spandsp/src/spandsp/private/t31.h index 740ec28073..2686b5f503 100644 --- a/libs/spandsp/src/spandsp/private/t31.h +++ b/libs/spandsp/src/spandsp/private/t31.h @@ -212,7 +212,7 @@ struct t31_state_s /*! TRUE if DLE prefix just used */ int dled; - /*! \brief Samples of silence awaited, as specified in a "wait for silence" command */ + /*! \brief Samples of silence awaited, as specified in a "wait for silence" command */ int silence_awaited; /*! \brief The current bit rate for the FAX fast message transfer modem. */ diff --git a/libs/spandsp/src/spandsp/private/t85.h b/libs/spandsp/src/spandsp/private/t85.h index c3e62e8c83..586a5cc22f 100644 --- a/libs/spandsp/src/spandsp/private/t85.h +++ b/libs/spandsp/src/spandsp/private/t85.h @@ -136,7 +136,7 @@ struct t85_decode_state_s /*! The number of bit planes expected, according to the header. Always 1 for true T.85 */ uint8_t bit_planes; uint8_t current_bit_plane; - + /*! The width of the full image, in pixels */ uint32_t xd; /*! The height of the full image, in pixels */ diff --git a/libs/spandsp/src/spandsp/super_tone_rx.h b/libs/spandsp/src/spandsp/super_tone_rx.h index c819a4442d..4ea640c685 100644 --- a/libs/spandsp/src/spandsp/super_tone_rx.h +++ b/libs/spandsp/src/spandsp/super_tone_rx.h @@ -43,7 +43,7 @@ If tones are close in frequency a single Goertzel set to the centre of the frequency range will be used. This optimises the efficiency of the detector. The Goertzel filters are applied without applying any special window functional (i.e. they use a rectangular window), so they have a sinc like response. -However, for most tone patterns their rejection qualities are adequate. +However, for most tone patterns their rejection qualities are adequate. The detector aims to meet the need of the standard call progress tones, to ITU-T E.180/Q.35 (busy, dial, ringback, reorder). Also, the extended tones, diff --git a/libs/spandsp/src/spandsp/super_tone_tx.h b/libs/spandsp/src/spandsp/super_tone_tx.h index 9f7ed6d6a1..55b8d670f0 100644 --- a/libs/spandsp/src/spandsp/super_tone_tx.h +++ b/libs/spandsp/src/spandsp/super_tone_tx.h @@ -33,7 +33,7 @@ The supervisory tone generator may be configured to generate most of the world's telephone supervisory tones - things like ringback, busy, number unobtainable, and so on. It uses tree structure tone descriptions, which can deal with quite -complex cadence patterns. +complex cadence patterns. \section super_tone_tx_page_sec_2 How does it work? diff --git a/libs/spandsp/src/spandsp/t38_terminal.h b/libs/spandsp/src/spandsp/t38_terminal.h index a847d96cf3..dbf0dca9cb 100644 --- a/libs/spandsp/src/spandsp/t38_terminal.h +++ b/libs/spandsp/src/spandsp/t38_terminal.h @@ -45,7 +45,7 @@ enum /*! This option enables the regular repeat transmission of indicator signals, during periods when no FAX signal transmission occurs. */ T38_TERMINAL_OPTION_REGULAR_INDICATORS = 0x02, - /*! This option enables the regular repeat transmission of indicator signals for the + /*! This option enables the regular repeat transmission of indicator signals for the first 2s, during periods when no FAX signal transmission occurs. */ T38_TERMINAL_OPTION_2S_REPEATING_INDICATORS = 0x04, /*! This option suppresses the transmission of indicators. This is usually used with diff --git a/libs/spandsp/src/spandsp/t42.h b/libs/spandsp/src/spandsp/t42.h index 3e9540e966..fe2c83aeab 100644 --- a/libs/spandsp/src/spandsp/t42.h +++ b/libs/spandsp/src/spandsp/t42.h @@ -51,13 +51,13 @@ extern "C" SPAN_DECLARE(void) srgb_to_lab(lab_params_t *s, uint8_t lab[], const uint8_t srgb[], int pixels); SPAN_DECLARE(void) lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t lab[], int pixels); - + SPAN_DECLARE(void) set_lab_illuminant(lab_params_t *s, float new_xn, float new_yn, float new_zn); SPAN_DECLARE(void) set_lab_gamut(lab_params_t *s, int L_min, int L_max, int a_min, int a_max, int b_min, int b_max, int ab_are_signed); SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, int a_Q, int b_P, int b_Q); - + SPAN_DECLARE(int) t42_itulab_to_itulab(logging_state_t *logging, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height); SPAN_DECLARE(int) t42_itulab_to_jpeg(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen); diff --git a/libs/spandsp/src/spandsp/t4_rx.h b/libs/spandsp/src/spandsp/t4_rx.h index f2ff4fa0ee..3b359c7d79 100644 --- a/libs/spandsp/src/spandsp/t4_rx.h +++ b/libs/spandsp/src/spandsp/t4_rx.h @@ -261,7 +261,7 @@ typedef struct /*! \brief The size of the image on the line, in bytes */ int line_image_size; } t4_stats_t; - + #if defined(__cplusplus) extern "C" { #endif @@ -369,19 +369,19 @@ SPAN_DECLARE(void) t4_rx_set_vendor(t4_rx_state_t *s, const char *vendor); \param model The model string, or NULL. */ SPAN_DECLARE(void) t4_rx_set_model(t4_rx_state_t *s, const char *model); -/*! Get the current image transfer statistics. +/*! Get the current image transfer statistics. \brief Get the current transfer statistics. \param s The T.4 context. \param t A pointer to a statistics structure. */ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t); -/*! Get the short text name of an encoding format. +/*! Get the short text name of an encoding format. \brief Get the short text name of an encoding format. \param encoding The encoding type. \return A pointer to the string. */ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding); -/*! Get the short text name of an image format. +/*! Get the short text name of an image format. \brief Get the short text name of an image format. \param encoding The image format. \return A pointer to the string. */ diff --git a/libs/spandsp/src/spandsp/t4_t6_encode.h b/libs/spandsp/src/spandsp/t4_t6_encode.h index 27ab9aa68e..7431d64f08 100644 --- a/libs/spandsp/src/spandsp/t4_t6_encode.h +++ b/libs/spandsp/src/spandsp/t4_t6_encode.h @@ -42,7 +42,7 @@ extern "C" { SPAN_DECLARE(int) t4_t6_encode_image_complete(t4_t6_encode_state_t *s); /*! \brief Get the next bit of the current image. The image will - be padded for the current minimum scan line time. + be padded for the current minimum scan line time. \param s The T.4/T.6 context. \return The next bit (i.e. 0 or 1). SIG_STATUS_END_OF_DATA for no more data. */ SPAN_DECLARE(int) t4_t6_encode_get_bit(t4_t6_encode_state_t *s); @@ -52,7 +52,7 @@ SPAN_DECLARE(int) t4_t6_encode_get_bit(t4_t6_encode_state_t *s); \param s The T.4/T.6 context. \param buf The buffer into which the chunk is to written. \param max_len The maximum length of the chunk. - \return The actual length of the chunk. If this is less than max_len it + \return The actual length of the chunk. If this is less than max_len it indicates that the end of the document has been reached. */ SPAN_DECLARE(int) t4_t6_encode_get(t4_t6_encode_state_t *s, uint8_t buf[], int max_len); diff --git a/libs/spandsp/src/spandsp/t4_tx.h b/libs/spandsp/src/spandsp/t4_tx.h index 3e04237fe0..8ee19be591 100644 --- a/libs/spandsp/src/spandsp/t4_tx.h +++ b/libs/spandsp/src/spandsp/t4_tx.h @@ -277,7 +277,7 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s); \param s The T.4 context. \param buf The buffer into which the chunk is to written. \param max_len The maximum length of the chunk. - \return The actual length of the chunk. If this is less than max_len it + \return The actual length of the chunk. If this is less than max_len it indicates that the end of the document has been reached. */ SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len); @@ -383,7 +383,7 @@ SPAN_DECLARE(int) t4_tx_get_pages_in_file(t4_tx_state_t *s); \return The page number, or -1 if there is an error. */ SPAN_DECLARE(int) t4_tx_get_current_page_in_file(t4_tx_state_t *s); -/*! Get the current image transfer statistics. +/*! Get the current image transfer statistics. \brief Get the current transfer statistics. \param s The T.4 context. \param t A pointer to a statistics structure. */ diff --git a/libs/spandsp/src/spandsp/t81_t82_arith_coding.h b/libs/spandsp/src/spandsp/t81_t82_arith_coding.h index 905e0491be..e5b4ec4567 100644 --- a/libs/spandsp/src/spandsp/t81_t82_arith_coding.h +++ b/libs/spandsp/src/spandsp/t81_t82_arith_coding.h @@ -63,7 +63,6 @@ SPAN_DECLARE(void) t81_t82_arith_encode(t81_t82_arith_encode_state_t *s, int cx, SPAN_DECLARE(void) t81_t82_arith_encode_flush(t81_t82_arith_encode_state_t *s); - SPAN_DECLARE(t81_t82_arith_decode_state_t *) t81_t82_arith_decode_init(t81_t82_arith_decode_state_t *s); SPAN_DECLARE(int) t81_t82_arith_decode_restart(t81_t82_arith_decode_state_t *s, int reuse_st); diff --git a/libs/spandsp/src/spandsp/t85.h b/libs/spandsp/src/spandsp/t85.h index 07dd88931f..29bd6ad7c1 100644 --- a/libs/spandsp/src/spandsp/t85.h +++ b/libs/spandsp/src/spandsp/t85.h @@ -74,7 +74,7 @@ SPAN_DECLARE(int) t85_encode_image_complete(t85_encode_state_t *s); \param s The T.85 context. \param buf The buffer into which the chunk is to written. \param max_len The maximum length of the chunk. - \return The actual length of the chunk. If this is less than max_len it + \return The actual length of the chunk. If this is less than max_len it indicates that the end of the document has been reached. */ SPAN_DECLARE(int) t85_encode_get(t85_encode_state_t *s, uint8_t buf[], size_t max_len); @@ -113,7 +113,7 @@ SPAN_DECLARE(t85_encode_state_t *) t85_encode_init(t85_encode_state_t *s, SPAN_DECLARE(int) t85_encode_restart(t85_encode_state_t *s, uint32_t image_width, uint32_t image_length); - + SPAN_DECLARE(int) t85_encode_release(t85_encode_state_t *s); SPAN_DECLARE(int) t85_encode_free(t85_encode_state_t *s); diff --git a/libs/spandsp/src/spandsp/tone_detect.h b/libs/spandsp/src/spandsp/tone_detect.h index bf779ca41e..df75f230d6 100644 --- a/libs/spandsp/src/spandsp/tone_detect.h +++ b/libs/spandsp/src/spandsp/tone_detect.h @@ -191,7 +191,7 @@ static __inline__ void goertzel_samplex(goertzel_state_t *s, float amp) */ SPAN_DECLARE(int) periodogram_generate_coeffs(complexf_t coeffs[], float freq, int sample_rate, int window_len); -/*! Generate the phase offset to be expected between successive periodograms evaluated at the +/*! Generate the phase offset to be expected between successive periodograms evaluated at the specified interval. \param offset A point to the generated phase offset. \param freq The frequency being matched by the periodogram, in Hz. diff --git a/libs/spandsp/src/spandsp/v8.h b/libs/spandsp/src/spandsp/v8.h index fa9df4a0c5..0c1924c1e8 100644 --- a/libs/spandsp/src/spandsp/v8.h +++ b/libs/spandsp/src/spandsp/v8.h @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ /*! \page v8_page The V.8 modem negotiation protocol diff --git a/libs/spandsp/src/spandsp/vector_int.h b/libs/spandsp/src/spandsp/vector_int.h index c20f02a7d9..daec30670e 100644 --- a/libs/spandsp/src/spandsp/vector_int.h +++ b/libs/spandsp/src/spandsp/vector_int.h @@ -70,7 +70,7 @@ static __inline__ void vec_zeroi32(int32_t z[], int n) static __inline__ void vec_seti(int z[], int x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = x; } @@ -79,7 +79,7 @@ static __inline__ void vec_seti(int z[], int x, int n) static __inline__ void vec_seti16(int16_t z[], int16_t x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = x; } @@ -88,7 +88,7 @@ static __inline__ void vec_seti16(int16_t z[], int16_t x, int n) static __inline__ void vec_seti32(int32_t z[], int32_t x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = x; } @@ -117,7 +117,7 @@ SPAN_DECLARE(void) vec_circular_lmsi16(const int16_t x[], int16_t y[], int n, in /*! \brief Find the minimum and maximum values in an int16_t vector. \param x The vector to be searched. \param n The number of elements in the vector. - \param out A two element vector. The first will receive the + \param out A two element vector. The first will receive the maximum. The second will receive the minimum. This parameter may be set to NULL. \return The absolute maximum value. Since the range of negative numbers diff --git a/libs/spandsp/src/super_tone_tx.c b/libs/spandsp/src/super_tone_tx.c index b43f20628e..3809bb4bf8 100644 --- a/libs/spandsp/src/super_tone_tx.c +++ b/libs/spandsp/src/super_tone_tx.c @@ -59,7 +59,7 @@ oddity amongst supervisory tones. It is designed to sound loud and nasty. Most tones are one or two pure sine pitches, or one AM moduluated pitch. This alert tone varies between countries, but AT&T are a typical example. - + AT&T Receiver Off-Hook Tone is 1400 Hz, 2060 Hz, 2450 Hz and 2600 Hz at 0dBm0/frequency on and off every .1 second. On some older space division switching systems Receiver Off-Hook was 1400 Hz, 2060 Hz, 2450 Hz and 2600 Hz at +5 VU on and @@ -82,7 +82,7 @@ SPAN_DECLARE(super_tone_tx_step_t *) super_tone_tx_make_step(super_tone_tx_step_ return NULL; } if (f1 >= 1.0f) - { + { s->tone[0].phase_rate = dds_phase_ratef(f1); s->tone[0].gain = dds_scaling_dbm0f(l1); } @@ -278,7 +278,6 @@ SPAN_DECLARE(int) super_tone_tx(super_tone_tx_state_t *s, int16_t amp[], int max tree = s->levels[--s->level]; } } - } return samples; } diff --git a/libs/spandsp/src/swept_tone.c b/libs/spandsp/src/swept_tone.c index f2b5eb7e24..f5ccc9bed8 100644 --- a/libs/spandsp/src/swept_tone.c +++ b/libs/spandsp/src/swept_tone.c @@ -80,7 +80,7 @@ SPAN_DECLARE(int) swept_tone(swept_tone_state_t *s, int16_t amp[], int max_len) int i; int len; int chunk_len; - + for (len = 0; len < max_len; ) { chunk_len = max_len - len; diff --git a/libs/spandsp/src/t35.c b/libs/spandsp/src/t35.c index 4186504a4c..3e210854ab 100644 --- a/libs/spandsp/src/t35.c +++ b/libs/spandsp/src/t35.c @@ -300,7 +300,7 @@ static const nsf_data_t vendor_00[] = {"\x00\x41", 2, "Swasaki Communication", FALSE, NULL}, {"\x00\x45", 2, "Muratec", FALSE, Muratec45}, {"\x00\x46", 2, "Pheonix", FALSE, NULL}, - {"\x00\x48", 2, "Muratec", FALSE, Muratec48}, /* Not registered */ + {"\x00\x48", 2, "Muratec", FALSE, Muratec48}, /* Not registered */ {"\x00\x49", 2, "Japan Electric", FALSE, NULL}, {"\x00\x4D", 2, "Okura Electric", FALSE, NULL}, {"\x00\x51", 2, "Sanyo", FALSE, Sanyo}, @@ -502,7 +502,7 @@ static const nsf_data_t vendor_b5[] = {"\x00\x6E", 2, "Microsoft", FALSE, NULL}, {"\x00\x72", 2, "Speaking Devices", FALSE, NULL}, {"\x00\x74", 2, "Compaq", FALSE, NULL}, - {"\x00\x76", 2, "Microsoft", FALSE, NULL}, /* uses LSB for country but MSB for manufacturer */ + {"\x00\x76", 2, "Microsoft", FALSE, NULL}, /* uses LSB for country but MSB for manufacturer */ {"\x00\x78", 2, "Cylink", FALSE, NULL}, {"\x00\x7A", 2, "Pitney Bowes", FALSE, NULL}, {"\x00\x7C", 2, "Digiboard", FALSE, NULL}, diff --git a/libs/spandsp/src/t42.c b/libs/spandsp/src/t42.c index 0163ff52f5..c8ed0a0804 100644 --- a/libs/spandsp/src/t42.c +++ b/libs/spandsp/src/t42.c @@ -422,7 +422,7 @@ SPAN_DECLARE(void) srgb_to_lab(lab_params_t *s, uint8_t lab[], const uint8_t srg x /= s->x_n; y /= s->y_n; z /= s->z_n; - + /* XYZ to Lab */ xx = (x <= 0.008856f) ? (7.787f*x + 0.1379f) : cbrtf(x); yy = (y <= 0.008856f) ? (7.787f*y + 0.1379f) : cbrtf(y); @@ -456,7 +456,7 @@ SPAN_DECLARE(void) lab_to_srgb(lab_params_t *s, uint8_t srgb[], const uint8_t la itu_to_lab(s, &l, lab); /* Lab to XYZ */ - ll = (1.0f/116.0f)*(l.L + 16.0f); + ll = (1.0f/116.0f)*(l.L + 16.0f); y = ll; y = (y <= 0.2068f) ? (0.1284f*(y - 0.1379f)) : y*y*y; x = ll + (1.0f/500.0f)*l.a; @@ -668,7 +668,7 @@ SPAN_DECLARE(int) t42_itulab_to_jpeg(logging_state_t *logging, lab_params_t *s, free(*dst); fclose(out); return FALSE; - } + } fclose(out); #endif @@ -1054,7 +1054,7 @@ SPAN_DECLARE(int) t42_itulab_to_itulab(logging_state_t *logging, tdata_t *dst, t free(*dst); fclose(out); return FALSE; - } + } fclose(out); #endif @@ -1105,6 +1105,7 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, span_log(logging, SPAN_LOG_FLOW, "%s\n", escape.error_message); else span_log(logging, SPAN_LOG_FLOW, "Unspecified libjpeg error.\n"); +printf("Error %s.\n", escape.error_message); if (scan_line_out) free(scan_line_out); fclose(in); @@ -1134,14 +1135,17 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, if (!is_itu_fax(logging, s, decompressor.marker_list)) { span_log(logging, SPAN_LOG_FLOW, "Is not an ITU FAX.\n"); - return FALSE; +printf("Is not an ITU FAX 1.\n"); + //return FALSE; } /* Copy size, resolution, etc */ *width = decompressor.image_width; *height = decompressor.image_height; +printf("Is %d x %d\n", decompressor.image_width, decompressor.image_height); jpeg_start_decompress(&decompressor); +printf("Is %d x %d x %d.\n", decompressor.output_width, decompressor.output_height, decompressor.num_components); if ((scan_line_in = (JSAMPROW) malloc(decompressor.output_width*decompressor.num_components)) == NULL) return FALSE; @@ -1151,6 +1155,7 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, jpeg_read_scanlines(&decompressor, &scan_line_in, 1); lab_to_srgb(s, scan_line_out, scan_line_in, decompressor.output_width); } +printf("Next %d\n", decompressor.output_scanline); free(scan_line_in); jpeg_finish_decompress(&decompressor); @@ -1159,6 +1164,7 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, *dstlen = pos; +printf("Next2 %d\n", decompressor.output_scanline); return TRUE; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/t4_t6_decode.c b/libs/spandsp/src/t4_t6_decode.c index d91992a04e..03b24ae4f3 100644 --- a/libs/spandsp/src/t4_t6_decode.c +++ b/libs/spandsp/src/t4_t6_decode.c @@ -31,23 +31,23 @@ * Copyright (c) 1990-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * * Decoder support is derived from code in Frank Cringle's viewfax program; @@ -541,8 +541,8 @@ static int put_bits(t4_t6_decode_state_t *s, uint32_t bit_string, int quantity) /* TODO: we really should record that something wasn't right at this point. */ s->a0 = old_a0; break; - } - } + } + } s->run_length += (s->a0 - old_a0); add_run_to_row(s); /* We need to move one step in one direction or the other, to change to the diff --git a/libs/spandsp/src/t4_t6_encode.c b/libs/spandsp/src/t4_t6_encode.c index c33b65ae24..22885f4ac1 100644 --- a/libs/spandsp/src/t4_t6_encode.c +++ b/libs/spandsp/src/t4_t6_encode.c @@ -31,23 +31,23 @@ * Copyright (c) 1990-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -508,7 +508,7 @@ static int row_to_run_lengths(uint32_t list[], const uint8_t row[], int width) x <<= frag; flip ^= 0xFF000000; rem -= frag; - } + } /* Save the remainder of the word */ span = (i << 3) + 8 - rem; } @@ -647,7 +647,7 @@ static void encode_2d_row(t4_t6_encode_state_t *s, const uint8_t *row_buf) uint32_t *p; /* - b1 b2 + b1 b2 XX XX XX XX XX -- -- -- -- -- XX XX XX -- -- -- -- -- XX XX XX -- -- -- -- -- XX XX XX XX XX XX -- -- -- -- a0 a1 a2 @@ -657,18 +657,18 @@ static void encode_2d_row(t4_t6_encode_state_t *s, const uint8_t *row_buf) This mode is identified when the position of b2 lies to the left of a1. When this mode has been coded, a0 is set on the element of the coding line below b2 in preparation for the next coding (i.e. on a0'). - - b1 b2 + + b1 b2 XX XX XX XX -- -- XX XX XX -- -- -- -- -- - XX XX -- -- -- -- -- -- -- -- -- -- XX XX + XX XX -- -- -- -- -- -- -- -- -- -- XX XX a0 a0' a1 Pass mode - + However, the state where b2 occurs just above a1, as shown in the figure below, is not considered as a pass mode. - b1 b2 + b1 b2 XX XX XX XX -- -- XX XX XX -- -- -- -- -- XX XX -- -- -- -- -- -- -- XX XX XX XX XX a0 a1 @@ -693,7 +693,7 @@ static void encode_2d_row(t4_t6_encode_state_t *s, const uint8_t *row_buf) Vertical - b1 b2 + b1 b2 -- XX XX XX XX XX -- -- -- -- -- -- -- -- XX XX XX XX -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- XX XX XX XX XX XX XX -- -- a0 a1 a2 diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 840b27a2f2..5a964f6f7f 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -133,7 +133,7 @@ static void TIFFFXDefaultDirectory(TIFF *tif) /* Since we may have overriddden another directory method, we call it now to allow it to set up the rest of its own methods. */ - if (_ParentExtender) + if (_ParentExtender) (*_ParentExtender)(tif); } /*- End of function --------------------------------------------------------*/ @@ -141,11 +141,11 @@ static void TIFFFXDefaultDirectory(TIFF *tif) SPAN_DECLARE(void) TIFF_FX_init(void) { static int first_time = TRUE; - + if (!first_time) return; first_time = FALSE; - + /* Grab the inherited method and install */ _ParentExtender = TIFFSetTagExtender(TIFFFXDefaultDirectory); } @@ -175,7 +175,7 @@ static int read_colour_map(t4_tx_state_t *s, int bits_per_sample) map_z = NULL; if (!TIFFGetField(s->tiff.tiff_file, TIFFTAG_COLORMAP, &map_L, &map_a, &map_b, &map_z)) return -1; - + /* TODO: This only allows for 8 bit deep maps */ if ((s->colour_map = realloc(s->colour_map, 3*256)) == NULL) return -1; diff --git a/libs/spandsp/src/testcpuid.c b/libs/spandsp/src/testcpuid.c index 92fdd68176..8453067e9e 100644 --- a/libs/spandsp/src/testcpuid.c +++ b/libs/spandsp/src/testcpuid.c @@ -75,7 +75,6 @@ static __inline__ int flag_is_changeable_p(uint32_t flag) " popfl\n" : "=&r" (f1), "=&r" (f2) : "ir" (flag)); - return ((f1^f2) & flag) != 0; } /*- End of function --------------------------------------------------------*/ @@ -96,21 +95,21 @@ int has_MMX(void) /*endif*/ __asm__ __volatile__( " push %%ebx;\n" - " mov $1,%%eax;\n" - " cpuid;\n" - " xor %%eax,%%eax;\n" - " test $0x800000,%%edx;\n" - " jz 1f;\n" /* no MMX support */ - " inc %%eax;\n" /* MMX support */ + " mov $1,%%eax;\n" + " cpuid;\n" + " xor %%eax,%%eax;\n" + " test $0x800000,%%edx;\n" + " jz 1f;\n" /* no MMX support */ + " inc %%eax;\n" /* MMX support */ "1:\n" " pop %%ebx;\n" - : "=a" (result) - : + : "=a" (result) + : : "ecx", "edx"); return result; } /*- End of function --------------------------------------------------------*/ - + int has_SIMD(void) { int result; @@ -120,16 +119,16 @@ int has_SIMD(void) /*endif*/ __asm__ __volatile__( " push %%ebx;\n" - " mov $1,%%eax;\n" - " cpuid;\n" - " xor %%eax,%%eax;\n" - " test $0x02000000,%%edx;\n" - " jz 1f;\n" /* no SIMD support */ - " inc %%eax;\n" /* SIMD support */ + " mov $1,%%eax;\n" + " cpuid;\n" + " xor %%eax,%%eax;\n" + " test $0x02000000,%%edx;\n" + " jz 1f;\n" /* no SIMD support */ + " inc %%eax;\n" /* SIMD support */ "1:\n" " pop %%ebx;\n" - : "=a" (result) - : + : "=a" (result) + : : "ecx", "edx"); return result; } @@ -144,21 +143,21 @@ int has_SIMD2(void) /*endif*/ __asm__ __volatile__( " push %%ebx;\n" - " mov $1,%%eax;\n" - " cpuid;\n" - " xor %%eax,%%eax;\n" - " test $0x04000000,%%edx;\n" - " jz 1f;\n" /* no SIMD2 support */ - " inc %%eax;\n" /* SIMD2 support */ + " mov $1,%%eax;\n" + " cpuid;\n" + " xor %%eax,%%eax;\n" + " test $0x04000000,%%edx;\n" + " jz 1f;\n" /* no SIMD2 support */ + " inc %%eax;\n" /* SIMD2 support */ "1:\n" " pop %%ebx;\n" - : "=a" (result) - : + : "=a" (result) + : : "ecx", "edx"); return result; } /*- End of function --------------------------------------------------------*/ - + int has_3DNow(void) { int result; @@ -168,21 +167,21 @@ int has_3DNow(void) /*endif*/ __asm__ __volatile__( " push %%ebx;\n" - " mov $0x80000000,%%eax;\n" - " cpuid;\n" + " mov $0x80000000,%%eax;\n" + " cpuid;\n" " xor %%ecx,%%ecx;\n" - " cmp $0x80000000,%%eax;\n" - " jbe 1f;\n" /* no extended MSR(1), so no 3DNow! */ - " mov $0x80000001,%%eax;\n" - " cpuid;\n" + " cmp $0x80000000,%%eax;\n" + " jbe 1f;\n" /* no extended MSR(1), so no 3DNow! */ + " mov $0x80000001,%%eax;\n" + " cpuid;\n" " xor %%ecx,%%ecx;\n" - " test $0x80000000,%%edx;\n" - " jz 1f;\n" /* no 3DNow! support */ - " inc %%ecx;\n" /* 3DNow! support */ + " test $0x80000000,%%edx;\n" + " jz 1f;\n" /* no 3DNow! support */ + " inc %%ecx;\n" /* 3DNow! support */ "1:\n" " pop %%ebx;\n" - : "=c" (result) - : + : "=c" (result) + : : "eax", "edx"); return result; } diff --git a/libs/spandsp/src/time_scale.c b/libs/spandsp/src/time_scale.c index 605e1c5fb5..5b2a64a66b 100644 --- a/libs/spandsp/src/time_scale.c +++ b/libs/spandsp/src/time_scale.c @@ -86,7 +86,7 @@ static __inline__ void overlap_add(int16_t amp1[], int16_t amp2[], int len) int i; float weight; float step; - + step = 1.0f/len; weight = 0.0f; for (i = 0; i < len; i++) diff --git a/libs/spandsp/src/tone_detect.c b/libs/spandsp/src/tone_detect.c index 2887af51d6..4dfea5d5bf 100644 --- a/libs/spandsp/src/tone_detect.c +++ b/libs/spandsp/src/tone_detect.c @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ #if defined(HAVE_CONFIG_H) diff --git a/libs/spandsp/src/v27ter_tx.c b/libs/spandsp/src/v27ter_tx.c index 6b0706aaf3..a877915271 100644 --- a/libs/spandsp/src/v27ter_tx.c +++ b/libs/spandsp/src/v27ter_tx.c @@ -171,7 +171,7 @@ static complexf_t getbaud(v27ter_tx_state_t *s) if (s->in_training) { - /* Send the training sequence */ + /* Send the training sequence */ if (++s->training_step <= V27TER_TRAINING_SEG_5) { if (s->training_step <= V27TER_TRAINING_SEG_4) diff --git a/libs/spandsp/src/v42.c b/libs/spandsp/src/v42.c index 3e73d67c27..3830f5c53a 100644 --- a/libs/spandsp/src/v42.c +++ b/libs/spandsp/src/v42.c @@ -246,7 +246,7 @@ static int tx_supervisory_frame(lapm_state_t *s, uint8_t addr, uint8_t ctrl, uin { v42_frame_t *f; uint8_t *buf; - + if ((f = get_next_free_ctrl_frame(s)) == NULL) return -1; buf = f->buf; @@ -438,7 +438,7 @@ static void transmit_xid(v42_state_t *ss, uint8_t addr) *buf++ = 2; *buf++ = (param_val >> 8) & 0xFF; *buf++ = (param_val & 0xFF); - + *buf++ = PI_TX_WINDOW_SIZE; *buf++ = 1; *buf++ = ss->config.v42_tx_window_size_k; @@ -466,7 +466,7 @@ static void transmit_xid(v42_state_t *ss, uint8_t addr) *buf++ = '4'; *buf++ = '2'; - /* V.42bis P0 + /* V.42bis P0 00 Compression in neither direction (default); 01 Negotiation initiator-responder direction only; 10 Negotiation responder-initiator direction only; @@ -1155,7 +1155,7 @@ static int lapm_config(v42_state_t *ss) static void reset_lapm(v42_state_t *ss) { lapm_state_t *s; - + s = &ss->lapm; /* Reset the LAP.M state */ s->local_busy = FALSE; diff --git a/libs/spandsp/src/v42bis.c b/libs/spandsp/src/v42bis.c index 2b25df28c2..fec129a6f2 100644 --- a/libs/spandsp/src/v42bis.c +++ b/libs/spandsp/src/v42bis.c @@ -23,10 +23,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. - Currently it performs the core compression and decompression functions OK. - However, a number of the bells and whistles in V.42bis are incomplete. */ - /*! \file */ #if defined(HAVE_CONFIG_H) @@ -59,7 +55,7 @@ /* Index number of first dictionary entry used to store a string */ #define V42BIS_N5 (V42BIS_N4 + V42BIS_N6) /* Number of control codewords */ -#define V42BIS_N6 3 +#define V42BIS_N6 3 /* V.42bis/9.2 */ #define V42BIS_ESC_STEP 51 @@ -489,7 +485,7 @@ SPAN_DECLARE(int) v42bis_compress_flush(v42bis_state_t *ss) { v42bis_comp_state_t *s; int len; - + s = &ss->compress; if (s->update_at) return 0; @@ -692,7 +688,7 @@ SPAN_DECLARE(int) v42bis_decompress_flush(v42bis_state_t *ss) { v42bis_comp_state_t *s; int len; - + s = &ss->decompress; len = s->string_length; send_string(s); diff --git a/libs/spandsp/src/v8.c b/libs/spandsp/src/v8.c index 37ef368a44..e04a1eba9c 100644 --- a/libs/spandsp/src/v8.c +++ b/libs/spandsp/src/v8.c @@ -22,7 +22,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /*! \file */ #if defined(HAVE_CONFIG_H) @@ -271,7 +271,7 @@ SPAN_DECLARE(void) v8_log_supported_modulations(v8_state_t *s, int modulation_sc { const char *comma; int i; - + comma = ""; span_log(&s->logging, SPAN_LOG_FLOW, ""); for (i = 0; i < 32; i++) @@ -562,7 +562,7 @@ static void put_bit(void *user_data, int bit) s->bit_cnt = 0; s->rx_data_ptr = 0; } - + if (s->preamble_type != V8_SYNC_UNKNOWN) { /* Parse octets with 1 bit start, 1 bit stop */ @@ -654,13 +654,13 @@ static void send_cm_jm(v8_state_t *s) int val; unsigned int offered_modulations; int bytes; - + /* Send a CM, or a JM as appropriate */ v8_put_preamble(s); v8_put_byte(s, V8_CM_JM_SYNC_OCTET); /* Data call */ v8_put_byte(s, (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG); - + /* Supported modulations */ offered_modulations = s->result.modulations; bytes = 0; @@ -949,14 +949,14 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len) if (s->got_cm_jm) { span_log(&s->logging, SPAN_LOG_FLOW, "CM recognised\n"); - + s->result.status = V8_STATUS_V8_OFFERED; report_event(s); - + /* Stop sending ANSam or ANSam/ and send JM instead */ fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH2], get_bit, s); /* Set the timeout for JM */ - s->negotiation_timer = ms_to_samples(5000); + s->negotiation_timer = ms_to_samples(5000); s->state = V8_JM_ON; send_cm_jm(s); s->modem_connect_tone_tx_on = ms_to_samples(75); @@ -1101,7 +1101,7 @@ SPAN_DECLARE(int) v8_release(v8_state_t *s) SPAN_DECLARE(int) v8_free(v8_state_t *s) { int ret; - + ret = queue_free(s->tx_queue); free(s); return ret; diff --git a/libs/spandsp/src/vector_float.c b/libs/spandsp/src/vector_float.c index dd09e449e1..b02e4288a9 100644 --- a/libs/spandsp/src/vector_float.c +++ b/libs/spandsp/src/vector_float.c @@ -52,7 +52,7 @@ SPAN_DECLARE(void) vec_copyf(float z[], const float x[], int n) { int i; __m128 n1; - + if ((i = n & ~3)) { for (i -= 4; i >= 0; i -= 4) @@ -76,7 +76,7 @@ SPAN_DECLARE(void) vec_copyf(float z[], const float x[], int n) SPAN_DECLARE(void) vec_copyf(float z[], const float x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = x[i]; } @@ -86,7 +86,7 @@ SPAN_DECLARE(void) vec_copyf(float z[], const float x[], int n) SPAN_DECLARE(void) vec_copy(double z[], const double x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = x[i]; } @@ -96,7 +96,7 @@ SPAN_DECLARE(void) vec_copy(double z[], const double x[], int n) SPAN_DECLARE(void) vec_copyl(long double z[], const long double x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = x[i]; } @@ -111,7 +111,7 @@ SPAN_DECLARE(void) vec_negatef(float z[], const float x[], int n) static const float *fmask = (float *) &mask; __m128 n1; __m128 n2; - + if ((i = n & ~3)) { n2 = _mm_set1_ps(*fmask); @@ -137,7 +137,7 @@ SPAN_DECLARE(void) vec_negatef(float z[], const float x[], int n) SPAN_DECLARE(void) vec_negatef(float z[], const float x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = -x[i]; } @@ -147,7 +147,7 @@ SPAN_DECLARE(void) vec_negatef(float z[], const float x[], int n) SPAN_DECLARE(void) vec_negate(double z[], const double x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = -x[i]; } @@ -157,7 +157,7 @@ SPAN_DECLARE(void) vec_negate(double z[], const double x[], int n) SPAN_DECLARE(void) vec_negatel(long double z[], const long double x[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = -x[i]; } @@ -169,7 +169,7 @@ SPAN_DECLARE(void) vec_zerof(float z[], int n) { int i; __m128 n1; - + if ((i = n & ~3)) { n1 = _mm_setzero_ps(); @@ -191,7 +191,7 @@ SPAN_DECLARE(void) vec_zerof(float z[], int n) SPAN_DECLARE(void) vec_zerof(float z[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = 0.0f; } @@ -201,7 +201,7 @@ SPAN_DECLARE(void) vec_zerof(float z[], int n) SPAN_DECLARE(void) vec_zero(double z[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = 0.0; } @@ -211,7 +211,7 @@ SPAN_DECLARE(void) vec_zero(double z[], int n) SPAN_DECLARE(void) vec_zerol(long double z[], int n) { int i; - + for (i = 0; i < n; i++) z[i] = 0.0L; } @@ -223,7 +223,7 @@ SPAN_DECLARE(void) vec_setf(float z[], float x, int n) { int i; __m128 n1; - + if ((i = n & ~3)) { n1 = _mm_set1_ps(x); @@ -245,7 +245,7 @@ SPAN_DECLARE(void) vec_setf(float z[], float x, int n) SPAN_DECLARE(void) vec_setf(float z[], float x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = x; } @@ -255,7 +255,7 @@ SPAN_DECLARE(void) vec_setf(float z[], float x, int n) SPAN_DECLARE(void) vec_set(double z[], double x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = x; } @@ -265,7 +265,7 @@ SPAN_DECLARE(void) vec_set(double z[], double x, int n) SPAN_DECLARE(void) vec_setl(long double z[], long double x, int n) { int i; - + for (i = 0; i < n; i++) z[i] = x; } @@ -278,7 +278,7 @@ SPAN_DECLARE(void) vec_addf(float z[], const float x[], const float y[], int n) int i; __m128 n1; __m128 n2; - + if ((i = n & ~3)) { for (i -= 4; i >= 0; i -= 4) @@ -339,7 +339,7 @@ SPAN_DECLARE(void) vec_scaledxy_addf(float z[], const float x[], float x_scale, __m128 n2; __m128 n3; __m128 n4; - + if ((i = n & ~3)) { n3 = _mm_set1_ps(x_scale); @@ -403,7 +403,7 @@ SPAN_DECLARE(void) vec_scaledy_addf(float z[], const float x[], const float y[], __m128 n1; __m128 n2; __m128 n3; - + if ((i = n & ~3)) { n3 = _mm_set1_ps(y_scale); @@ -464,7 +464,7 @@ SPAN_DECLARE(void) vec_subf(float z[], const float x[], const float y[], int n) int i; __m128 n1; __m128 n2; - + if ((i = n & ~3)) { for (i -= 4; i >= 0; i -= 4) @@ -552,7 +552,7 @@ SPAN_DECLARE(void) vec_scalar_mulf(float z[], const float x[], float y, int n) int i; __m128 n1; __m128 n2; - + if ((i = n & ~3)) { n2 = _mm_set1_ps(y); @@ -600,7 +600,7 @@ SPAN_DECLARE(void) vec_scalar_addf(float z[], const float x[], float y, int n) int i; __m128 n1; __m128 n2; - + if ((i = n & ~3)) { n2 = _mm_set1_ps(y); @@ -659,7 +659,7 @@ SPAN_DECLARE(void) vec_scalar_subf(float z[], const float x[], float y, int n) int i; __m128 n1; __m128 n2; - + if ((i = n & ~3)) { n2 = _mm_set1_ps(y); @@ -719,7 +719,7 @@ SPAN_DECLARE(void) vec_mulf(float z[], const float x[], const float y[], int n) __m128 n1; __m128 n2; __m128 n3; - + if ((i = n & ~3)) { for (i -= 4; i >= 0; i -= 4) @@ -781,7 +781,7 @@ SPAN_DECLARE(float) vec_dot_prodf(const float x[], const float y[], int n) __m128 n2; __m128 n3; __m128 n4; - + z = 0.0f; if ((i = n & ~3)) { @@ -869,7 +869,7 @@ SPAN_DECLARE(void) vec_lmsf(const float x[], float y[], int n, float error) __m128 n2; __m128 n3; __m128 n4; - + if ((i = n & ~3)) { n3 = _mm_set1_ps(error); diff --git a/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c b/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c index 5fe521df68..c862a2ba80 100644 --- a/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c +++ b/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c @@ -210,7 +210,7 @@ static void set_pixel_range(uint8_t buf[], int row, int start, int end) static void clear_pixel_range(uint8_t buf[], int row, int start, int end) { int i; - + for (i = start; i <= end; i++) clear_pixel(buf, row, i); } @@ -602,11 +602,11 @@ int main(int argc, char *argv[]) TIFFSetField(tiff_file, TIFFTAG_XRESOLUTION, floorf(x_resolution*2.54f + 0.5f)); TIFFSetField(tiff_file, TIFFTAG_YRESOLUTION, floorf(y_resolution*2.54f + 0.5f)); TIFFSetField(tiff_file, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); - + TIFFSetField(tiff_file, TIFFTAG_SOFTWARE, "spandsp"); if (gethostname(buf, sizeof(buf)) == 0) TIFFSetField(tiff_file, TIFFTAG_HOSTCOMPUTER, buf); - + TIFFSetField(tiff_file, TIFFTAG_IMAGEDESCRIPTION, "Blank test image"); TIFFSetField(tiff_file, TIFFTAG_MAKE, "soft-switch.org"); TIFFSetField(tiff_file, TIFFTAG_MODEL, "test data"); diff --git a/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c b/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c index 03ae0e8602..4276b8c835 100644 --- a/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c +++ b/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c @@ -29,7 +29,7 @@ This program generates an A4 sized FAX image of a fine checkerboard. This doesn't compress well, so it results in a rather large file for a single page. This is good for testing the handling of extreme pages. - + Note that due to a bug in FAX image handling, versions of libtiff up to 3.8.2 fail to handle this complex image properly, if 2-D compression is used. The bug should be fixed in CVS at the time of writing, and so should be fixed in released versions diff --git a/libs/spandsp/test-data/itu/fax/generate_sized_pages.c b/libs/spandsp/test-data/itu/fax/generate_sized_pages.c index a075f622e5..983e5e49b9 100644 --- a/libs/spandsp/test-data/itu/fax/generate_sized_pages.c +++ b/libs/spandsp/test-data/itu/fax/generate_sized_pages.c @@ -83,189 +83,189 @@ struct T4_X_RESOLUTION_R8, T4_Y_RESOLUTION_FINE, T4_WIDTH_R8_A4, - 2200 + 1100*2 }, { "R8_77_B4.tif", T4_X_RESOLUTION_R8, T4_Y_RESOLUTION_FINE, T4_WIDTH_R8_B4, - 2400 + 1200*2 }, { "R8_77_A3.tif", T4_X_RESOLUTION_R8, T4_Y_RESOLUTION_FINE, T4_WIDTH_R8_A3, - 3111 + 1556*2 }, { "R8_154_A4.tif", T4_X_RESOLUTION_R8, T4_Y_RESOLUTION_SUPERFINE, T4_WIDTH_R8_A4, - 4400 + 1100*4 }, { "R8_154_B4.tif", T4_X_RESOLUTION_R8, T4_Y_RESOLUTION_SUPERFINE, T4_WIDTH_R8_B4, - 4800 + 1200*4 }, { "R8_154_A3.tif", T4_X_RESOLUTION_R8, T4_Y_RESOLUTION_SUPERFINE, T4_WIDTH_R8_A3, - 6222 + 1556*4 }, { "R300_300_A4.tif", T4_X_RESOLUTION_300, T4_Y_RESOLUTION_300, T4_WIDTH_300_A4, - 4400 + 1100*3 }, { "R300_300_B4.tif", T4_X_RESOLUTION_300, T4_Y_RESOLUTION_300, T4_WIDTH_300_B4, - 4800 + 1200*3 }, { "R300_300_A3.tif", T4_X_RESOLUTION_300, T4_Y_RESOLUTION_300, T4_WIDTH_300_A3, - 6222 + 1556*3 }, { "R300_600_A4.tif", T4_X_RESOLUTION_300, T4_Y_RESOLUTION_600, T4_WIDTH_300_A4, - 4400 + 1100*6 }, { "R300_600_B4.tif", T4_X_RESOLUTION_300, T4_Y_RESOLUTION_600, T4_WIDTH_300_B4, - 4800 + 1200*6 }, { "R300_600_A3.tif", T4_X_RESOLUTION_300, T4_Y_RESOLUTION_600, T4_WIDTH_300_A3, - 6222 + 1556*6 }, { "R16_154_A4.tif", T4_X_RESOLUTION_R16, T4_Y_RESOLUTION_SUPERFINE, T4_WIDTH_R16_A4, - 4400 + 1100*4 }, { "R16_154_B4.tif", T4_X_RESOLUTION_R16, T4_Y_RESOLUTION_SUPERFINE, T4_WIDTH_R16_B4, - 4800 + 1200*4 }, { "R16_154_A3.tif", T4_X_RESOLUTION_R16, T4_Y_RESOLUTION_SUPERFINE, T4_WIDTH_R16_A3, - 6222 + 1556*4 }, { "R16_800_A4.tif", T4_X_RESOLUTION_R16, T4_Y_RESOLUTION_800, T4_WIDTH_R16_A4, - 4400 + 1100*8 }, { "R16_800_B4.tif", T4_X_RESOLUTION_R16, T4_Y_RESOLUTION_800, T4_WIDTH_R16_B4, - 4800 + 1200*8 }, { "R16_800_A3.tif", T4_X_RESOLUTION_R16, T4_Y_RESOLUTION_800, T4_WIDTH_R16_A3, - 6222 + 1556*8 }, { "R600_600_A4.tif", T4_X_RESOLUTION_600, T4_Y_RESOLUTION_600, T4_WIDTH_600_A4, - 4400 + 1100*6 }, { "R600_600_B4.tif", T4_X_RESOLUTION_600, T4_Y_RESOLUTION_600, T4_WIDTH_600_B4, - 4800 + 1200*6 }, { "R600_600_A3.tif", T4_X_RESOLUTION_600, T4_Y_RESOLUTION_600, T4_WIDTH_600_A3, - 6222 + 1556*6 }, { "R600_1200_A4.tif", T4_X_RESOLUTION_600, T4_Y_RESOLUTION_1200, T4_WIDTH_600_A4, - 4400 + 1100*12 }, { "R600_1200_B4.tif", T4_X_RESOLUTION_600, T4_Y_RESOLUTION_1200, T4_WIDTH_600_B4, - 4800 + 1200*12 }, { "R600_1200_A3.tif", T4_X_RESOLUTION_600, T4_Y_RESOLUTION_1200, T4_WIDTH_600_A3, - 6222 + 1556*12 }, { "R1200_1200_A4.tif", T4_X_RESOLUTION_1200, T4_Y_RESOLUTION_1200, T4_WIDTH_1200_A4, - 4400 + 1100*12 }, { "R1200_1200_B4.tif", T4_X_RESOLUTION_1200, T4_Y_RESOLUTION_1200, T4_WIDTH_1200_B4, - 4800 + 1200*12 }, { "R1200_1200_A3.tif", T4_X_RESOLUTION_1200, T4_Y_RESOLUTION_1200, T4_WIDTH_1200_A3, - 6222 + 1556*12 }, { NULL, @@ -291,7 +291,7 @@ int main(int argc, char *argv[]) int compression; int photo_metric; int fill_order; - + compression = T4_COMPRESSION_ITU_T6; photo_metric = PHOTOMETRIC_MINISWHITE; fill_order = FILLORDER_LSB2MSB; @@ -336,17 +336,17 @@ int main(int argc, char *argv[]) TIFFSetField(tiff_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tiff_file, TIFFTAG_PHOTOMETRIC, photo_metric); TIFFSetField(tiff_file, TIFFTAG_FILLORDER, fill_order); - + x_resolution = sequence[i].x_res/100.0f; y_resolution = sequence[i].y_res/100.0f; TIFFSetField(tiff_file, TIFFTAG_XRESOLUTION, floorf(x_resolution*2.54f + 0.5f)); TIFFSetField(tiff_file, TIFFTAG_YRESOLUTION, floorf(y_resolution*2.54f + 0.5f)); TIFFSetField(tiff_file, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); - + TIFFSetField(tiff_file, TIFFTAG_SOFTWARE, "spandsp"); if (gethostname(buf, sizeof(buf)) == 0) TIFFSetField(tiff_file, TIFFTAG_HOSTCOMPUTER, buf); - + TIFFSetField(tiff_file, TIFFTAG_IMAGEDESCRIPTION, "Blank test image"); TIFFSetField(tiff_file, TIFFTAG_MAKE, "soft-switch.org"); TIFFSetField(tiff_file, TIFFTAG_MODEL, "test data"); @@ -362,7 +362,7 @@ int main(int argc, char *argv[]) tm->tm_min, tm->tm_sec); TIFFSetField(tiff_file, TIFFTAG_DATETIME, buf); - + TIFFSetField(tiff_file, TIFFTAG_IMAGELENGTH, sequence[i].length); TIFFSetField(tiff_file, TIFFTAG_PAGENUMBER, 0, 1); TIFFSetField(tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN); diff --git a/libs/spandsp/tests/ademco_contactid_tests.c b/libs/spandsp/tests/ademco_contactid_tests.c index ba75905fb2..a54b22c6e9 100644 --- a/libs/spandsp/tests/ademco_contactid_tests.c +++ b/libs/spandsp/tests/ademco_contactid_tests.c @@ -240,7 +240,7 @@ static int end_to_end_tests(void) samples = ademco_contactid_receiver_tx(receiver, amp, SAMPLES_PER_CHUNK); for (j = samples; j < SAMPLES_PER_CHUNK; j++) amp[j] = 0; - + /* We add AWGN and codec impairments to the signal, to stress the tone detector. */ codec_munge(munge, amp, SAMPLES_PER_CHUNK); for (j = 0; j < SAMPLES_PER_CHUNK; j++) diff --git a/libs/spandsp/tests/adsi_tests.c b/libs/spandsp/tests/adsi_tests.c index d077de9986..17be38bcc4 100644 --- a/libs/spandsp/tests/adsi_tests.c +++ b/libs/spandsp/tests/adsi_tests.c @@ -233,7 +233,7 @@ static void put_adsi_msg(void *user_data, const uint8_t *msg, int len) int field_len; int message_type; uint8_t body[256]; - + printf("Good message received (%d bytes)\n", len); good_message_received = TRUE; for (i = 0; i < len; i++) @@ -784,7 +784,7 @@ int main(int argc, char *argv[]) } } outhandle = NULL; - + tdd_character_set_tests(); if (decode_test_file) diff --git a/libs/spandsp/tests/async_tests.c b/libs/spandsp/tests/async_tests.c index 1f49d56512..bd1a7d9d07 100644 --- a/libs/spandsp/tests/async_tests.c +++ b/libs/spandsp/tests/async_tests.c @@ -60,7 +60,7 @@ int v14_test_async_tx_get_bit(void *user_data) async_tx_state_t *s; int bit; static int destuff = 0; - + /* Special routine to test V.14 rate adaption, by randomly skipping stop bits. */ s = (async_tx_state_t *) user_data; @@ -110,7 +110,7 @@ int v14_test_async_tx_get_bit(void *user_data) static int test_get_async_byte(void *user_data) { int byte; - + byte = tx_async_chars & 0xFF; tx_async_chars++; return byte; @@ -150,7 +150,7 @@ int main(int argc, char *argv[]) printf("Test failed.\n"); exit(2); } - + printf("Test with async 7E1\n"); async_tx_init(&tx_async, 7, ASYNC_PARITY_EVEN, 1, FALSE, test_get_async_byte, NULL); async_rx_init(&rx_async, 7, ASYNC_PARITY_EVEN, 1, FALSE, test_put_async_byte, NULL); diff --git a/libs/spandsp/tests/at_interpreter_tests.c b/libs/spandsp/tests/at_interpreter_tests.c index 68915c9c58..bdb26e1bec 100644 --- a/libs/spandsp/tests/at_interpreter_tests.c +++ b/libs/spandsp/tests/at_interpreter_tests.c @@ -244,7 +244,7 @@ static const struct command_response_s general_test_seq[] = {"AT+FIT=?\r", "\r\n+FIT:(0-255),(0-1)\r\n\r\nOK\r\n"}, /* T.31 8.5.4 - DTE inactivity timeout */ {"AT+FIT?\r", "\r\n+FIT:0,0\r\n\r\nOK\r\n"}, {"AT+FLO=?\r", "\r\n+FLO:(0-2)\r\n\r\nOK\r\n"}, /* T.31 says to implement something similar to +IFC */ - {"AT+FLO?\r", "\r\n+FLO:2\r\n\r\nOK\r\n"}, + {"AT+FLO?\r", "\r\n+FLO:2\r\n\r\nOK\r\n"}, {"AT+FMI?\r", "\r\n" MANUFACTURER "\r\n\r\nOK\r\n"}, /* T.31 says to duplicate +GMI */ {"AT+FMM?\r", "\r\n" PACKAGE "\r\n\r\nOK\r\n"}, /* T.31 says to duplicate +GMM */ {"AT+FMR?\r", "\r\n" VERSION "\r\n\r\nOK\r\n"}, /* T.31 says to duplicate +GMR */ @@ -279,7 +279,7 @@ static const struct command_response_s general_test_seq[] = {"AT+ICLOK?\r", "\r\n+ICLOK:0\r\n\r\nOK\r\n"}, /* V.250 6.2.14 - Select sync transmit clock source */ {"AT+IDSR?\r", "\r\n+IDSR:0\r\n\r\nOK\r\n"}, /* V.250 6.2.16 - Select data set ready option */ {"AT+IFC=?\r", "\r\n+IFC:(0-2),(0-2)\r\n\r\nOK\r\n"}, /* V.250 6.2.12 - DTE-DCE local flow control */ - {"AT+IFC?\r", "\r\n+IFC:2,2\r\n\r\nOK\r\n"}, + {"AT+IFC?\r", "\r\n+IFC:2,2\r\n\r\nOK\r\n"}, {"AT+ILRR\r", "\r\nOK\r\n"}, /* V.250 6.2.13 - DTE-DCE local rate reporting */ {"AT+ILSD=?\r", "\r\n+ILSD:(0,1)\r\n\r\nOK\r\n"}, /* V.250 6.2.15 - Select long space disconnect option */ {"AT+ILSD?\r", "\r\n+ILSD:0\r\n\r\nOK\r\n"}, @@ -459,13 +459,13 @@ static int at_send_hdlc(at_state_t *s, uint8_t *t, int len) static int general_test(at_state_t *s) { int i; - + for (i = 0; general_test_seq[i].command[0]; i++) { response_buf_ptr = 0; response_buf[0] = '\0'; command_response_test_step = i; - at_send(s, general_test_seq[i].command); + at_send(s, general_test_seq[i].command); if (strcmp(general_test_seq[command_response_test_step].response, response_buf) != 0) { printf("Incorrect response\n"); @@ -544,7 +544,7 @@ static int at_tx_handler(at_state_t *s, void *user_data, const uint8_t *buf, siz putchar(buf[i]); } response_buf[response_buf_ptr] = '\0'; - + return 0; } /*- End of function --------------------------------------------------------*/ @@ -552,7 +552,7 @@ static int at_tx_handler(at_state_t *s, void *user_data, const uint8_t *buf, siz int main(int argc, char *argv[]) { at_state_t *at_state; - + if ((at_state = at_init(NULL, at_tx_handler, NULL, modem_call_control, NULL)) == NULL) { fprintf(stderr, "Cannot start the AT interpreter\n"); diff --git a/libs/spandsp/tests/awgn_tests.c b/libs/spandsp/tests/awgn_tests.c index 478c07cdd9..f5ba0c71ac 100644 --- a/libs/spandsp/tests/awgn_tests.c +++ b/libs/spandsp/tests/awgn_tests.c @@ -134,7 +134,7 @@ int main(int argc, char *argv[]) /* Now send it out for graphing. */ printf("%6d %.7f %.7f\n", i - 32768, x, p); } - + printf("Tests passed.\n"); return 0; } diff --git a/libs/spandsp/tests/bell_mf_rx_tests.c b/libs/spandsp/tests/bell_mf_rx_tests.c index 68c9a7a05b..ed33c95d35 100644 --- a/libs/spandsp/tests/bell_mf_rx_tests.c +++ b/libs/spandsp/tests/bell_mf_rx_tests.c @@ -236,14 +236,14 @@ int main(int argc, char *argv[]) /* Test 1: Mitel's test 1 isn't really a test. Its a calibration step, which has no meaning here. */ - printf ("Test 1: Calibration\n"); - printf (" Passed\n"); + printf("Test 1: Calibration\n"); + printf(" Passed\n"); /* Test 2: Decode check This is a sanity check, that all digits are reliably detected under ideal conditions. Each possible digit is repeated 10 times, with 68ms bursts. The level of each tone is about 6dB down from clip */ - printf ("Test 2: Decode check\n"); + printf("Test 2: Decode check\n"); my_mf_gen_init(0.0, -3, 0.0, -3, 68, 68); s = ALL_POSSIBLE_DIGITS; digit[1] = '\0'; @@ -258,14 +258,14 @@ int main(int argc, char *argv[]) actual = bell_mf_rx_get(mf_state, buf, 128); if (actual != 1 || buf[0] != digit[0]) { - printf (" Sent '%s'\n", digit); - printf (" Received '%s' [%d]\n", buf, actual); - printf (" Failed\n"); - exit (2); + printf(" Sent '%s'\n", digit); + printf(" Received '%s' [%d]\n", buf, actual); + printf(" Failed\n"); + exit(2); } } } - printf (" Passed\n"); + printf(" Passed\n"); /* Test 3: Recognition bandwidth and channel centre frequency check. Use all digits. Each digit types requires four tests to complete @@ -295,7 +295,7 @@ int main(int argc, char *argv[]) The spec calls for +-1.5% +-10Hz of bandwidth. */ - printf ("Test 3: Recognition bandwidth and channel centre frequency check\n"); + printf("Test 3: Recognition bandwidth and channel centre frequency check\n"); s = ALL_POSSIBLE_DIGITS; digit[1] = '\0'; j = 0; @@ -320,17 +320,17 @@ int main(int argc, char *argv[]) } rrb = (float) (nplus + nminus)/10.0; rcfo = (float) (nplus - nminus)/10.0; - printf (" %c (low) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", - digit[0], - rrb, - rcfo, - (float) nminus/10.0, - (float) nplus/10.0); + printf(" %c (low) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", + digit[0], + rrb, + rcfo, + (float) nminus/10.0, + (float) nplus/10.0); if (rrb < 3.0 + rcfo + (2.0*100.0*10.0/bell_mf_tones[j].f1) || rrb >= 15.0 + rcfo) { - printf (" Failed\n"); - exit (2); + printf(" Failed\n"); + exit(2); } for (nplus = 0, i = 1; i <= 60; i++) @@ -351,27 +351,27 @@ int main(int argc, char *argv[]) } rrb = (float) (nplus + nminus)/10.0; rcfo = (float) (nplus - nminus)/10.0; - printf (" %c (high) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", - digit[0], - rrb, - rcfo, - (float) nminus/10.0, - (float) nplus/10.0); + printf(" %c (high) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", + digit[0], + rrb, + rcfo, + (float) nminus/10.0, + (float) nplus/10.0); if (rrb < 3.0 + rcfo + (2.0*100.0*10.0/bell_mf_tones[j].f2) || rrb >= 15.0 + rcfo) { - printf (" Failed\n"); - exit (2); + printf(" Failed\n"); + exit(2); } j++; } - printf (" Passed\n"); + printf(" Passed\n"); /* Test 4: Acceptable amplitude ratio (twist). Twist all digits in both directions, and check the maximum twist we can accept. The way this is done is styled after the Mitel DTMF test, and has good and bad points. */ - printf ("Test 4: Acceptable amplitude ratio (twist)\n"); + printf("Test 4: Acceptable amplitude ratio (twist)\n"); s = ALL_POSSIBLE_DIGITS; digit[1] = '\0'; while (*s) @@ -538,12 +538,12 @@ int main(int argc, char *argv[]) if (!callback_ok) { printf(" Failed\n"); - exit (2); + exit(2); } printf(" Passed\n"); duration = time (NULL) - now; - printf ("Tests passed in %ds\n", duration); + printf("Tests passed in %ds\n", duration); return 0; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/tests/dc_restore_tests.c b/libs/spandsp/tests/dc_restore_tests.c index ef5c32208b..6fae1458a7 100644 --- a/libs/spandsp/tests/dc_restore_tests.c +++ b/libs/spandsp/tests/dc_restore_tests.c @@ -37,7 +37,7 @@ #include #include "spandsp.h" - + int main (int argc, char *argv[]) { awgn_state_t *noise_source; diff --git a/libs/spandsp/tests/dtmf_rx_tests.c b/libs/spandsp/tests/dtmf_rx_tests.c index 38ee420bdb..89a456bd82 100644 --- a/libs/spandsp/tests/dtmf_rx_tests.c +++ b/libs/spandsp/tests/dtmf_rx_tests.c @@ -47,12 +47,12 @@ The DTMF detection test suite performs similar tests to the Mitel test tape, traditionally used for testing DTMF receivers. Mitel seem to have discontinued -this product, but all it not lost. +this product, but all it not lost. The first side of the Mitel tape consists of a number of tone and tone+noise based tests. The test suite synthesizes equivalent test data. Being digitally generated, this data is rather more predictable than the test data on the nasty -old stretchy cassette tapes which Mitel sold. +old stretchy cassette tapes which Mitel sold. The second side of the Mitel tape contains fragments of real speech from real phone calls captured from the North American telephone network. These are @@ -62,14 +62,14 @@ copies of this seem to be unobtainable. However, Bellcore produce a much more aggressive set of three cassette tapes. All six side (about 30 minutes each) are filled with much tougher fragments of real speech from the North American telephone network. If you can do well in this test, nobody cares about your -results against the Mitel test tape. +results against the Mitel test tape. A fresh set of tapes was purchased for these tests, and digitised, producing 6 wave files of 16 bit signed PCM data, sampled at 8kHz. They were transcribed using a speed adjustable cassette player. The test tone at the start of the tapes is pretty accurate, and the new tapes should not have had much opportunity to stretch. It is believed these transcriptions are about as good as the source -material permits. +material permits. PLEASE NOTE @@ -79,7 +79,7 @@ you also have no right to use this data. The original tapes are the copyright material of BellCore, and they charge over US$200 for a set. I doubt they sell enough copies to consider this much of a business. However, it is their data, and it is their right to do as they wish with it. Currently I see no indication -they wish to give it away for free. +they wish to give it away for free. */ #if defined(HAVE_CONFIG_H) @@ -460,7 +460,7 @@ static void mitel_cm7291_side_1_tests(void) printf(" Passed\n"); /* Test 4: Acceptable amplitude ratio (twist). - Use only the diagonal pairs of tones (digits 1, 5, 9 and D). + Use only the diagonal pairs of tones (digits 1, 5, 9 and D). There are eight sections to the test. Each section contains 200 pulses with a 50ms duration for each pulse. Initially the amplitude of both tones is 6dB down from clip. The two sections to test one @@ -477,7 +477,7 @@ static void mitel_cm7291_side_1_tests(void) The Acceptable Amplitude Ratio in dB is equal to the number of responses registered in (a) or (b), divided by 10. - + TODO: This is supposed to work in 1/10dB steps, but here I used 1dB steps, as the current tone generator has its amplitude set in 1dB steps. @@ -527,7 +527,7 @@ static void mitel_cm7291_side_1_tests(void) clip. The amplitude of each is gradually attenuated by -35dB at a rate of 1dB per pulse. The Dynamic Range in dB is equal to the number of responses from the receiver during the test. - + Well not really, but that is the Mitel test. Lets sweep a bit further, and see what the real range is */ printf("Test 5: Dynamic range\n"); @@ -555,7 +555,7 @@ static void mitel_cm7291_side_1_tests(void) are transmitted at an amplitude of -6dB from clip per frequency. Pulse duration starts at 49ms and is gradually reduced to 10ms. Guard time in ms is equal to (500 - number of responses)/10. - + That is the Mitel test, and we will follow it. Its totally bogus, though. Just what the heck is a pass or fail here? */ @@ -580,7 +580,7 @@ static void mitel_cm7291_side_1_tests(void) level is -24dBV, the second -18dBV and the third -12dBV.. The acceptable signal to noise ratio is the lowest ratio of signal to noise in the test where the receiver responds to all 1000 pulses. - + Well, that is the Mitel test, but it doesn't tell you what the decoder can really do. Lets do a more comprehensive test */ @@ -597,7 +597,7 @@ static void mitel_cm7291_side_1_tests(void) // TODO: Clip for (sample = 0; sample < len; sample++) amp[sample] = saturate(amp[sample] + awgn(&noise_source)); - + codec_munge(munge, amp, len); dtmf_rx(dtmf_state, amp, len); @@ -735,10 +735,10 @@ static void dial_tone_tolerance_tests(void) printf(" Acceptable signal to dial tone ratio is %ddB\n", -15 - j); if ((use_dialtone_filter && (-15 - j) > -12) || - (!use_dialtone_filter && (-15 - j) > 10)) + (!use_dialtone_filter && (-15 - j) > 10)) { printf(" Failed\n"); - exit(2); + exit(2); } printf(" Passed\n"); } diff --git a/libs/spandsp/tests/echo_tests.c b/libs/spandsp/tests/echo_tests.c index c0f62a9266..aba34d92b9 100644 --- a/libs/spandsp/tests/echo_tests.c +++ b/libs/spandsp/tests/echo_tests.c @@ -112,7 +112,7 @@ typedef struct fir_float_state_t *fir; float history[35*8]; int pos; - float factor; + float factor; float power; float peak; } level_measurement_device_t; @@ -361,7 +361,7 @@ static void print_results(void) { if (!quiet) printf("test model ERL time Max Rin Max Rout Max Sgen Max Sin Max Sout\n"); - printf("%-4s %-1d %-5.1f%6.2fs%9.2f%9.2f%9.2f%9.2f%9.2f\n", + printf("%-4s %-1d %-5.1f%6.2fs%9.2f%9.2f%9.2f%9.2f%9.2f\n", test_name, chan_model.model_no, 20.0f*log10f(-chan_model.erl + 1.0e-10f), @@ -404,7 +404,7 @@ static int channel_model_create(channel_model_state_t *chan, int model, float er sizeof(line_model_d8_coeffs)/sizeof(line_model_d8_coeffs[0]), sizeof(line_model_d9_coeffs)/sizeof(line_model_d9_coeffs[0]) }; - static const float ki[] = + static const float ki[] = { 3.05e-5f, LINE_MODEL_D2_GAIN, @@ -488,13 +488,13 @@ static void write_log_files(int16_t rout, int16_t sin) fprintf(fdump, " %d %d %d %d %d %d %d %d %d %d\n", ctx->clean_nlp, - ctx->Ltx, + ctx->Ltx, ctx->Lrx, - ctx->Lclean, + ctx->Lclean, (ctx->nonupdate_dwell > 0), ctx->adapt, ctx->Lclean_bg, - ctx->Pstates, + ctx->Pstates, ctx->Lbgn_upper, ctx->Lbgn); #endif @@ -616,7 +616,7 @@ static void run_test(echo_can_state_t *ctx, int16_t (*tx_source)(void), int16_t static void print_test_title(const char *title) { - if (quiet == FALSE) + if (quiet == FALSE) printf(title); } /*- End of function --------------------------------------------------------*/ @@ -653,7 +653,7 @@ static int perform_test_sanity(void) echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CNG); run_test(ctx, local_css_signal, silence, 5000); echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION); - + for (i = 0; i < SAMPLE_RATE*10; i++) { tx = local_css_signal(); @@ -715,7 +715,7 @@ static int perform_test_sanity(void) //result_sound[result_cur++] = (ctx->narrowband_score)*5; // ? SAMPLE_RATE : -SAMPLE_RATE; //result_sound[result_cur++] = ctx->tap_rotate_counter*10; ////result_sound[result_cur++] = ctx->vad; - + put_residue(clean - far_tx); if (result_cur >= RESULT_CHANNELS*SAMPLE_RATE) { @@ -812,7 +812,7 @@ static int perform_test_2b(void) echo_can_flush(ctx); echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION); signal_restart(&local_css, 0.0f); - + /* Test 2B (a) - Convergence test with NLP disabled */ /* Converge the canceller */ @@ -863,17 +863,17 @@ static int perform_test_2ca(void) print_test_title("Performing test 2C(a) - Convergence with background noise present\n"); ctx = echo_can_init(TEST_EC_TAPS, 0); awgn_init_dbm0(&far_noise_source, 7162534, -50.0f); - + echo_can_flush(ctx); echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION); - + /* Converge a canceller */ signal_restart(&local_css, 0.0f); run_test(ctx, silence, silence, 200); - + awgn_init_dbm0(&far_noise_source, 7162534, -40.0f); run_test(ctx, local_css_signal, far_hoth_noise_signal, 5000); - + /* Now freeze adaption, and measure the echo. */ echo_can_adaption_mode(ctx, 0); level_measurements_reset_peaks(); @@ -901,18 +901,18 @@ static int perform_test_3a(void) echo_can_flush(ctx); echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION); - + run_test(ctx, silence, silence, 200); signal_restart(&local_css, 0.0f); signal_restart(&far_css, -20.0f); /* Apply double talk, with a weak far end signal */ run_test(ctx, local_css_signal, far_css_signal, 5000); - + /* Now freeze adaption. */ echo_can_adaption_mode(ctx, 0); run_test(ctx, local_css_signal, silence, 500); - + /* Now measure the echo */ level_measurements_reset_peaks(); run_test(ctx, local_css_signal, silence, 5000); @@ -943,20 +943,20 @@ static int perform_test_3ba(void) run_test(ctx, silence, silence, 200); signal_restart(&local_css, 0.0f); signal_restart(&far_css, 0.0f); - + /* Converge the canceller */ run_test(ctx, local_css_signal, silence, 5000); - + /* Apply double talk */ run_test(ctx, local_css_signal, far_css_signal, 5000); - + /* Now freeze adaption. */ echo_can_adaption_mode(ctx, 0); run_test(ctx, local_css_signal, far_css_signal, 1000); - + /* Turn off the double talk. */ run_test(ctx, local_css_signal, silence, 500); - + /* Now measure the echo */ level_measurements_reset_peaks(); run_test(ctx, local_css_signal, silence, 5000); @@ -983,20 +983,20 @@ static int perform_test_3bb(void) run_test(ctx, silence, silence, 200); signal_restart(&local_css, 0.0f); signal_restart(&far_css, -15.0f); - + /* Converge the canceller */ run_test(ctx, local_css_signal, silence, 5000); - + /* Apply double talk */ run_test(ctx, local_css_signal, far_css_signal, 5000); - + /* Now freeze adaption. */ echo_can_adaption_mode(ctx, 0); run_test(ctx, local_css_signal, silence, 1000); - + /* Turn off the double talk. */ run_test(ctx, local_css_signal, silence, 500); - + /* Now measure the echo */ level_measurements_reset_peaks(); run_test(ctx, local_css_signal, silence, 5000); @@ -1082,7 +1082,7 @@ static int perform_test_4(void) static int perform_test_5(void) { echo_can_state_t *ctx; - + /* Test 5 - Infinite return loss convergence test */ print_test_title("Performing test 5 - Infinite return loss convergence test\n"); ctx = echo_can_init(TEST_EC_TAPS, 0); @@ -1261,8 +1261,8 @@ static int perform_test_9(void) echo_can_flush(ctx); echo_can_adaption_mode(ctx, - ECHO_CAN_USE_ADAPTION - | ECHO_CAN_USE_NLP + ECHO_CAN_USE_ADAPTION + | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CNG); /* Test 9 part 1 - matching */ @@ -1492,7 +1492,7 @@ static void simulate_ec(char *argv[], int two_channel_file, int mode) if (two_channel_file) { txfile = sf_open_telephony_read(argv[0], 1); - rxfile = sf_open_telephony_read(argv[1], 1); + rxfile = sf_open_telephony_read(argv[1], 1); ecfile = sf_open_telephony_write(argv[2], 1); } else @@ -1524,7 +1524,7 @@ static void simulate_ec(char *argv[], int two_channel_file, int mode) exit(2); } if ((nrx = sf_readf_short(rxfile, &sin, 1)) < 0) - { + { fprintf(stderr, " Error reading rx sound file\n"); exit(2); } diff --git a/libs/spandsp/tests/fax_decode.c b/libs/spandsp/tests/fax_decode.c index a62e8971ee..37792a9f2b 100644 --- a/libs/spandsp/tests/fax_decode.c +++ b/libs/spandsp/tests/fax_decode.c @@ -139,7 +139,7 @@ static void print_frame(const char *io, const uint8_t *fr, int frlen) const char *country; const char *vendor; const char *model; - + fprintf(stderr, "%s %s:", io, t30_frametype(fr[2])); for (i = 2; i < frlen; i++) fprintf(stderr, " %02x", fr[i]); @@ -545,7 +545,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Failed to init\n"); exit(0); } - + for (;;) { len = sf_readf_short(inhandle, amp, SAMPLES_PER_CHUNK); diff --git a/libs/spandsp/tests/fax_tester.c b/libs/spandsp/tests/fax_tester.c index 7767a2d544..d42ea3a074 100644 --- a/libs/spandsp/tests/fax_tester.c +++ b/libs/spandsp/tests/fax_tester.c @@ -102,7 +102,7 @@ static void hdlc_underflow_handler(void *user_data) uint8_t buf[400]; s = (faxtester_state_t *) user_data; - + if (s->image_buffer) { /* We are sending an ECM image */ @@ -172,7 +172,7 @@ static void tone_detected(void *user_data, int tone, int level, int delay) SPAN_LOG_FLOW, "Tone was on for %fs\n", (float) (s->timer - s->tone_on_time)/SAMPLE_RATE + 0.55); - } + } s->tone_state = tone; if (tone == MODEM_CONNECT_TONES_NONE) front_end_step_complete(s); @@ -336,7 +336,7 @@ int faxtester_rx(faxtester_state_t *s, int16_t *amp, int len) int faxtester_tx(faxtester_state_t *s, int16_t *amp, int max_len) { int len; - + len = 0; if (s->transmit) { @@ -350,7 +350,7 @@ int faxtester_tx(faxtester_state_t *s, int16_t *amp, int max_len) { /* Pad to the requested length with silence */ memset(amp + len, 0, (max_len - len)*sizeof(int16_t)); - len = max_len; + len = max_len; } break; } @@ -362,7 +362,7 @@ int faxtester_tx(faxtester_state_t *s, int16_t *amp, int max_len) { /* Pad to the requested length with silence */ memset(amp, 0, max_len*sizeof(int16_t)); - len = max_len; + len = max_len; } } return len; diff --git a/libs/spandsp/tests/fax_tests.c b/libs/spandsp/tests/fax_tests.c index cf28500905..02c840974a 100644 --- a/libs/spandsp/tests/fax_tests.c +++ b/libs/spandsp/tests/fax_tests.c @@ -343,7 +343,7 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result) int i; t30_stats_t t; char tag[20]; - + i = (int) (intptr_t) user_data; snprintf(tag, sizeof(tag), "%c: Phase E", i + 'A'); printf("%c: Phase E handler - (%d) %s\n", i + 'A', result, t30_completion_code_to_str(result)); @@ -363,7 +363,7 @@ static void real_time_frame_handler(t30_state_t *s, int len) { int i; - + i = (intptr_t) user_data; printf("%c: Real time frame handler - %s, %s, length = %d\n", i + 'A', @@ -376,7 +376,7 @@ static void real_time_frame_handler(t30_state_t *s, static int document_handler(t30_state_t *s, void *user_data, int event) { int i; - + i = (intptr_t) user_data; printf("%c: Document handler - event %d\n", i + 'A', event); return FALSE; @@ -400,7 +400,7 @@ static void real_time_gateway_frame_handler(t38_gateway_state_t *s, int len) { int i; - + i = (intptr_t) user_data; printf("%c: Real time gateway frame handler - %s, %s, length = %d\n", i + 'A', @@ -674,7 +674,7 @@ int main(int argc, char *argv[]) } } memset(silence, 0, sizeof(silence)); - + srand48(0x1234567); /* Set up the nodes */ input_wave_handle = NULL; @@ -858,6 +858,7 @@ int main(int argc, char *argv[]) | T30_SUPPORT_300_600_RESOLUTION | T30_SUPPORT_400_800_RESOLUTION | T30_SUPPORT_600_1200_RESOLUTION); + //t30_set_rx_encoding(t30_state[i], T4_COMPRESSION_ITU_T85); t30_set_ecm_capability(t30_state[i], use_ecm); if (use_ecm) { @@ -1096,7 +1097,7 @@ int main(int argc, char *argv[]) exit(2); } } - + /* Check how many pages should have been transferred */ expected_pages = get_tiff_total_pages(input_tiff_file_name); if (end_page >= 0 && expected_pages > end_page + 1) diff --git a/libs/spandsp/tests/fax_utils.c b/libs/spandsp/tests/fax_utils.c index b306855965..b6f075da6d 100644 --- a/libs/spandsp/tests/fax_utils.c +++ b/libs/spandsp/tests/fax_utils.c @@ -41,7 +41,7 @@ void fax_log_tx_parameters(t30_state_t *s, const char *tag) { const char *u; - + if ((u = t30_get_tx_ident(s))) printf("%s: Local ident '%s'\n", tag, u); if ((u = t30_get_tx_sub_address(s))) diff --git a/libs/spandsp/tests/fsk_tests.c b/libs/spandsp/tests/fsk_tests.c index 22ee5ab3c6..9cd69f5865 100644 --- a/libs/spandsp/tests/fsk_tests.c +++ b/libs/spandsp/tests/fsk_tests.c @@ -174,7 +174,7 @@ int main(int argc, char *argv[]) int16_t out_amp[2*BLOCK_LEN]; SNDFILE *inhandle; SNDFILE *outhandle; - int outframes; + int outframes; int i; int j; int samples; @@ -350,14 +350,14 @@ int main(int argc, char *argv[]) } off_at = i; printf("Carrier on at %d, off at %d\n", on_at, off_at); - if (on_at < -29 || on_at > -26 + if (on_at < -29 || on_at > -26 || off_at < -35 || off_at > -31) { printf("Tests failed.\n"); exit(2); } - + printf("Test with BERT\n"); test_bps = preset_fsk_specs[modem_under_test_1].baud_rate; if (modem_under_test_1 >= 0) @@ -426,7 +426,7 @@ int main(int argc, char *argv[]) out_amp[2*i + 1] = answerer_model_amp[i]; for ( ; i < BLOCK_LEN; i++) out_amp[2*i + 1] = 0; - + if (log_audio) { outframes = sf_writef_short(outhandle, out_amp, BLOCK_LEN); @@ -468,7 +468,7 @@ int main(int argc, char *argv[]) } break; } - + /* Put a little silence between the chunks in the file. */ memset(out_amp, 0, sizeof(out_amp)); if (log_audio) diff --git a/libs/spandsp/tests/g711_tests.c b/libs/spandsp/tests/g711_tests.c index cf4453c4a2..bb0956d677 100644 --- a/libs/spandsp/tests/g711_tests.c +++ b/libs/spandsp/tests/g711_tests.c @@ -173,7 +173,7 @@ static void compliance_tests(int log_audio) printf("Tests failed\n"); exit(2); } - + printf("Cyclic conversion repeatability tests.\n"); /* Find what happens to every possible linear value after a round trip. */ for (i = 0; i < 65536; i++) @@ -200,7 +200,7 @@ static void compliance_tests(int log_audio) exit(2); } } - + printf("Reference power level tests.\n"); power_meter_init(&power_meter, 7); @@ -274,7 +274,7 @@ static void compliance_tests(int log_audio) } } } - + enc_state = g711_init(NULL, G711_ALAW); transcode = g711_init(NULL, G711_ALAW); dec_state = g711_init(NULL, G711_ULAW); diff --git a/libs/spandsp/tests/g722_tests.c b/libs/spandsp/tests/g722_tests.c index 28688999b1..dff1b959d2 100644 --- a/libs/spandsp/tests/g722_tests.c +++ b/libs/spandsp/tests/g722_tests.c @@ -136,7 +136,7 @@ static const char *decode_test_files[] = TESTDATA_DIR "T3L3.RC2", TESTDATA_DIR "T3L3.RC3", TESTDATA_DIR "T3H3.RC0", - + NULL }; @@ -197,13 +197,13 @@ static int get_test_vector(const char *file, uint16_t buf[], int max_len) int octets; int i; FILE *infile; - + if ((infile = fopen(file, "r")) == NULL) { fprintf(stderr, " Failed to open '%s'\n", file); exit(2); } - octets = 0; + octets = 0; while ((i = get_vector(infile, buf + octets)) > 0) octets += i; fclose(infile); @@ -232,7 +232,7 @@ static void itu_compliance_tests(void) for (file = 0; encode_test_files[file]; file += 2) { printf("Testing %s -> %s\n", encode_test_files[file], encode_test_files[file + 1]); - + /* Get the input data */ len_data = get_test_vector(encode_test_files[file], (uint16_t *) itu_data, MAX_TEST_VECTOR_LEN); @@ -322,7 +322,7 @@ static void itu_compliance_tests(void) len = j - i; for (k = 0; k < len; k++) compressed[k] = itu_data[k + i] >> ((mode == 3) ? 10 : (mode == 2) ? 9 : 8); - + dec_state = g722_decode_init(NULL, (mode == 3) ? 48000 : (mode == 2) ? 56000 : 64000, 0); dec_state->itu_test_mode = TRUE; len2 = g722_decode(dec_state, decompressed, compressed, len); diff --git a/libs/spandsp/tests/g726_tests.c b/libs/spandsp/tests/g726_tests.c index 369a8860ed..4fba66021e 100644 --- a/libs/spandsp/tests/g726_tests.c +++ b/libs/spandsp/tests/g726_tests.c @@ -157,7 +157,7 @@ Algorithm Input Intermediate Output Input Intermediate Output HN40FA.I HN40FX.O HV40FA.I HV40FX.O */ -#define G726_ENCODING_NONE 9999 +#define G726_ENCODING_NONE 9999 typedef struct { @@ -1043,13 +1043,13 @@ static int get_test_vector(const char *file, uint8_t buf[], int max_len) int i; int sum; FILE *infile; - + if ((infile = fopen(file, "r")) == NULL) { fprintf(stderr, " Failed to open '%s'\n", file); exit(2); } - octets = 0; + octets = 0; while ((i = get_vector(infile, buf + octets)) > 0) octets += i; fclose(infile); @@ -1253,7 +1253,7 @@ int main(int argc, char *argv[]) printf("ADPCM packing is %d\n", packing); g726_init(&enc_state, bit_rate, G726_ENCODING_LINEAR, packing); g726_init(&dec_state, bit_rate, G726_ENCODING_LINEAR, packing); - + while ((frames = sf_readf_short(inhandle, amp, 159))) { adpcm = g726_encode(&enc_state, adpcmdata, amp, frames); diff --git a/libs/spandsp/tests/gsm0610_tests.c b/libs/spandsp/tests/gsm0610_tests.c index 6b41a33b07..9993a39260 100644 --- a/libs/spandsp/tests/gsm0610_tests.c +++ b/libs/spandsp/tests/gsm0610_tests.c @@ -92,7 +92,7 @@ copied to etsitests/gsm0610/unpacked so the files are arranged in the following ./fr_sync_A: Seqsync_A.inp Sync000_A.cod --to-- Sync159_A.cod - + ./fr_sync_L: Bitsync.inp Seqsync.inp @@ -153,7 +153,7 @@ static int get_test_vector(int full, int disk, const char *name) int in; int len; int i; - + if (full) { sprintf(buf, "%s%c/%s.inp", TESTDATA_DIR, 'L', name); @@ -189,7 +189,7 @@ static int get_test_vector(int full, int disk, const char *name) { vector_len = len; } - + sprintf(buf, "%s%c/%s.cod", TESTDATA_DIR, 'L', name); if ((in = open(buf, O_RDONLY)) < 0) { @@ -221,9 +221,9 @@ static int get_law_test_vector(int full, int law, const char *name) int len; int i; int law_uc; - + law_uc = toupper(law); - + if (full) { sprintf(buf, "%s%c/%s-%c.inp", TESTDATA_DIR, law_uc, name, law_uc); @@ -286,7 +286,7 @@ static int get_law_test_vector(int full, int law, const char *name) len /= sizeof(int16_t); for (i = 0; i < len; i++) decoder_code_vector[i] = code_vector_buf[i]; - + return len; } /*- End of function --------------------------------------------------------*/ @@ -368,7 +368,7 @@ static int perform_law_test(int full, int law, const char *name) printf("Performing A-law test '%s'\n", name); else printf("Performing u-law test '%s'\n", name); - + get_law_test_vector(full, law, name); if (full) @@ -448,9 +448,9 @@ static int repack_gsm0610_voip_to_wav49(uint8_t c[], const uint8_t d[]) { gsm0610_frame_t frame[2]; int n; - - n = gsm0610_unpack_voip(&frame[0], d); - gsm0610_unpack_voip(&frame[1], d + n); + + n = gsm0610_unpack_voip(&frame[0], d); + gsm0610_unpack_voip(&frame[1], d + n); n = gsm0610_pack_wav49(c, frame); return n; } @@ -479,7 +479,7 @@ static int perform_pack_unpack_test(void) printf("Performing packing/unpacking tests (not part of the ETSI conformance tests).\n"); /* Try trans-packing a lot of random data looking for before/after mismatch. */ for (j = 0; j < 1000; j++) - { + { for (i = 0; i < 65; i++) a[i] = rand(); repack_gsm0610_wav49_to_voip(b, a); @@ -583,13 +583,13 @@ int main(int argc, char *argv[]) fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); exit(2); } - + if ((gsm0610_enc_state = gsm0610_init(NULL, packing)) == NULL) { fprintf(stderr, " Cannot create encoder\n"); exit(2); } - + if ((gsm0610_dec_state = gsm0610_init(NULL, packing)) == NULL) { fprintf(stderr, " Cannot create decoder\n"); @@ -602,7 +602,7 @@ int main(int argc, char *argv[]) gsm0610_decode(gsm0610_dec_state, post_amp, gsm0610_data, bytes); sf_writef_short(outhandle, post_amp, frames); } - + if (sf_close_telephony(inhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME); diff --git a/libs/spandsp/tests/hdlc_tests.c b/libs/spandsp/tests/hdlc_tests.c index a4a35dcf3c..70df13425c 100644 --- a/libs/spandsp/tests/hdlc_tests.c +++ b/libs/spandsp/tests/hdlc_tests.c @@ -818,7 +818,7 @@ static void decode_bitstream(const char *in_file_name) int num; hdlc_rx_state_t rx; FILE *in; - + if ((in = fopen(in_file_name, "r")) == NULL) { fprintf(stderr, "Failed to open '%s'\n", in_file_name); diff --git a/libs/spandsp/tests/ima_adpcm_tests.c b/libs/spandsp/tests/ima_adpcm_tests.c index c335f6179b..dcf2a6a4cb 100644 --- a/libs/spandsp/tests/ima_adpcm_tests.c +++ b/libs/spandsp/tests/ima_adpcm_tests.c @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) fprintf(stderr, " Cannot create encoder\n"); exit(2); } - + if ((ima_dec_state = ima_adpcm_init(NULL, variant, enc_chunk_size)) == NULL) { fprintf(stderr, " Cannot create decoder\n"); @@ -203,7 +203,7 @@ int main(int argc, char *argv[]) printf("Tests failed.\n"); exit(2); } - + printf("Tests passed.\n"); return 0; } diff --git a/libs/spandsp/tests/image_translate_tests.c b/libs/spandsp/tests/image_translate_tests.c index 5fb68c7042..cd4195f7da 100644 --- a/libs/spandsp/tests/image_translate_tests.c +++ b/libs/spandsp/tests/image_translate_tests.c @@ -196,7 +196,7 @@ static int test_dithered_50_by_50(int row, int width, uint8_t buf[]) " 46: @ @ @ @ @ @ @@ @ @ @@ @@ @@ @@@@@ @ @@ @@@@@@@@@@", " 47: @ @ @ @ @ @@ @ @ @@@@ @@@@ @@@@@ @@@@@@@@@@@ @@@@@", " 48: @ @ @ @@ @ @@ @@ @ @@ @ @@@ @ @@@@@ @@@@@@@@@@@@@", - " 49: @ @ @ @ @ @@ @@ @@ @@ @@@@ @@@@@@@ @@@@@@ @@@@@@@@" + " 49: @ @ @ @ @ @@ @@ @@ @@ @@@@ @@@@@@@ @@@@@@ @@@@@@@@" }; int i; int match; diff --git a/libs/spandsp/tests/make_g168_css.c b/libs/spandsp/tests/make_g168_css.c index 133782e9fa..0cb065783d 100644 --- a/libs/spandsp/tests/make_g168_css.c +++ b/libs/spandsp/tests/make_g168_css.c @@ -241,7 +241,7 @@ int main(int argc, char *argv[]) pk = peak(noise_sound, 8192); ms = rms(noise_sound, 8192); printf("Filtered noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); - + for (i = 0; i < 8192; i++) silence_sound[i] = 0.0; diff --git a/libs/spandsp/tests/modem_connect_tones_tests.c b/libs/spandsp/tests/modem_connect_tones_tests.c index 52b1f8d940..fd7f104992 100644 --- a/libs/spandsp/tests/modem_connect_tones_tests.c +++ b/libs/spandsp/tests/modem_connect_tones_tests.c @@ -130,7 +130,7 @@ static int preamble_get_bit(void *user_data) { static int bit_no = 0; int bit; - + /* Generate a section of HDLC flag octet preamble. Then generate some random bits, which should not look like preamble. */ if (++preamble_count < 255) diff --git a/libs/spandsp/tests/modem_echo_tests.c b/libs/spandsp/tests/modem_echo_tests.c index 4f042b9fcd..c6ce135a02 100644 --- a/libs/spandsp/tests/modem_echo_tests.c +++ b/libs/spandsp/tests/modem_echo_tests.c @@ -27,12 +27,12 @@ \section modem_echo_can_tests_page_sec_1 What does it do? Currently the echo cancellation tests only provide simple exercising of the cancellor in the way it might be used for line echo cancellation. The test code -is in echotests.c. +is in echotests.c. The goal is to test the echo cancellor again the G.16X specs. Clearly, that also means the goal for the cancellor itself is to comply with those specs. Right now, the only aspect of these tests implemented is the line impulse response -models in g168tests.c. +models in g168tests.c. \section modem_echo_can_tests_page_sec_2 How does it work? The current test consists of feeding an audio file of real speech to the echo @@ -42,7 +42,7 @@ real speech is also used to simulate a signal received form the far end of the line. This is gated so it is only placed for one second every 10 seconds, simulating the double talk condition. The resulting echo cancelled signal can either be store in a file for further analysis, or played back as the data is -processed. +processed. A number of modified versions of this test have been performed. The signal level of the two speech sources has been varied. Several simple models of the @@ -53,7 +53,7 @@ is very loud (with earlier versions, well, ....:) ). The lack of saturating arithmetic in general purpose CPUs is a huge disadvantage here, as software saturation logic would cause a major slow down. Floating point would be good, but is not usable in the Linux kernel. Anyway, the bottom line seems to be the -current design is genuinely useful, if imperfect. +current design is genuinely useful, if imperfect. \section modem_echo_can_tests_page_sec_2 How do I use it? @@ -69,7 +69,7 @@ echo_tests.c is commented out with a \#if. If this is enabled, detailed information about the results of the echo cancellation will be written to stdout. By saving this into a file, Grace (recommended), GnuPlot, or some other plotting package may be used to graphically display the functioning of the -cancellor. +cancellor. */ #if defined(HAVE_CONFIG_H) @@ -266,7 +266,7 @@ int main(int argc, char *argv[]) #if defined(ENABLE_GUI) int16_t amp[2]; #endif - + line_model_no = 0; use_gui = FALSE; for (i = 1; i < argc; i++) @@ -305,7 +305,7 @@ int main(int argc, char *argv[]) power_meter_init(&power_before, 5); power_meter_init(&power_after, 5); - + /* Measure the echo power before adaption */ modem_echo_can_adaption_mode(ctx, FALSE); for (i = 0; i < 8000*5; i++) @@ -319,7 +319,7 @@ int main(int argc, char *argv[]) unadapted_output_power = power_meter_current_dbm0(&power_before); unadapted_echo_power = power_meter_current_dbm0(&power_after); printf("Pre-adaption: output power %10.5fdBm0, echo power %10.5fdBm0\n", unadapted_output_power, unadapted_echo_power); - + /* Converge the canceller */ signal_restart(&local_css); modem_echo_can_adaption_mode(ctx, TRUE); @@ -364,7 +364,7 @@ int main(int argc, char *argv[]) adapted_output_power = power_meter_current_dbm0(&power_before); adapted_echo_power = power_meter_current_dbm0(&power_after); printf("Post-adaption: output power %10.5fdBm0, echo power %10.5fdBm0\n", adapted_output_power, adapted_echo_power); - + if (fabsf(adapted_output_power - unadapted_output_power) > 0.1f || adapted_echo_power > unadapted_echo_power - 30.0f) diff --git a/libs/spandsp/tests/noise_tests.c b/libs/spandsp/tests/noise_tests.c index 568c916682..0c7ee99bbf 100644 --- a/libs/spandsp/tests/noise_tests.c +++ b/libs/spandsp/tests/noise_tests.c @@ -202,7 +202,7 @@ int main (int argc, char *argv[]) exit(2); } } - + quality = 7; printf("Generating Hoth noise at -15dBOv to file\n"); level = -15; @@ -224,7 +224,7 @@ int main (int argc, char *argv[]) fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); exit(2); } - + printf("Tests passed.\n"); return 0; } diff --git a/libs/spandsp/tests/pcap_parse.c b/libs/spandsp/tests/pcap_parse.c index 2571dc7cbf..d9c6870029 100644 --- a/libs/spandsp/tests/pcap_parse.c +++ b/libs/spandsp/tests/pcap_parse.c @@ -79,7 +79,7 @@ struct iphdr uint32_t daddr; /*The options start here. */ }; - + #endif /* We define our own structures for Ethernet Header and IPv6 Header as they are not available on CYGWIN. @@ -287,6 +287,9 @@ int pcap_scan_pkts(const char *file, fprintf(stderr, "Truncated packet - total len = %d, captured len = %d\n", pkthdr->len, pkthdr->caplen); exit(2); } +#if 0 + printf("%d:%d -> %d:%d\n", ntohl(iphdr->saddr), ntohs(udphdr->source), ntohl(iphdr->daddr), ntohs(udphdr->dest)); +#endif body = (const uint8_t *) udphdr; body += sizeof(struct udphdr); body_len = pktlen - sizeof(struct udphdr); diff --git a/libs/spandsp/tests/playout_tests.c b/libs/spandsp/tests/playout_tests.c index acdbd8ed1c..a5180eafdf 100644 --- a/libs/spandsp/tests/playout_tests.c +++ b/libs/spandsp/tests/playout_tests.c @@ -260,7 +260,7 @@ static void static_buffer_tests(void) fr, type, len, - next_scheduled_send, + next_scheduled_send, next_actual_receive); switch (ret) { diff --git a/libs/spandsp/tests/power_meter_tests.c b/libs/spandsp/tests/power_meter_tests.c index 9dc6b3e4af..0dd04c7424 100644 --- a/libs/spandsp/tests/power_meter_tests.c +++ b/libs/spandsp/tests/power_meter_tests.c @@ -101,7 +101,7 @@ static int power_surge_detector_tests(void) if (prev_signal_present != signal_present) { signal_power = power_surge_detector_current_dbm0(sig); - if (signal_present) + if (signal_present) { if (ok == 0 && i >= 0 && i < 25) ok = 1; @@ -120,7 +120,7 @@ static int power_surge_detector_tests(void) if (extremes[3] < i) extremes[3] = i; printf("Off at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); - } + } prev_signal_present = signal_present; } amp_out[2*i] = amp[i]; diff --git a/libs/spandsp/tests/queue_tests.c b/libs/spandsp/tests/queue_tests.c index 4e208db946..d01aa60ec9 100644 --- a/libs/spandsp/tests/queue_tests.c +++ b/libs/spandsp/tests/queue_tests.c @@ -546,7 +546,7 @@ static void functional_message_tests(void) uint8_t buf[MSG_LEN]; int i; int len; - + total_in = 0; total_out = 0; diff --git a/libs/spandsp/tests/r2_mf_rx_tests.c b/libs/spandsp/tests/r2_mf_rx_tests.c index 66f6526e32..6fb9b0781d 100644 --- a/libs/spandsp/tests/r2_mf_rx_tests.c +++ b/libs/spandsp/tests/r2_mf_rx_tests.c @@ -149,7 +149,7 @@ static void my_mf_gen_init(float low_fudge, { const mf_digit_tones_t *tone; int i; - + for (i = 0; i < 15; i++) { if (fwd) @@ -190,7 +190,7 @@ static void codec_munge(int16_t amp[], int len) { int i; uint8_t alaw; - + for (i = 0; i < len; i++) { alaw = linear_to_alaw (amp[i]); @@ -245,15 +245,15 @@ static int test_a_tone_set(int fwd) /* Test 1: Mitel's test 1 isn't really a test. Its a calibration step, which has no meaning here. */ - printf ("Test 1: Calibration\n"); - printf (" Passed\n"); + printf("Test 1: Calibration\n"); + printf(" Passed\n"); /* Test 2: Decode check This is a sanity check, that all digits are reliably detected under ideal conditions. Each possible digit is repeated 10 times, with 68ms bursts. The level of each tone is about 6dB down from clip */ - printf ("Test 2: Decode check\n"); + printf("Test 2: Decode check\n"); my_mf_gen_init(0.0, -3, 0.0, -3, 68, fwd); s = r2_mf_tone_codes; while (*s) @@ -267,14 +267,14 @@ static int test_a_tone_set(int fwd) actual = r2_mf_rx_get(mf_state); if (actual != digit) { - printf (" Sent '%c'\n", digit); - printf (" Received 0x%X\n", actual); - printf (" Failed\n"); - exit (2); + printf(" Sent '%c'\n", digit); + printf(" Received 0x%X\n", actual); + printf(" Failed\n"); + exit(2); } } } - printf (" Passed\n"); + printf(" Passed\n"); /* Test 3: Recognition bandwidth and channel centre frequency check. Use all digits. Each digit types requires four tests to complete @@ -297,14 +297,14 @@ static int test_a_tone_set(int fwd) RRB% = (N+ + N-)/10 Receiver Center Frequency Offset (RCFO) is calculated as follows: RCFO% = X + (N+ - N-)/20 - + Note that this test doesn't test what it says it is testing at all, and the results are quite inaccurate, if not a downright lie! However, it follows the Mitel procedure, so how can it be bad? :) - + The spec calls for +-4 +-10Hz (ie +-14Hz) of bandwidth. */ - printf ("Test 3: Recognition bandwidth and channel centre frequency check\n"); + printf("Test 3: Recognition bandwidth and channel centre frequency check\n"); s = r2_mf_tone_codes; j = 0; while (*s) @@ -330,17 +330,17 @@ static int test_a_tone_set(int fwd) } rrb = (float) (nplus + nminus)/10.0; rcfo = (float) (nplus - nminus)/10.0; - printf (" %c (low) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", - digit, - rrb, - rcfo, - (float) nminus/10.0, - (float) nplus/10.0); + printf(" %c (low) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", + digit, + rrb, + rcfo, + (float) nminus/10.0, + (float) nplus/10.0); if (rrb < rcfo + (2.0*100.0*14.0/r2_mf_fwd_tones[j].f1) || rrb >= 15.0 + rcfo) { - printf (" Failed\n"); - exit (2); + printf(" Failed\n"); + exit(2); } for (nplus = 0, i = 1; i <= 60; i++) @@ -363,27 +363,27 @@ static int test_a_tone_set(int fwd) } rrb = (float) (nplus + nminus)/10.0; rcfo = (float) (nplus - nminus)/10.0; - printf (" %c (high) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", - digit, - rrb, - rcfo, - (float) nminus/10.0, - (float) nplus/10.0); + printf(" %c (high) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n", + digit, + rrb, + rcfo, + (float) nminus/10.0, + (float) nplus/10.0); if (rrb < rcfo + (2.0*100.0*14.0/r2_mf_fwd_tones[j].f2) || rrb >= 15.0 + rcfo) { - printf (" Failed\n"); - exit (2); + printf(" Failed\n"); + exit(2); } j++; } - printf (" Passed\n"); + printf(" Passed\n"); /* Test 4: Acceptable amplitude ratio (twist). Twist all digits in both directions, and check the maximum twist we can accept. The way this is done is styled after the Mitel DTMF test, and has good and bad points. */ - printf ("Test 4: Acceptable amplitude ratio (twist)\n"); + printf("Test 4: Acceptable amplitude ratio (twist)\n"); s = r2_mf_tone_codes; while (*s) { @@ -398,11 +398,11 @@ static int test_a_tone_set(int fwd) if (r2_mf_rx_get(mf_state) == digit) nplus++; } - printf (" %c normal twist = %.2fdB\n", digit, (float) nplus/10.0); + printf(" %c normal twist = %.2fdB\n", digit, (float) nplus/10.0); if (nplus < 70) { - printf (" Failed\n"); - exit (2); + printf(" Failed\n"); + exit(2); } for (nminus = 0, i = -50; i >= -250; i--) { @@ -414,21 +414,21 @@ static int test_a_tone_set(int fwd) if (r2_mf_rx_get(mf_state) == digit) nminus++; } - printf (" %c reverse twist = %.2fdB\n", digit, (float) nminus/10.0); + printf(" %c reverse twist = %.2fdB\n", digit, (float) nminus/10.0); if (nminus < 70) { - printf (" Failed\n"); - exit (2); + printf(" Failed\n"); + exit(2); } } - printf (" Passed\n"); + printf(" Passed\n"); /* Test 5: Dynamic range - This test sends all possible digits, with gradually increasing + This test sends all possible digits, with gradually increasing amplitude. We determine the span over which we achieve reliable detection. */ - - printf ("Test 5: Dynamic range\n"); + + printf("Test 5: Dynamic range\n"); for (nplus = nminus = -1000, i = -50; i <= 3; i++) { s = r2_mf_tone_codes; @@ -458,19 +458,19 @@ static int test_a_tone_set(int fwd) nminus = i; } } - printf (" Dynamic range = %ddB to %ddB\n", nplus, nminus - 1); + printf(" Dynamic range = %ddB to %ddB\n", nplus, nminus - 1); if (nplus > -35 || nminus <= -5) { printf(" Failed\n"); exit(2); } - printf (" Passed\n"); + printf(" Passed\n"); /* Test 6: Guard time - This test sends all possible digits, with a gradually reducing + This test sends all possible digits, with a gradually reducing duration. */ - printf ("Test 6: Guard time\n"); + printf("Test 6: Guard time\n"); for (i = 30; i < 62; i++) { s = r2_mf_tone_codes; @@ -493,19 +493,19 @@ static int test_a_tone_set(int fwd) if (j == 500) break; } - printf (" Guard time = %dms\n", i); + printf(" Guard time = %dms\n", i); if (i > 61) { printf(" Failed\n"); exit(2); } - printf (" Passed\n"); + printf(" Passed\n"); /* Test 7: Acceptable signal to noise ratio We send all possible digits at -6dBm from clip, mixed with AWGN. We gradually reduce the noise until we get clean detection. */ - printf ("Test 7: Acceptable signal to noise ratio\n"); + printf("Test 7: Acceptable signal to noise ratio\n"); my_mf_gen_init(0.0, -3, 0.0, -3, 68, fwd); for (i = -3; i > -50; i--) { @@ -563,7 +563,7 @@ static int test_a_tone_set(int fwd) if (!callback_ok) { printf(" Failed\n"); - exit (2); + exit(2); } printf(" Passed\n"); @@ -571,7 +571,7 @@ static int test_a_tone_set(int fwd) meaningless for R2 MF. However the decoder's tolerance of out of band noise is significant. */ /* TODO: add a OOB tolerance test. */ - + return 0; } /*- End of function --------------------------------------------------------*/ @@ -587,7 +587,7 @@ int main(int argc, char *argv[]) printf("R2 backward tones\n"); test_a_tone_set(FALSE); duration = time(NULL) - now; - printf ("Tests passed in %lds\n", duration); + printf("Tests passed in %lds\n", duration); return 0; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/tests/rfc2198_sim_tests.c b/libs/spandsp/tests/rfc2198_sim_tests.c index 2a88f24637..2c2700fc44 100644 --- a/libs/spandsp/tests/rfc2198_sim_tests.c +++ b/libs/spandsp/tests/rfc2198_sim_tests.c @@ -183,7 +183,7 @@ int main(int argc, char *argv[]) if ((len = rfc2198_sim_put(s, put_pkt, put_pkt_len, i, (double) i*0.001*PACKET_INTERVAL)) > 0) packets_really_put++; packets_put++; -#if 0 +#if 0 if (i == 5) rfc2198_sim_queue_dump(s); #endif diff --git a/libs/spandsp/tests/saturated_tests.c b/libs/spandsp/tests/saturated_tests.c index 419020cd1b..793cff9dd9 100644 --- a/libs/spandsp/tests/saturated_tests.c +++ b/libs/spandsp/tests/saturated_tests.c @@ -287,7 +287,7 @@ int main(int argc, char *argv[]) || saturated_mul16_32(32767, 32767) != 2147352578 || - saturated_mul16_32(-32768, -32768) != -2147483648) + saturated_mul16_32(-32768, -32768) != INT32_MAX) { printf("Test failed.\n"); exit(2); diff --git a/libs/spandsp/tests/schedule_tests.c b/libs/spandsp/tests/schedule_tests.c index f1b19bc946..e3aca335bc 100644 --- a/libs/spandsp/tests/schedule_tests.c +++ b/libs/spandsp/tests/schedule_tests.c @@ -94,7 +94,7 @@ int main(int argc, char *argv[]) when1 = span_schedule_time(&sched) + 500000; when2 = span_schedule_time(&sched) + 550000; //span_schedule_del(&sched, id); - + for (i = 0; i < 100000000; i += 20000) span_schedule_update(&sched, 20000); when = span_schedule_time(&sched); diff --git a/libs/spandsp/tests/sig_tone_tests.c b/libs/spandsp/tests/sig_tone_tests.c index 2aa30a98f1..4288891e57 100644 --- a/libs/spandsp/tests/sig_tone_tests.c +++ b/libs/spandsp/tests/sig_tone_tests.c @@ -88,12 +88,12 @@ static int use_gui = FALSE; static void plot_frequency_response(void) { FILE *gnucmd; - + if ((gnucmd = popen("gnuplot", "w")) == NULL) { exit(2); } - + fprintf(gnucmd, "set autoscale\n"); fprintf(gnucmd, "unset log\n"); fprintf(gnucmd, "unset label\n"); @@ -175,7 +175,7 @@ static void tx_handler(void *user_data, int what, int level, int duration) #endif {0, 0} }; - + s = (sig_tone_tx_state_t *) user_data; tx_handler_callbacks++; //printf("What - %d, duration - %d\n", what, duration); @@ -268,7 +268,7 @@ static void map_frequency_response(sig_tone_rx_state_t *s, template_t template[] double gain; int template_entry; FILE *file; - + /* Things like noise don't highlight the frequency response of the high Q notch very well. We use a slowly swept frequency to check it. */ printf("Frequency response test\n"); @@ -650,7 +650,7 @@ int main(int argc, char *argv[]) sequence_tests(&tx_state, &rx_state, munge); } /*endfor*/ - + printf("Tests completed.\n"); return 0; } diff --git a/libs/spandsp/tests/super_tone_rx_tests.c b/libs/spandsp/tests/super_tone_rx_tests.c index 718960463b..d090d7cce0 100644 --- a/libs/spandsp/tests/super_tone_rx_tests.c +++ b/libs/spandsp/tests/super_tone_rx_tests.c @@ -58,7 +58,7 @@ #define IN_FILE_NAME "super_tone.wav" #define MITEL_DIR "../test-data/mitel/" -#define BELLCORE_DIR "../test-data/bellcore/" +#define BELLCORE_DIR "../test-data/bellcore/" const char *bellcore_files[] = { @@ -270,7 +270,7 @@ static void get_tone_set(super_tone_rx_descriptor_t *desc, const char *tone_file xmlValidCtxt valid; #endif xmlChar *x; - + ns = NULL; xmlKeepBlanksDefault(0); xmlCleanupParser(); @@ -334,7 +334,7 @@ static void get_tone_set(super_tone_rx_descriptor_t *desc, const char *tone_file static void super_tone_rx_fill_descriptor(super_tone_rx_descriptor_t *desc) { int tone_id; - + tone_id = super_tone_rx_add_tone(desc); super_tone_rx_add_element(desc, tone_id, 400, 0, 700, 0); tone_names[tone_id] = "XXX"; @@ -390,12 +390,12 @@ static int talk_off_tests(super_tone_rx_state_t *super) x = super_tone_rx(super, amp + sample, frames - sample); sample += x; } - } + } if (sf_close_telephony(inhandle)) - { - printf(" Cannot close speech file '%s'\n", bellcore_files[j]); + { + printf(" Cannot close speech file '%s'\n", bellcore_files[j]); exit(2); - } + } } return 0; } diff --git a/libs/spandsp/tests/super_tone_tx_tests.c b/libs/spandsp/tests/super_tone_tx_tests.c index ff465193f7..561b333c36 100644 --- a/libs/spandsp/tests/super_tone_tx_tests.c +++ b/libs/spandsp/tests/super_tone_tx_tests.c @@ -212,7 +212,7 @@ static void get_tone_set(const char *tone_file, const char *set_id) #endif xmlChar *x; - ns = NULL; + ns = NULL; xmlKeepBlanksDefault(0); xmlCleanupParser(); doc = xmlParseFile(tone_file); diff --git a/libs/spandsp/tests/t31_pseudo_terminal_tests.c b/libs/spandsp/tests/t31_pseudo_terminal_tests.c index c216a901c1..da32c80c9f 100644 --- a/libs/spandsp/tests/t31_pseudo_terminal_tests.c +++ b/libs/spandsp/tests/t31_pseudo_terminal_tests.c @@ -70,9 +70,9 @@ typedef enum { - MODEM_POLL_READ = (1 << 0), - MODEM_POLL_WRITE = (1 << 1), - MODEM_POLL_ERROR = (1 << 2) + MODEM_POLL_READ = (1 << 0), + MODEM_POLL_WRITE = (1 << 1), + MODEM_POLL_ERROR = (1 << 2) } modem_poll_t; g1050_state_t *path_a_to_b; @@ -139,8 +139,8 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result) static int at_tx_handler(at_state_t *s, void *user_data, const uint8_t *buf, size_t len) { #if defined(WIN32) - DWORD res; - OVERLAPPED o; + DWORD res; + OVERLAPPED o; #else int res; #endif @@ -155,16 +155,16 @@ printf("\n"); modem = (modem_t *) user_data; #if defined(WIN32) - o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - /* Initialize the rest of the OVERLAPPED structure to zero. */ - o.Internal = 0; - o.InternalHigh = 0; - o.Offset = 0; - o.OffsetHigh = 0; - assert(o.hEvent); - if (!WriteFile(modem->master, buf, (DWORD) len, &res, &o)) - GetOverlappedResult(modem->master, &o, &res, TRUE); - CloseHandle(o.hEvent); + o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + /* Initialize the rest of the OVERLAPPED structure to zero. */ + o.Internal = 0; + o.InternalHigh = 0; + o.Offset = 0; + o.OffsetHigh = 0; + assert(o.hEvent); + if (!WriteFile(modem->master, buf, (DWORD) len, &res, &o)) + GetOverlappedResult(modem->master, &o, &res, TRUE); + CloseHandle(o.hEvent); #else res = write(modem->master, buf, len); #endif @@ -172,7 +172,7 @@ printf("\n"); { printf("Failed to write the whole buffer to the device. %d bytes of %d written: %s\n", res, (int) len, strerror(errno)); - if (res == -1) + if (res == -1) res = 0; #if !defined(WIN32) if (tcflush(modem->master, TCOFLUSH)) @@ -300,7 +300,7 @@ static int modem_wait_sock(modem_t *modem, int ms, modem_poll_t flags) HANDLE arHandles[2]; ret = MODEM_POLL_ERROR; - arHandles[0] = modem->threadAbort; + arHandles[0] = modem->threadAbort; o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); arHandles[1] = o.hEvent; @@ -322,7 +322,7 @@ static int modem_wait_sock(modem_t *modem, int ms, modem_poll_t flags) } else { - /* IO is pending, wait for it to finish */ + /* IO is pending, wait for it to finish */ dwWait = WaitForMultipleObjects(2, arHandles, FALSE, INFINITE); if (dwWait == WAIT_OBJECT_0 + 1 && !modem->block_read) ret = MODEM_POLL_READ; @@ -341,37 +341,37 @@ static int modem_wait_sock(modem_t *modem, int ms, modem_poll_t flags) #else static int modem_wait_sock(int sock, uint32_t ms, modem_poll_t flags) { - struct pollfd pfds[2] = {{0}}; - int s; + struct pollfd pfds[2] = {{0}}; + int s; int ret; - pfds[0].fd = sock; + pfds[0].fd = sock; - if ((flags & MODEM_POLL_READ)) - pfds[0].events |= POLLIN; - if ((flags & MODEM_POLL_WRITE)) - pfds[0].events |= POLLOUT; - if ((flags & MODEM_POLL_ERROR)) - pfds[0].events |= POLLERR; + if ((flags & MODEM_POLL_READ)) + pfds[0].events |= POLLIN; + if ((flags & MODEM_POLL_WRITE)) + pfds[0].events |= POLLOUT; + if ((flags & MODEM_POLL_ERROR)) + pfds[0].events |= POLLERR; - s = poll(pfds, (modem->block_read) ? 0 : 1, ms); + s = poll(pfds, (modem->block_read) ? 0 : 1, ms); ret = 0; - if (s < 0) + if (s < 0) { - ret = s; - } + ret = s; + } else if (s > 0) { - if ((pfds[0].revents & POLLIN)) - ret |= MODEM_POLL_READ; - if ((pfds[0].revents & POLLOUT)) - ret |= MODEM_POLL_WRITE; - if ((pfds[0].revents & POLLERR)) - ret |= MODEM_POLL_ERROR; - } + if ((pfds[0].revents & POLLIN)) + ret |= MODEM_POLL_READ; + if ((pfds[0].revents & POLLOUT)) + ret |= MODEM_POLL_WRITE; + if ((pfds[0].revents & POLLERR)) + ret |= MODEM_POLL_ERROR; + } - return ret; + return ret; } /*- End of function --------------------------------------------------------*/ @@ -407,8 +407,8 @@ static int t30_tests(int t38_mode, int use_ecm, int use_gui, int log_audio, int SNDFILE *in_handle; at_state_t *at_state; #if defined(WIN32) - DWORD read_bytes; - OVERLAPPED o; + DWORD read_bytes; + OVERLAPPED o; #endif /* Test the T.31 modem against the full FAX machine in spandsp */ @@ -606,18 +606,18 @@ printf("ZZZ\n"); if ((ret & MODEM_POLL_READ)) { #if defined(WIN32) - o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - /* Initialize the rest of the OVERLAPPED structure to zero. */ - o.Internal = 0; - o.InternalHigh = 0; - o.Offset = 0; - o.OffsetHigh = 0; - assert(o.hEvent); - if (!ReadFile(modem->master, buf, avail, &read_bytes, &o)) - GetOverlappedResult(modem->master, &o, &read_bytes, TRUE); - CloseHandle (o.hEvent); - if ((len = read_bytes)) + /* Initialize the rest of the OVERLAPPED structure to zero. */ + o.Internal = 0; + o.InternalHigh = 0; + o.Offset = 0; + o.OffsetHigh = 0; + assert(o.hEvent); + if (!ReadFile(modem->master, buf, avail, &read_bytes, &o)) + GetOverlappedResult(modem->master, &o, &read_bytes, TRUE); + CloseHandle (o.hEvent); + if ((len = read_bytes)) #else if ((len = read(modem[0].master, buf, 1024))) #endif diff --git a/libs/spandsp/tests/t85_tests.c b/libs/spandsp/tests/t85_tests.c index f0a27f38f7..b7047d2ad6 100644 --- a/libs/spandsp/tests/t85_tests.c +++ b/libs/spandsp/tests/t85_tests.c @@ -219,7 +219,7 @@ static int test_cycle(const char *test_id, down the image, will only succeed if a new chunk is started afterwards. */ if (comment) t85_encode_comment(t85_enc, comment, strlen((const char *) comment) + 1); - + testbuf_len = 0; max_len = 100; while ((len = t85_encode_get(t85_enc, &testbuf[testbuf_len], max_len)) > 0) @@ -321,7 +321,7 @@ static int test_cycle(const char *test_id, free(decoded_image); t85_decode_release(t85_dec); printf("Test passed\n"); - + return 0; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/tests/tone_generate_tests.c b/libs/spandsp/tests/tone_generate_tests.c index d5e01fb109..54b7c4e828 100644 --- a/libs/spandsp/tests/tone_generate_tests.c +++ b/libs/spandsp/tests/tone_generate_tests.c @@ -79,7 +79,7 @@ int main(int argc, char *argv[]) break; sf_writef_short(outhandle, amp, len); } - + /* Try a different tone pair */ tone_gen_descriptor_init(&tone_desc, 350, @@ -211,7 +211,7 @@ int main(int argc, char *argv[]) break; sf_writef_short(outhandle, amp, len); } - + /* Try an AM modulated tone at maximum modulation level (100%) */ tone_gen_descriptor_init(&tone_desc, 425, @@ -233,7 +233,7 @@ int main(int argc, char *argv[]) break; sf_writef_short(outhandle, amp, len); } - + if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME); diff --git a/libs/spandsp/tests/udptl.c b/libs/spandsp/tests/udptl.c index 96071da55d..96f2c25162 100644 --- a/libs/spandsp/tests/udptl.c +++ b/libs/spandsp/tests/udptl.c @@ -7,7 +7,7 @@ * * Written by Steve Underwood * - * Copyright (C) 2005 Steve Underwood + * Copyright (C) 2005, 2009, 2012 Steve Underwood * * All rights reserved. * @@ -381,6 +381,8 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int int len; int limit; int high_tide; + int len_before_entries; + int previous_len; /* UDPTL cannot cope with zero length messages, and our buffering for redundancy limits their maximum length. */ @@ -425,16 +427,28 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int entries = s->error_correction_entries; else entries = s->tx_seq_no; + len_before_entries = len; /* The number of entries will always be small, so it is pointless allowing for the fragmented case here. */ if (encode_length(buf, &len, entries) < 0) return -1; /* Encode the elements */ - for (i = 0; i < entries; i++) + for (m = 0; m < entries; m++) { - j = (entry - i - 1) & UDPTL_BUF_MASK; + previous_len = len; + j = (entry - m - 1) & UDPTL_BUF_MASK; if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) return -1; + + /* If we have exceeded the far end's max datagram size, don't include this last chunk, + and stop trying to add more. */ + if (len > s->far_max_datagram_size) + { + len = previous_len; + if (encode_length(buf, &len_before_entries, m) < 0) + return -1; + break; + } } break; case UDPTL_ERROR_CORRECTION_FEC: @@ -455,9 +469,11 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int buf[len++] = span; /* The number of entries is defined as a length, but will only ever be a small value. Treat it as such. */ + len_before_entries = len; buf[len++] = entries; for (m = 0; m < entries; m++) { + previous_len = len; /* Make an XOR'ed entry the maximum length */ limit = (entry + m) & UDPTL_BUF_MASK; high_tide = 0; @@ -479,6 +495,15 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int } if (encode_open_type(buf, &len, fec, high_tide) < 0) return -1; + + /* If we have exceeded the far end's max datagram size, don't include this last chunk, + and stop trying to add more. */ + if (len > s->far_max_datagram_size) + { + len = previous_len; + buf[len_before_entries] = (uint8_t) m; + break; + } } break; } diff --git a/libs/spandsp/tests/v18_tests.c b/libs/spandsp/tests/v18_tests.c index f084cdeecb..23efd7ae3c 100644 --- a/libs/spandsp/tests/v18_tests.c +++ b/libs/spandsp/tests/v18_tests.c @@ -50,11 +50,20 @@ int log_audio = FALSE; SNDFILE *outhandle = NULL; +char result[1024]; +int unexpected_echo = FALSE; char *decode_test_file = NULL; int good_message_received; +both_ways_line_model_state_t *model; +int rbs_pattern = 0; +float noise_level = -70.0f; +int line_model_no = 0; +int channel_codec = MUNGE_CODEC_NONE; +v18_state_t *v18[2]; + const char *qbf_tx = "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()'"; const char *qbf_rx = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789!X$$/'+.()'"; const char *full_baudot_rx = @@ -79,43 +88,61 @@ static void put_text_msg(void *user_data, const uint8_t *msg, int len) static void basic_tests(int mode) { - int16_t amp[SAMPLES_PER_CHUNK]; + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; int outframes; - int len; + int samples; int push; int i; - v18_state_t *v18_a; - v18_state_t *v18_b; - logging_state_t *logging; + int j; printf("Testing %s\n", v18_mode_to_str(mode)); - v18_a = v18_init(NULL, TRUE, mode, put_text_msg, NULL); - logging = v18_get_logging_state(v18_a); + v18[0] = v18_init(NULL, TRUE, mode, put_text_msg, NULL); + logging = v18_get_logging_state(v18[0]); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "A"); - v18_b = v18_init(NULL, FALSE, mode, put_text_msg, NULL); - logging = v18_get_logging_state(v18_b); + v18[1] = v18_init(NULL, FALSE, mode, put_text_msg, NULL); + logging = v18_get_logging_state(v18[1]); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "B"); + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + /* Fake an OK condition for the first message test */ good_message_received = TRUE; push = 0; - if (v18_put(v18_a, qbf_tx, -1) != strlen(qbf_tx)) + if (v18_put(v18[0], qbf_tx, -1) != strlen(qbf_tx)) { printf("V.18 put failed\n"); exit(2); } - for (i = 0; i < 100000; i++) + + for (i = 0; i < 10000; i++) { if (push == 0) { - if ((len = v18_tx(v18_a, amp, SAMPLES_PER_CHUNK)) == 0) + if ((samples = v18_tx(v18[0], amp[0], SAMPLES_PER_CHUNK)) == 0) push = 10; } else { - len = 0; + samples = 0; /* Push a little silence through, to flush things out */ if (--push == 0) { @@ -125,36 +152,71 @@ static void basic_tests(int mode) exit(2); } good_message_received = FALSE; - if (v18_put(v18_a, qbf_tx, -1) != strlen(qbf_tx)) + if (v18_put(v18[0], qbf_tx, -1) != strlen(qbf_tx)) { printf("V.18 put failed\n"); exit(2); } } } - if (len < SAMPLES_PER_CHUNK) + if (samples < SAMPLES_PER_CHUNK) { - memset(&[len], 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - len)); - len = SAMPLES_PER_CHUNK; + vec_zeroi16(&[0][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + if ((samples = v18_tx(v18[1], amp[1], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[1][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; } if (log_audio) { - outframes = sf_writef_short(outhandle, amp, len); - if (outframes != len) + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) { fprintf(stderr, " Error writing audio file\n"); exit(2); } } - v18_rx(v18_b, amp, len); +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); } - v18_free(v18_a); - v18_free(v18_b); + v18_free(v18[0]); + v18_free(v18[1]); } /*- End of function --------------------------------------------------------*/ static int test_misc_01(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.1 No disconnection test Purpose: To verify that the DCE does not initiate a disconnection. @@ -165,6 +227,73 @@ static int test_misc_01(void) TUT should continue to probe until the test is terminated. Comments: This feature should also be verified by observation during the automoding tests. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -172,6 +301,17 @@ static int test_misc_01(void) static int test_misc_02(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.2 Automatic resumption of automoding Purpose: To ensure that the DCE can be configured to automatically re-assume the automode @@ -182,10 +322,77 @@ static int test_misc_02(void) The tester will then transmit silence for 11 seconds followed by a 1300Hz tone for 5 seconds (i.e. V.23). Pass criteria: 1) Ten seconds after dropping the carrier the TUT should return to state Monitor 1. - 2) After 2.7±0.3 seconds the TUT should select V.23 mode and send a 390Hz tone. + 2) After 2.7+-0.3 seconds the TUT should select V.23 mode and send a 390Hz tone. Comments: The TUT should indicate that carrier has been lost at some time after the 1650Hz signal is lost. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -193,6 +400,17 @@ static int test_misc_02(void) static int test_misc_03(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.3 Retention of selected mode on loss of signal Purpose: To ensure that the DCE stays in the selected transmission mode if it is not @@ -207,6 +425,73 @@ static int test_misc_03(void) Comments: The TUT should indicate that carrier has been lost at some time after the carrier signal is removed and not disconnect. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -214,6 +499,17 @@ static int test_misc_03(void) static int test_misc_04(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.4 Detection of BUSY tone Purpose: To ensure that the DCE provides the call progress indication "BUSY" in presence of @@ -227,6 +523,73 @@ static int test_misc_04(void) automatically hang up when busy tone is detected. PABX busy tones may differ in frequency and cadence from national parameters. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -234,6 +597,17 @@ static int test_misc_04(void) static int test_misc_05(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.5 Detection of RINGING Purpose: To ensure that the DCE provides the call progress indication "RINGING" in @@ -244,6 +618,73 @@ static int test_misc_05(void) Pass criteria: The RINGING condition should be visually indicated by the TUT. Comments: This test should be repeated across a range of valid timings and ring voltages. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -251,6 +692,17 @@ static int test_misc_05(void) static int test_misc_06(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.6 "LOSS OF CARRIER" indication Purpose: To ensure that the DCE provides the call progress indication "LOSS OF CARRIER" @@ -264,6 +716,73 @@ static int test_misc_06(void) mode. There may be other cases, e.g. where the V.18 DCE is used in a gateway, when automatic disconnection is required. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -271,6 +790,17 @@ static int test_misc_06(void) static int test_misc_07(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.7 Call progress indication Purpose: To ensure that the DCE provides the call progress indication "CONNECT(x)" upon @@ -282,6 +812,73 @@ static int test_misc_07(void) However, this may possibly not be indicated by the DTE. Comments: The possible modes are: V.21, V.23, Baudot 45, Baudot 50, EDT, Bell 103, DTMF. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -289,6 +886,17 @@ static int test_misc_07(void) static int test_misc_08(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.8 Circuit 135 Test Purpose: To ensure that the DCE implements circuit 135 or an equivalent way of indicating @@ -301,6 +909,73 @@ static int test_misc_08(void) Comment: The response times and signal level thresholds of Circuit 135 are not specified in ITU-T V.18 or V.24 and therefore the pattern indicated may vary. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -308,6 +983,17 @@ static int test_misc_08(void) static int test_misc_09(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.1.9 Connection procedures Purpose: To ensure that the TUT implements the call connect procedure described in @@ -317,6 +1003,73 @@ static int test_misc_09(void) Pass criteria: TBD Comment: TBD */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -324,6 +1077,17 @@ static int test_misc_09(void) static int test_org_01(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.1 CI and XCI signal coding and cadence Purpose: To verify that TUT correctly emits the CI and XCI signals with the ON/OFF @@ -342,6 +1106,73 @@ static int test_org_01(void) 8) The whole sequence should be repeated until the call is cleared. 9) When V.18 to V.18, the XCI must not force V.23 or Minitel mode. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -349,6 +1180,17 @@ static int test_org_01(void) static int test_org_02(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.2 ANS signal detection Purpose: To verify that TUT correctly detects the ANS (2100Hz) signal during the @@ -362,6 +1204,73 @@ static int test_org_02(void) 2) The TUT should reply with transmission of TXP as defined in 5.1.2. 3) Verify that TXP sequence has correct bit pattern. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -369,6 +1278,17 @@ static int test_org_02(void) static int test_org_03(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.3 End of ANS signal detection Purpose: The TUT should stop sending TXP at the end of the current sequence when the ANS @@ -379,6 +1299,73 @@ static int test_org_03(void) Pass criteria: The TUT should stop sending TXP at the end of the current sequence when ANS tone ceases. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -386,6 +1373,17 @@ static int test_org_03(void) static int test_org_04(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.4 ANS tone followed by TXP Purpose: To check correct detection of V.18 modem. @@ -400,6 +1398,73 @@ static int test_org_04(void) with the V.18 operational requirements. Comments: The TUT should indicate that V.18 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -407,6 +1472,17 @@ static int test_org_04(void) static int test_org_05(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.5 ANS tone followed by 1650Hz Purpose: To check correct detection of V.21 modem upper channel when preceded by answer @@ -422,6 +1498,73 @@ static int test_org_05(void) examination of TUT. If there is no visual indication, verify by use of ITU-T T.50 for ITU-T V.21 as opposed to UTF-8 coded ISO 10646 character set for ITU-T V.18. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -429,6 +1572,17 @@ static int test_org_05(void) static int test_org_06(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.6 ANS tone followed by 1300Hz Purpose: To check correct detection of V.23 modem upper channel when preceded by answer @@ -443,6 +1597,73 @@ static int test_org_06(void) by the TUT to comply with Annex E. Comments: The TUT should indicate that V.23 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -450,6 +1671,17 @@ static int test_org_06(void) static int test_org_07(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.7 ANS tone followed by no tone Purpose: To confirm that TUT does not lock up under this condition. @@ -464,6 +1696,73 @@ static int test_org_07(void) literally. It may however, occur when connected to certain Swedish textphones if the handset is lifted just after the start of an automatically answered incoming call. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -471,16 +1770,94 @@ static int test_org_07(void) static int test_org_08(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.8 Bell 103 (2225Hz signal) detection Purpose: To verify that the TUT correctly detects the Bell 103 upper channel signal during the 2-second interval between transmission of CI sequences. Preamble: N/A Method: The tester waits for a CI and then sends a 2225Hz signal for 5 seconds. - Pass criteria: 1) The TUT should respond with a 1270Hz tone in 0.5±0.1 seconds. + Pass criteria: 1) The TUT should respond with a 1270Hz tone in 0.5+-0.1 seconds. 2) Data should be transmitted and received at 300 bit/s to comply with Annex D. Comments: The TUT should indicate that Bell 103 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -488,16 +1865,94 @@ static int test_org_08(void) static int test_org_09(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.9 V.21 (1650Hz signal) detection Purpose: To verify that the TUT correctly detects the V.21 upper channel signal during the 2-second interval between transmission of CI sequences. Preamble: N/A Method: The tester waits for a CI and then sends a 1650Hz signal for 5 seconds. - Pass criteria: 1) The TUT should respond with a 980Hz tone in 0.5±0.1 seconds. + Pass criteria: 1) The TUT should respond with a 980Hz tone in 0.5+-0.1 seconds. 2) Data should be transmitted and received at 300 bit/s to comply with Annex F. Comments: The TUT should indicate that V.21 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -505,17 +1960,95 @@ static int test_org_09(void) static int test_org_10(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.10 V.23 (1300Hz signal) detection Purpose: To verify that the TUT correctly detects the V.23 upper channel signal during the 2-second interval between transmission of CI sequences. Preamble: N/A Method: The tester waits for a CI and then sends a 1300Hz signal for 5 seconds. - Pass criteria: 1) The TUT should respond with a 390Hz tone in 1.7±0.1 seconds. + Pass criteria: 1) The TUT should respond with a 390Hz tone in 1.7+-0.1 seconds. 2) Data should be transmitted and received at 75 bit/s and 1200 bit/s respectively by the TUT to comply with Annex E. Comments: The TUT should indicate that V.23 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -523,6 +2056,17 @@ static int test_org_10(void) static int test_org_11(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.11 V.23 (390Hz signal) detection Purpose: To confirm correct selection of V.23 reverse mode during sending of XCI. @@ -537,6 +2081,73 @@ static int test_org_11(void) Comments: The TUT should indicate that V.23 mode has been selected at least 3 seconds after the start of the 390Hz tone. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -544,6 +2155,17 @@ static int test_org_11(void) static int test_org_12(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.12 5 bit mode (Baudot) detection tests Purpose: To confirm detection of Baudot modulation at various bit rates that may be @@ -563,6 +2185,73 @@ static int test_org_12(void) automode answer state. The TUT may then select either 45.45 or 50 bit/s for the transmission. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -570,6 +2259,17 @@ static int test_org_12(void) static int test_org_13(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.13 DTMF signal detection Purpose: To verify whether the TUT correctly recognizes DTMF signals during the 2-second @@ -583,6 +2283,73 @@ static int test_org_13(void) TUT should comply with ITU-T Q.24 for the Danish Administration while receiving for best possible performance. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -590,6 +2357,17 @@ static int test_org_13(void) static int test_org_14(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.14 EDT rate detection Purpose: To confirm detection of EDT modems by detecting the transmission rate of received @@ -605,6 +2383,73 @@ static int test_org_14(void) the number lost should be minimal. The data bits and parity are specified in Annex C. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -612,6 +2457,17 @@ static int test_org_14(void) static int test_org_15(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.15 Rate detection test Purpose: To verify the presence of 980/1180Hz at a different signalling rate than 110 bit/s @@ -622,6 +2478,73 @@ static int test_org_15(void) the CI signal. Comments: Echoes of the CI sequences may be detected at 300 bit/s. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -629,16 +2552,94 @@ static int test_org_15(void) static int test_org_16(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.16 980Hz detection Purpose: To confirm correct selection of V.21 reverse mode. Preamble: N/A Method: The tester sends 980Hz to TUT for 5 seconds. - Pass criteria: 1) TUT should respond with 1650Hz tone after 1.5±0.1 seconds after start of + Pass criteria: 1) TUT should respond with 1650Hz tone after 1.5+-0.1 seconds after start of 980Hz tone. 2) Data should be transmitted and received at 300 bit/s complying with Annex F. Comments: The TUT should indicate that V.21 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -646,6 +2647,17 @@ static int test_org_16(void) static int test_org_17(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.17 Loss of signal after 980Hz Purpose: To confirm that TUT returns to the Monitor 1 state if 980Hz signal disappears. @@ -654,6 +2666,73 @@ static int test_org_17(void) Pass criteria: TUT should not respond to the 980Hz tone and resume sending CI signals after a maximum of 2.4 seconds from the end of the 980Hz tone. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -661,16 +2740,94 @@ static int test_org_17(void) static int test_org_18(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.18 Tr timer Purpose: To confirm that TUT returns to the Monitor 1 state if Timer Tr expires. Preamble: N/A Method: The tester sends 980Hz to TUT for 1.2 seconds followed by 1650Hz for 5 seconds with no pause. - Pass criteria: TUT should respond with 980Hz after 1.3±0.1 seconds of 1650Hz. + Pass criteria: TUT should respond with 980Hz after 1.3+-0.1 seconds of 1650Hz. Comments: This implies timer Tr has expired 2 seconds after the start of the 980Hz tone and then 1650Hz has been detected for 0.5 seconds. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -678,15 +2835,93 @@ static int test_org_18(void) static int test_org_19(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.19 Bell 103 (1270Hz signal) detection Purpose: To confirm correct selection of Bell 103 reverse mode. Preamble: N/A Method: The tester sends 1270Hz to TUT for 5 seconds. - Pass criteria: 1) TUT should respond with 2225Hz tone after 0.7±0.1 s. + Pass criteria: 1) TUT should respond with 2225Hz tone after 0.7+-0.1 s. 2) Data should be transmitted and received at 300 bit/s complying with Annex D. Comments: The TUT should indicate that Bell 103 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -694,6 +2929,17 @@ static int test_org_19(void) static int test_org_20(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.20 Immunity to network tones Purpose: To ensure that the TUT does not interpret network tones as valid signals. @@ -710,6 +2956,73 @@ static int test_org_20(void) presence and cadence of the tones for instance by a flashing light. The TUT may disconnect on reception of tones indicating a failed call attempt. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -717,6 +3030,17 @@ static int test_org_20(void) static int test_org_21(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.21 Immunity to non-textphone modems Purpose: To ensure that the TUT does not interpret modem tones not supported by V.18 as @@ -729,6 +3053,73 @@ static int test_org_21(void) Comments: Some high speed modems may fall back to a compatibility mode, e.g. V.21 or V.23 that should be correctly detected by the TUT. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -736,6 +3127,17 @@ static int test_org_21(void) static int test_org_22(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.22 Immunity to fax tones Purpose: To ensure that the TUT will not interpret a called fax machine as being a textphone. @@ -747,6 +3149,73 @@ static int test_org_22(void) Comments: Ideally the TUT should detect the presence of a fax machine and report it back to the user. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -754,6 +3223,17 @@ static int test_org_22(void) static int test_org_23(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.23 Immunity to voice Purpose: To ensure that the TUT does not misinterpret speech as a valid textphone signal. @@ -765,6 +3245,73 @@ static int test_org_23(void) Comments: Ideally the TUT should report the presence of speech back to the user, e.g. via circuit 135. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -772,6 +3319,17 @@ static int test_org_23(void) static int test_org_24(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.24 ANSam signal detection Purpose: To verify that TUT correctly detects the ANSam (2100Hz modulated) signal during @@ -785,6 +3343,73 @@ static int test_org_24(void) 2) The TUT should reply with transmission of CM as defined in 5.2.13. 3) Verify that CM sequence has correct bit pattern. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -792,6 +3417,17 @@ static int test_org_24(void) static int test_org_25(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.2.25 V.8 calling procedure Purpose: To verify that TUT correctly performs a V.8 call negotiation. @@ -800,6 +3436,73 @@ static int test_org_25(void) Method: The Test System waits for the TUT to start transmitting V.21 carrier (1). Pass criteria: The TUT should connect by sending V.21 carrier (1). */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -807,6 +3510,17 @@ static int test_org_25(void) static int test_ans_01(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.1 Ta timer Purpose: To ensure that on connecting the call, the DCE starts timer Ta (3 seconds) and on @@ -816,6 +3530,73 @@ static int test_ans_01(void) answers the call. It will then monitor for any signal. Pass criteria: The TUT should start probing 3 seconds after answering the call. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -823,6 +3604,17 @@ static int test_ans_01(void) static int test_ans_02(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.2 CI signal detection Purpose: To confirm the correct detection and response to the V.18 CI signal. @@ -830,10 +3622,77 @@ static int test_ans_02(void) Method: The tester will transmit 2 sequences of 4 CI patterns separated by 2 seconds. It will monitor for ANS and measure duration. Pass criteria: 1) The TUT should respond after either the first or second CI with ANSam tone. - 2) ANSam tone should remain for 3 seconds ±0.5 s followed by silence. + 2) ANSam tone should remain for 3 seconds +-0.5 s followed by silence. Comments: The ANSam tone is a modulated 2100Hz tone. It may have phase reversals. The XCI signal is tested in a separate test. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -841,6 +3700,17 @@ static int test_ans_02(void) static int test_ans_03(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.3 Early termination of ANSam tone Purpose: To confirm that the TUT will respond correctly to TXP signals, i.e. by stopping @@ -849,13 +3719,80 @@ static int test_ans_03(void) Method: The tester will transmit 2 sequences of 4 CI patterns separated by 2 seconds. On reception of the ANSam tone the tester will wait 0.5 seconds and then begin transmitting the TXP signal in V.21 (1) mode. - Pass criteria: 1) On reception of the TXP signal, the TUT should remain silent for 75±5 ms. + Pass criteria: 1) On reception of the TXP signal, the TUT should remain silent for 75+-5 ms. 2) The TUT should then transmit 3 TXP sequences in V.21(2) mode. 3) The 3 TXPs should be followed by continuous 1650Hz. 4) Correct transmission and reception of T.140 data should be verified after the V.18 mode connection is completed. Comments: The TUT should indicate V.18 mode. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -863,6 +3800,17 @@ static int test_ans_03(void) static int test_ans_04(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.4 Tt timer Purpose: To ensure that after detection of ANSam the TUT will return to Monitor A after @@ -872,6 +3820,73 @@ static int test_ans_04(void) Pass criteria: The TUT should start probing 3 seconds after ANSam disappears. Comments: It is assumed that timer Ta is restarted on return to Monitor A. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -879,6 +3894,17 @@ static int test_ans_04(void) static int test_ans_05(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.5 ANS tone followed by 980Hz Purpose: To check correct detection of V.21 modem lower channel when preceded by answer @@ -886,9 +3912,76 @@ static int test_ans_05(void) Preamble: N/A Method: Tester transmits ANS for 2.5 seconds followed by 75 ms of no tone then transmits 980Hz and starts a 1 s timer. - Pass criteria: TUT should respond with 1650Hz within 400±100 ms of start of 980Hz. + Pass criteria: TUT should respond with 1650Hz within 400+-100 ms of start of 980Hz. Comments: The TUT should indicate that V.21 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -896,6 +3989,17 @@ static int test_ans_05(void) static int test_ans_06(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.6 ANS tone followed by 1300Hz Purpose: To check correct detection of V.23 modem upper channel when preceded by answer @@ -906,6 +4010,73 @@ static int test_ans_06(void) Pass criteria: TUT should respond with 390Hz after 1.7(+0.2-0.0) seconds of start of 1300Hz. Comments: The TUT should indicate that V.23 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -913,6 +4084,17 @@ static int test_ans_06(void) static int test_ans_07(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.7 ANS tone followed by 1650Hz Purpose: To check correct detection of V.21 modem upper channel when preceded by answer @@ -920,9 +4102,76 @@ static int test_ans_07(void) Preamble: N/A Method: Tester transmits ANS for 2.5 seconds followed by 75 ms of no tone then transmits 1650Hz and starts a 1-second timer. - Pass criteria: TUT should respond with 980Hz within 400±100 ms of start of 1650Hz. + Pass criteria: TUT should respond with 980Hz within 400+-100 ms of start of 1650Hz. Comments: The TUT should indicate that V.21 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -930,6 +4179,17 @@ static int test_ans_07(void) static int test_ans_08(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.8 980Hz followed by 1650Hz Purpose: To ensure the correct selection of V.21 modem channel when certain types of @@ -942,6 +4202,73 @@ static int test_ans_08(void) Comments: The TUT should indicate a V.21 connection. The time for which each frequency is transmitted is random and varies between 0.64 and 2.56 seconds. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -949,6 +4276,17 @@ static int test_ans_08(void) static int test_ans_09(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.9 980Hz calling tone detection Purpose: To confirm correct detection of 980Hz calling tones as defined in V.25. @@ -960,6 +4298,73 @@ static int test_ans_09(void) 700 ms followed by 1 second of silence. Comments: The probe sent by the TUT will depend on the country setting. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -967,15 +4372,93 @@ static int test_ans_09(void) static int test_ans_10(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.10 V.21 detection by timer Purpose: To confirm correct selection of V.21 calling modem when the received signal is not modulated, i.e. there is no 1180Hz. Preamble: N/A Method: The tester sends 980Hz to TUT for 2 seconds. - Pass criteria: The TUT should respond with a 1650Hz tone in 1.5±0.1 seconds. + Pass criteria: The TUT should respond with a 1650Hz tone in 1.5+-0.1 seconds. Comments: The TUT should indicate that V.21 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -983,6 +4466,17 @@ static int test_ans_10(void) static int test_ans_11(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.11 EDT detection by rate Purpose: To confirm detection of EDT modems by detecting the transmission rate of received @@ -996,6 +4490,73 @@ static int test_ans_11(void) be lost during the detection process. However, the number lost should be minimal. The data bits and parity are specified in Annex C. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1003,6 +4564,17 @@ static int test_ans_11(void) static int test_ans_12(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.12 V.21 Detection by rate Purpose: To confirm detection of V.21 modem low channel by detecting the transmission rate @@ -1017,6 +4589,73 @@ static int test_ans_12(void) (1650Hz) probe. However, it is catered for in V.18. It is more likely that this is where CI or TXP characters would be detected (see test ANS-02). */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1024,6 +4663,17 @@ static int test_ans_12(void) static int test_ans_13(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.13 Tr timer Purpose: To ensure that the TUT returns to the Monitor A state on expiry of timer Tr @@ -1031,12 +4681,79 @@ static int test_ans_13(void) Preamble: N/A Method: The tester will transmit 980Hz for 200 ms followed by alternating 980Hz/1180Hz at 110 bit/s for 100 ms followed by 980Hz for 1 second. - Pass criteria: The TUT should begin probing 4±0.5 seconds after the 980Hz signal is removed. + Pass criteria: The TUT should begin probing 4+-0.5 seconds after the 980Hz signal is removed. Comments: It is not possible to be precise on timings for this test since the definition of a "modulated signal" as in 5.2.4.4 is not specified. Therefore it is not known exactly when timer Tr will start. It is assumed that timer Ta is restarted on re-entering the Monitor A state. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1044,16 +4761,94 @@ static int test_ans_13(void) static int test_ans_14(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.14 Te timer Purpose: To ensure that the TUT returns to the Monitor A on expiry of timer Te (2.7 seconds). Timer Te is started when a 980Hz signal is detected. Preamble: N/A Method: The tester will transmit 980Hz for 200 ms followed silence for 7 s. - Pass criteria: The TUT should begin probing 5.5±0.5 seconds after the 980Hz signal is removed. + Pass criteria: The TUT should begin probing 5.5+-0.5 seconds after the 980Hz signal is removed. Comments: It is assumed that timer Ta (3 seconds) is restarted on re-entering the Monitor A state. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1061,6 +4856,17 @@ static int test_ans_14(void) static int test_ans_15(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.15 5 Bit mode (Baudot) detection tests Purpose: To confirm detection of Baudot modulation at various bit rates that may be @@ -1081,6 +4887,73 @@ static int test_ans_15(void) automode answer state. The TUT may then select either 45.45 or 50 bit/s for the transmission. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1088,6 +4961,17 @@ static int test_ans_15(void) static int test_ans_16(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.16 DTMF signal detection Purpose: To verify whether the TUT correctly recognizes DTMF signals. @@ -1099,6 +4983,73 @@ static int test_ans_16(void) Comments: The TUT should indicate that it has selected DTMF mode. The DTMF capabilities of the TUT should comply with ITU-T Q.24 for the Danish Administration. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1106,14 +5057,92 @@ static int test_ans_16(void) static int test_ans_17(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.17 Bell 103 (1270Hz signal) detection Purpose: To ensure correct detection and selection of Bell 103 modems. Preamble: N/A Method: The tester sends 1270Hz to TUT for 5 seconds. - Pass criteria: TUT should respond with 2225Hz tone after 0.7±0.1 s. + Pass criteria: TUT should respond with 2225Hz tone after 0.7+-0.1 s. Comments: The TUT should indicate that Bell 103 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1121,15 +5150,93 @@ static int test_ans_17(void) static int test_ans_18(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.18 Bell 103 (2225Hz signal) detection Purpose: To ensure correct detection and selection of Bell 103 modems in reverse mode. Preamble: N/A Method: The tester sends 2225Hz to TUT for 5 seconds. - Pass criteria: The TUT should respond with 1270Hz after 1±0.2 seconds. + Pass criteria: The TUT should respond with 1270Hz after 1+-0.2 seconds. Comments: The TUT should indicate that Bell 103 mode has been selected. Bell 103 modems use 2225Hz as both answer tone and higher frequency of the upper channel. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1137,14 +5244,92 @@ static int test_ans_18(void) static int test_ans_19(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.19 V.21 Reverse mode (1650Hz) detection Purpose: To ensure correct detection and selection of V.21 reverse mode. Preamble: N/A Method: The tester sends 1650Hz to TUT for 5 seconds. - Pass criteria: The TUT should respond with 980Hz after 0.4±0.2 seconds. + Pass criteria: The TUT should respond with 980Hz after 0.4+-0.2 seconds. Comments: The TUT should indicate that V.21 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1152,6 +5337,17 @@ static int test_ans_19(void) static int test_ans_20(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.20 1300Hz calling tone discrimination Purpose: To confirm correct detection of 1300Hz calling tones as defined in ITU-T V.25. @@ -1163,6 +5359,73 @@ static int test_ans_20(void) 700 ms followed by 1 second of silence. Comments: The probe sent by the TUT will depend on the country setting. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1170,14 +5433,92 @@ static int test_ans_20(void) static int test_ans_21(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.21 V.23 Reverse mode (1300Hz) detection Purpose: To ensure correct detection and selection of V.23 reverse mode. Preamble: N/A Method: The tester sends 1300Hz only, with no XCI signals, to TUT for 5 seconds. - Pass criteria: The TUT should respond with 390Hz after 1.7±0.1 seconds. + Pass criteria: The TUT should respond with 390Hz after 1.7+-0.1 seconds. Comments: The TUT should indicate that V.23 mode has been selected. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1185,6 +5526,17 @@ static int test_ans_21(void) static int test_ans_22(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.22 1300Hz with XCI test Purpose: To ensure correct detection of the XCI signal and selection of V.18 mode. @@ -1193,6 +5545,73 @@ static int test_ans_22(void) silent for 500 ms then transmit the TXP signal in V.21 (1) mode. Pass criteria: The TUT should respond with TXP using V.21 (2) and select V.18 mode. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1200,6 +5619,17 @@ static int test_ans_22(void) static int test_ans_23(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.23 Stimulate mode country settings Purpose: To ensure that the TUT steps through the probes in the specified order for the @@ -1211,6 +5641,73 @@ static int test_ans_23(void) Pass criteria: The TUT should use the orders described in Appendix I. Comments: The order of the probes is not mandatory. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1218,6 +5715,17 @@ static int test_ans_23(void) static int test_ans_24(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.24 Stimulate carrierless mode probe message Purpose: To ensure that the TUT sends the correct probe message for each of the carrierless @@ -1229,6 +5737,73 @@ static int test_ans_24(void) modes followed by a pause of Tm (default 3) seconds. Comments: The carrierless modes are those described in Annexes A, B and C. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1236,6 +5811,17 @@ static int test_ans_24(void) static int test_ans_25(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.25 Interrupted carrierless mode probe Purpose: To ensure that the TUT continues probing from the point of interruption a maximum @@ -1247,6 +5833,73 @@ static int test_ans_25(void) Pass criteria: The TUT should transmit silence on detecting the 1270Hz tone and then continue probing starting with the V.23 probe 20 seconds after the end of the 1270Hz signal. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1254,6 +5907,17 @@ static int test_ans_25(void) static int test_ans_26(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.26 Stimulate carrier mode probe time Purpose: To ensure that the TUT sends each carrier mode for time Tc (default 6 seconds) @@ -1262,9 +5926,76 @@ static int test_ans_26(void) Method: The tester will call the TUT, wait for Ta to expire and then monitor the probes sent by the TUT. Pass criteria: The TUT should send the ANS tone (2100Hz) for 1 second followed by silence for - 75±5 ms and then the 1650Hz, 1300Hz and 2225Hz probes for time Tc. + 75+-5 ms and then the 1650Hz, 1300Hz and 2225Hz probes for time Tc. Comments: The carrier modes are those described in Annexes D, E, and F. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1272,6 +6003,17 @@ static int test_ans_26(void) static int test_ans_27(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.27 V.23 mode (390Hz) detection Purpose: To confirm correct selection of V.23 mode. @@ -1287,6 +6029,73 @@ static int test_ans_27(void) 390Hz. When the 1300Hz probe is not being transmitted, a 390Hz tone may be interpreted as a 400Hz network tone. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1294,6 +6103,17 @@ static int test_ans_27(void) static int test_ans_28(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.28 Interrupted carrier mode probe Purpose: To ensure that the TUT continues probing from the point of interruption a maximum @@ -1307,6 +6127,73 @@ static int test_ans_28(void) Comments: It is most likely that the TUT will return to probing time Ta (3 seconds) after the 1270Hz tone ceases. This condition needs further clarification. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1314,6 +6201,17 @@ static int test_ans_28(void) static int test_ans_29(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.29 Stimulate mode response during probe Purpose: To ensure that the TUT is able to detect an incoming signal while transmitting a @@ -1326,6 +6224,73 @@ static int test_ans_29(void) Comments: The TUT may not respond to any signals while a carrierless mode probe is being sent since these modes are half duplex. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1333,6 +6298,17 @@ static int test_ans_29(void) static int test_ans_30(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.30 Immunity to network tones Purpose: To ensure that the TUT does not interpret network tones as valid signals. @@ -1347,6 +6323,73 @@ static int test_ans_30(void) tones may be ignored. Some devices may only provide a visual indication of the presence and cadence of the tones for instance by a flashing light. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1354,6 +6397,17 @@ static int test_ans_30(void) static int test_ans_31(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.31 Immunity to fax calling tones Purpose: To determine whether the TUT can discriminate fax calling tones. @@ -1365,6 +6419,73 @@ static int test_ans_31(void) Comments: This is an optional test as detection of the fax calling tone is not required by ITU-T V.18. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1372,6 +6493,17 @@ static int test_ans_31(void) static int test_ans_32(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.32 Immunity to voice Purpose: To ensure that the TUT does not misinterpret speech as a valid textphone signal. @@ -1383,6 +6515,73 @@ static int test_ans_32(void) Comments: Ideally the TUT should report the presence of speech back to the user. This is an optional test. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1390,6 +6589,17 @@ static int test_ans_32(void) static int test_ans_33(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.3.33 CM detection and V.8 answering Purpose: To confirm that the TUT will respond correctly to CM signals and connect @@ -1406,6 +6616,73 @@ static int test_ans_33(void) V.18 mode connection is completed. Comments: The TUT should indicate V.18 mode. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1420,6 +6697,17 @@ static int test_mon_01(void) static int test_mon_21(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.4.1 Automode monitor Ta timer test Purpose: To ensure that on entering monitor mode, timer Ta (3 seconds) is not active and that @@ -1429,6 +6717,73 @@ static int test_mon_21(void) for 1 minute. Pass criteria: The TUT should not start probing. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1436,6 +6791,17 @@ static int test_mon_21(void) static int test_mon_22(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.4.2 Automode monitor 1300Hz calling tone discrimination Purpose: To confirm correct detection and reporting of 1300Hz calling tones as defined in @@ -1449,6 +6815,73 @@ static int test_mon_22(void) Comments: In automode answer, the 1300Hz calling causes the DCE to start probing. In monitor mode it should only report detection to the DTE. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1456,6 +6889,17 @@ static int test_mon_22(void) static int test_mon_23(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.4.3 Automode monitor 980Hz calling tone discrimination Purpose: To confirm correct detection and reporting of 980Hz calling tones as defined in @@ -1469,13 +6913,101 @@ static int test_mon_23(void) Comments: In automode answer, the 980Hz calling causes the DCE to start probing. In monitor mode it should only report detection to the DTE. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } /*- End of function --------------------------------------------------------*/ +static void x_01_put_text_msg(void *user_data, const uint8_t *msg, int len) +{ +printf("1-1 %d '%s'\n", len, msg); + if (user_data == NULL) + strcat(result, (const char *) msg); + else + v18_put(v18[1], "abcdefghij", 10); +} +/*- End of function --------------------------------------------------------*/ + static int test_x_01(void) { + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + const char *ref; + /* III.5.4.5.1 Baudot carrier timing and receiver disabling Purpose: To verify that the TUT sends unmodulated carrier for 150 ms before a new character @@ -1490,13 +7022,96 @@ static int test_x_01(void) 3) The tester will confirm that 1 start bit and at least 1.5 stop bits are used. Comments: The carrier should be maintained during the 300 ms after a character. */ - printf("Test not yet implemented\n"); + v18[0] = v18_init(NULL, TRUE, V18_MODE_5BIT_45, x_01_put_text_msg, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_5BIT_45, x_01_put_text_msg, (void *) (intptr_t) 1); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + v18_put(v18[0], "z", 1); + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); + ref = "cdefghij"; + printf("Result:\n%s\n", result); + printf("Reference result:\n%s\n", ref); + if (unexpected_echo || strcmp(result, ref) != 0) + return -1; return 1; } /*- End of function --------------------------------------------------------*/ static int test_x_02(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.2 Baudot bit rate confirmation Purpose: To verify that the TUT uses the correct bit rates in the Baudot mode. @@ -1506,6 +7121,73 @@ static int test_x_02(void) transmit the string "abcdef" at each rate. Pass criteria: The tester will measure the bit timings and confirm the rates. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_5BIT_45, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_5BIT_45, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } @@ -1513,6 +7195,17 @@ static int test_x_02(void) static int test_x_03(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.3 Baudot probe bit rate confirmation Purpose: To verify that the TUT uses the correct bit rates in the Baudot mode probe during @@ -1525,21 +7218,104 @@ static int test_x_03(void) Comments: The probe message must be long enough for the tester to establish the bit rate. "GA" may not be sufficient. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_5BIT_45, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_5BIT_45, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 1; } /*- End of function --------------------------------------------------------*/ +static void x_04_put_echo_text_msg(void *user_data, const uint8_t *msg, int len) +{ + printf("Unexpected ECHO received (%d) '%s'\n", len, msg); + unexpected_echo = TRUE; +} +/*- End of function --------------------------------------------------------*/ + +static void x_04_put_text_msg(void *user_data, const uint8_t *msg, int len) +{ +printf("1-1 %d '%s'\n", len, msg); + strcat(result, (const char *) msg); +} +/*- End of function --------------------------------------------------------*/ + static int test_x_04(void) { - char result[1024]; - char *t; - int ch; - int xx; - int yy; - int i; - v18_state_t *v18_state; + char msg[1024]; + v18_state_t *v18[2]; logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int i; + int j; /* III.5.4.5.4 5 Bit to T.50 character conversion @@ -1560,43 +7336,109 @@ static int test_x_04(void) assumed that the character conversion is the same for Baudot at 50 bit/s and any other supported speed. */ - v18_state = v18_init(NULL, TRUE, V18_MODE_5BIT_45, NULL, NULL); - logging = v18_get_logging_state(v18_state); + v18[0] = v18_init(NULL, TRUE, V18_MODE_5BIT_45, x_04_put_echo_text_msg, NULL); + logging = v18_get_logging_state(v18[0]); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); - span_log_set_tag(logging, ""); - printf("Original:\n"); - t = result; - for (i = 0; i < 127; i++) + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_5BIT_45, x_04_put_text_msg, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) { - ch = i; - printf("%c", ch); - xx = v18_encode_baudot(v18_state, ch); - if (xx) - { - if ((xx & 0x3E0)) - { - yy = v18_decode_baudot(v18_state, (xx >> 5) & 0x1F); - if (yy) - *t++ = yy; - } - yy = v18_decode_baudot(v18_state, xx & 0x1F); - if (yy) - *t++ = yy; - } + fprintf(stderr, " Failed to create line model\n"); + exit(2); } - printf("\n"); - *t = '\0'; - v18_free(v18_state); + + result[0] = '\0'; + unexpected_echo = FALSE; + for (i = 0; i < 127; i++) + msg[i] = i + 1; + msg[127] = '\0'; + v18_put(v18[0], msg, 127); + + for (i = 0; i < 1000; i++) + { + for (j = 0; j < 2; j++) + { + samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK); + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Result:\n%s\n", result); printf("Reference result:\n%s\n", full_baudot_rx); - if (strcmp(result, full_baudot_rx) != 0) + if (unexpected_echo || strcmp(result, full_baudot_rx) != 0) return -1; return 0; } /*- End of function --------------------------------------------------------*/ +static void x_05_put_text_msg(void *user_data, const uint8_t *msg, int len) +{ + if (user_data == NULL) + strcat(result, (const char *) msg); + else + v18_put(v18[1], "behknqtwz", 9); +} +/*- End of function --------------------------------------------------------*/ + static int test_x_05(void) { + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + const char *ref; + /* III.5.4.5.5 DTMF receiver disabling Purpose: To verify that the TUT disables its DTMF receiver for 300 ms when a character is @@ -1608,18 +7450,106 @@ static int test_x_05(void) display will show when its receiver is re-enabled. Pass criteria: The receiver should be re-enabled after 300 ms. */ - printf("Test not yet implemented\n"); + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, x_05_put_text_msg, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, x_05_put_text_msg, (void *) (intptr_t) 1); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + result[0] = '\0'; + v18_put(v18[0], "e", 1); + + for (i = 0; i < 1000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); + ref = "knqtwz"; + printf("Result:\n%s\n", result); + printf("Reference result:\n%s\n", ref); + if (strcmp(result, ref) != 0) + return -1; return 0; } /*- End of function --------------------------------------------------------*/ +static void x_06_put_text_msg(void *user_data, const uint8_t *msg, int len) +{ + strcat(result, (const char *) msg); +} +/*- End of function --------------------------------------------------------*/ + static int test_x_06(void) { char msg[128]; char dtmf[1024]; - char result[1024]; const char *ref; + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; int i; + int j; /* III.5.4.5.6 DTMF character conversion @@ -1635,22 +7565,89 @@ static int test_x_06(void) receiving character from the TUT. It is assumed that the echo delay in the test system is negligible. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, x_06_put_text_msg, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + result[0] = '\0'; for (i = 0; i < 127; i++) msg[i] = i + 1; msg[127] = '\0'; - printf("%s\n", msg); + printf("Original:\n%s\n", msg); v18_encode_dtmf(NULL, dtmf, msg); - printf("%s\n", dtmf); - + printf("DTMF:\n%s\n", dtmf); v18_decode_dtmf(NULL, result, dtmf); + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + ref = "\b \n\n\n?\n\n\n %+().+,-.0123456789:;(=)" "?XABCDEFGHIJKLMNOPQRSTUVWXYZ\xC6\xD8\xC5" " abcdefghijklmnopqrstuvwxyz\xE6\xF8\xE5 \b"; printf("Result:\n%s\n", result); printf("Reference result:\n%s\n", ref); + v18_free(v18[0]); + v18_free(v18[1]); if (strcmp(result, ref) != 0) return -1; return 0; @@ -1659,6 +7656,17 @@ static int test_x_06(void) static int test_x_07(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.7 EDT carrier timing and receiver disabling Purpose: To verify that the TUT sends unmodulated carrier for 300 ms before a character and @@ -1673,6 +7681,73 @@ static int test_x_07(void) 3) The tester will confirm that 1 start bit and at least 1.5 stop bits are used. Comments: The carrier should be maintained during the 300 ms after a character. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 0; } @@ -1680,6 +7755,17 @@ static int test_x_07(void) static int test_x_08(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.8 EDT bit rate and character structure Purpose: To verify that the TUT uses the correct bit rate and character structure in the EDT @@ -1690,6 +7776,73 @@ static int test_x_08(void) 2) The tester should confirm that 1 start bit, 7 data bits, 1 even parity bit and 2 stop bits are used. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 0; } @@ -1697,6 +7850,17 @@ static int test_x_08(void) static int test_x_09(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.9 V.23 calling mode character format Purpose: To verify that the TUT uses the correct character format in the V.23 calling mode. @@ -1710,6 +7874,73 @@ static int test_x_09(void) that there are no duplicate characters on the TUT display. 3) The received string should be correctly displayed despite the incorrect parity. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 0; } @@ -1717,6 +7948,17 @@ static int test_x_09(void) static int test_x_10(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.10 V.23 answer mode character format Purpose: To verify that the TUT uses the correct character format in the V.23 answer mode. @@ -1733,6 +7975,73 @@ static int test_x_10(void) Comments: This test is only applicable to Minitel Dialogue terminals. Prestel and Minitel Normal terminals cannot operate in this mode. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 0; } @@ -1740,6 +8049,17 @@ static int test_x_10(void) static int test_x_11(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.11 V.21 character structure Purpose: To verify that the TUT uses the character structure in the V.21 mode. @@ -1754,6 +8074,73 @@ static int test_x_11(void) 4) The last five characters on the TUT display should be "12345" (no "6") correctly displayed despite the incorrect parity. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 0; } @@ -1761,6 +8148,17 @@ static int test_x_11(void) static int test_x_12(void) { + v18_state_t *v18[2]; + logging_state_t *logging; + int16_t amp[2][SAMPLES_PER_CHUNK]; + int16_t model_amp[2][SAMPLES_PER_CHUNK]; + int16_t out_amp[2*SAMPLES_PER_CHUNK]; + int outframes; + int samples; + int push; + int i; + int j; + /* III.5.4.5.12 V.18 mode Purpose: To verify that the TUT uses the protocol defined in ITU-T T.140. @@ -1772,6 +8170,73 @@ static int test_x_12(void) Pass criteria: The tester should confirm UTF8 encoded UNICODE characters are used with the controls specified in ITU-T T.140. */ + v18[0] = v18_init(NULL, TRUE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[0]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "A"); + v18[1] = v18_init(NULL, FALSE, V18_MODE_DTMF, NULL, NULL); + logging = v18_get_logging_state(v18[1]); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "B"); + + if ((model = both_ways_line_model_init(line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + line_model_no, + (float) noise_level, + -15.0f, + -15.0f, + channel_codec, + rbs_pattern)) == NULL) + { + fprintf(stderr, " Failed to create line model\n"); + exit(2); + } + + for (i = 0; i < 10000; i++) + { + for (j = 0; j < 2; j++) + { + if ((samples = v18_tx(v18[j], amp[j], SAMPLES_PER_CHUNK)) == 0) + push = 10; + if (samples < SAMPLES_PER_CHUNK) + { + vec_zeroi16(&[j][samples], SAMPLES_PER_CHUNK - samples); + samples = SAMPLES_PER_CHUNK; + } + } + if (log_audio) + { + for (j = 0; j < samples; j++) + { + out_amp[2*j + 0] = amp[0][j]; + out_amp[2*j + 1] = amp[1][j]; + } + outframes = sf_writef_short(outhandle, out_amp, samples); + if (outframes != samples) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } + } +#if 1 + both_ways_line_model(model, + model_amp[0], + amp[0], + model_amp[1], + amp[1], + samples); +#else + vec_copyi16(model_amp[0], amp[0], samples); + vec_copyi16(model_amp[1], amp[1], samples); +#endif + v18_rx(v18[0], model_amp[1], samples); + v18_rx(v18[1], model_amp[0], samples); + } + + v18_free(v18[0]); + v18_free(v18[1]); printf("Test not yet implemented\n"); return 0; } @@ -1829,7 +8294,7 @@ const struct } test_list[] = { {"III.3.2.1 Operational requirements tests", NULL}, - {"MISC-01 4 (1) No Disconnection Test", test_misc_01}, + {"MISC-01 4 (1) No disconnection test", test_misc_01}, {"MISC-02 4 (2) Automatic resumption of automoding", test_misc_02}, {"MISC-03 4 (2) Retention of selected mode on loss of signal", test_misc_03}, {"MISC-04 4 (4) Detection of BUSY tone", test_misc_04}, @@ -1837,81 +8302,81 @@ const struct {"MISC-06 4 (4) LOSS OF CARRIER indication", test_misc_06}, {"MISC-07 4 (4) Call progress indication", test_misc_07}, {"MISC-08 4 (5) Circuit 135 test", test_misc_08}, - {"MISC-09 4 (6) Connection Procedures", test_misc_09}, + {"MISC-09 4 (6) Connection procedures", test_misc_09}, {"III.3.2.2 Automode originate tests", NULL}, - {"ORG-01 5.1.1 CI & XCI Signal coding and cadence", test_org_01}, - {"ORG-02 5.1.3 ANS Signal Detection", test_org_02}, + {"ORG-01 5.1.1 CI & XCI signal coding and cadence", test_org_01}, + {"ORG-02 5.1.3 ANS signal detection", test_org_02}, {"ORG-03 5.2.3.1 End of ANS signal detection", test_org_03}, {"ORG-04 5.1.3.2 ANS tone followed by TXP", test_org_04}, {"ORG-05 5.1.3.3 ANS tone followed by 1650Hz", test_org_05}, {"ORG-06 5.1.3.4 ANS tone followed by 1300Hz", test_org_06}, {"ORG-07 5.1.3 ANS tone followed by no tone", test_org_07}, - {"ORG-08 5.1.4 Bell 103 (2225Hz Signal) Detection", test_org_08}, - {"ORG-09 5.1.5 V.21 (1650Hz Signal) Detection", test_org_09}, - {"ORG-10 5.1.6 V.23 (1300Hz Signal) Detection", test_org_10}, - {"ORG-11 5.1.7 V.23 (390Hz Signal) Detection", test_org_11}, - {"ORG-12a to d 5.1.8 5 Bit Mode (Baudot) Detection Tests", test_org_12}, + {"ORG-08 5.1.4 Bell 103 (2225Hz signal) detection", test_org_08}, + {"ORG-09 5.1.5 V.21 (1650Hz signal) detection", test_org_09}, + {"ORG-10 5.1.6 V.23 (1300Hz signal) detection", test_org_10}, + {"ORG-11 5.1.7 V.23 (390Hz signal) detection", test_org_11}, + {"ORG-12a to d 5.1.8 5 Bit Mode (baudot) detection Tests", test_org_12}, {"ORG-13 5.1.9 DTMF signal detection", test_org_13}, - {"ORG-14 5.1.10 EDT Rate Detection", test_org_14}, - {"ORG-15 5.1.10.1 Rate Detection Test", test_org_15}, - {"ORG-16 5.1.10.2 980Hz Detection", test_org_16}, + {"ORG-14 5.1.10 EDT rate detection", test_org_14}, + {"ORG-15 5.1.10.1 Rate detection test", test_org_15}, + {"ORG-16 5.1.10.2 980Hz detection", test_org_16}, {"ORG-17 5.1.10.3 Loss of signal after 980Hz", test_org_17}, {"ORG-18 5.1.10.3 Tr Timer", test_org_18}, - {"ORG-19 5.1.11 Bell 103 (1270Hz Signal) Detection", test_org_19}, - {"ORG-20 Immunity to Network Tones", test_org_20}, + {"ORG-19 5.1.11 Bell 103 (1270Hz signal) detection", test_org_19}, + {"ORG-20 Immunity to network tones", test_org_20}, {"ORG-21a to b Immunity to other non-textphone modems", test_org_21}, - {"ORG-22 Immunity to Fax Tones", test_org_22}, - {"ORG-23 Immunity to Voice", test_org_23}, + {"ORG-22 Immunity to Fax tones", test_org_22}, + {"ORG-23 Immunity to voice", test_org_23}, {"ORG-24 5.1.2 ANSam detection", test_org_24}, {"ORG-25 6.1 V.8 originate call", test_org_25}, {"III.3.2.3 Automode answer tests", NULL}, {"ANS-01 5.2.1 Ta timer", test_ans_01}, - {"ANS-02 5.2.2 CI Signal Detection", test_ans_02}, - {"ANS-03 5.2.2.1 Early Termination of ANS tone", test_ans_03}, + {"ANS-02 5.2.2 CI signal detection", test_ans_02}, + {"ANS-03 5.2.2.1 Early termination of ANS tone", test_ans_03}, {"ANS-04 5.2.2.2 Tt Timer", test_ans_04}, {"ANS-05 5.2.3.2 ANS tone followed by 980Hz", test_ans_05}, {"ANS-06 5.2.3.2 ANS tone followed by 1300Hz", test_ans_06}, {"ANS-07 5.2.3.3 ANS tone followed by 1650Hz", test_ans_07}, {"ANS-08 5.2.4.1 980Hz followed by 1650Hz", test_ans_08}, {"ANS-09a to d 5.2.4.2 980Hz calling tone detection", test_ans_09}, - {"ANS-10 5.2.4.3 V.21 Detection by Timer", test_ans_10}, - {"ANS-11 5.2.4.4.1 EDT Detection by Rate", test_ans_11}, - {"ANS-12 5.2.4.4.2 V.21 Detection by Rate", test_ans_12}, + {"ANS-10 5.2.4.3 V.21 detection by timer", test_ans_10}, + {"ANS-11 5.2.4.4.1 EDT detection by rate", test_ans_11}, + {"ANS-12 5.2.4.4.2 V.21 detection by rate", test_ans_12}, {"ANS-13 5.2.4.4.3 Tr Timer", test_ans_13}, {"ANS-14 5.2.4.5 Te Timer", test_ans_14}, - {"ANS-15a to d 5.2.5 5 Bit Mode (Baudot) Detection Tests", test_ans_15}, - {"ANS-16 5.2.6 DTMF Signal Detection", test_ans_16}, + {"ANS-15a to d 5.2.5 5 bit mode (Baudot) detection tests", test_ans_15}, + {"ANS-16 5.2.6 DTMF signal detection", test_ans_16}, {"ANS-17 5.2.7 Bell 103 (1270Hz signal) detection", test_ans_17}, {"ANS-18 5.2.8 Bell 103 (2225Hz signal) detection", test_ans_18}, - {"ANS-19 5.2.9 V.21 Reverse Mode (1650Hz) Detection", test_ans_19}, - {"ANS-20a to d 5.2.10 1300Hz Calling Tone Discrimination", test_ans_20}, - {"ANS-21 5.2.11 V.23 Reverse Mode (1300Hz) Detection", test_ans_21}, + {"ANS-19 5.2.9 V.21 reverse mode (1650Hz) detection", test_ans_19}, + {"ANS-20a to d 5.2.10 1300Hz calling tone discrimination", test_ans_20}, + {"ANS-21 5.2.11 V.23 reverse mode (1300Hz) detection", test_ans_21}, {"ANS-22 1300Hz with XCI Test", test_ans_22}, - {"ANS-23 5.2.12 Stimulate Mode Country Settings", test_ans_23}, - {"ANS-24 5.2.12.1 Stimulate Carrierless Mode Probe Message", test_ans_24}, - {"ANS-25 5.2.12.1.1 Interrupted Carrierless Mode Probe", test_ans_25}, - {"ANS-26 5.2.12.2 Stimulate Carrier Mode Probe Time", test_ans_26}, - {"ANS-27 5.2.12.2.1 V.23 Mode (390Hz) Detection", test_ans_27}, - {"ANS-28 5.2.12.2.2 Interrupted Carrier Mode Probe", test_ans_28}, - {"ANS-29 5.2.12.2.2 Stimulate Mode Response During Probe", test_ans_29}, - {"ANS-30 Immunity to Network Tones", test_ans_30}, - {"ANS-31 Immunity to Fax Calling Tones", test_ans_31}, - {"ANS-32 Immunity to Voice", test_ans_32}, - {"ANS-33 5.2.2.1 V.8 CM detection and V.8 Answering", test_ans_33}, + {"ANS-23 5.2.12 Stimulate mode country settings", test_ans_23}, + {"ANS-24 5.2.12.1 Stimulate carrierless mode probe message", test_ans_24}, + {"ANS-25 5.2.12.1.1 Interrupted carrierless mode probe", test_ans_25}, + {"ANS-26 5.2.12.2 Stimulate carrier mode probe time", test_ans_26}, + {"ANS-27 5.2.12.2.1 V.23 mode (390Hz) detection", test_ans_27}, + {"ANS-28 5.2.12.2.2 Interrupted carrier mode probe", test_ans_28}, + {"ANS-29 5.2.12.2.2 Stimulate mode response during probe", test_ans_29}, + {"ANS-30 Immunity to network tones", test_ans_30}, + {"ANS-31 Immunity to Fax calling tones", test_ans_31}, + {"ANS-32 Immunity to voice", test_ans_32}, + {"ANS-33 5.2.2.1 V.8 CM detection and V.8 answering", test_ans_33}, {"III.3.2.4 Automode monitor tests", NULL}, {"MON-01 to -20 5.3 Repeat all answer mode tests excluding tests ANS-01, ANS-20 and ANS-23 to ANS-29", test_mon_01}, - {"MON-21 5.3 Automode Monitor Ta timer", test_mon_21}, - {"MON-22a to d 5.3 Automode Monitor 1300Hz Calling Tone Discrimination", test_mon_22}, - {"MON-23a to d 5.3 Automode Monitor 980Hz Calling Tone Discrimination", test_mon_23}, + {"MON-21 5.3 Automode monitor Ta timer", test_mon_21}, + {"MON-22a to d 5.3 Automode monitor 1300Hz calling tone discrimination", test_mon_22}, + {"MON-23a to d 5.3 Automode monitor 980Hz calling tone discrimination", test_mon_23}, {"III.3.2.5 ITU-T V.18 annexes tests", NULL}, {"X-01 A.1 Baudot carrier timing and receiver disabling", test_x_01}, {"X-02 A.2 Baudot bit rate confirmation", test_x_02}, {"X-03 A.3 Baudot probe bit rate confirmation", test_x_03}, - {"X-04 A.4 5 Bit to T.50 Character Conversion", test_x_04}, + {"X-04 A.4 5 Bit to T.50 character conversion", test_x_04}, {"X-05 B.1 DTMF receiver disabling", test_x_05}, {"X-06 B.2 DTMF character conversion", test_x_06}, {"X-07 C.1 EDT carrier timing and receiver disabling", test_x_07}, @@ -1967,7 +8432,7 @@ int main(int argc, char *argv[]) outhandle = NULL; if (log_audio) { - if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 1)) == NULL) + if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME); exit(2); diff --git a/libs/spandsp/tests/v22bis_tests.c b/libs/spandsp/tests/v22bis_tests.c index 82722e2556..aade32c726 100644 --- a/libs/spandsp/tests/v22bis_tests.c +++ b/libs/spandsp/tests/v22bis_tests.c @@ -373,7 +373,6 @@ int main(int argc, char *argv[]) bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]); } - #if defined(ENABLE_GUI) if (use_gui) { From 92308bf6e1a466cfe32609b4229b30334d36763f Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 14 Mar 2013 10:04:09 -0500 Subject: [PATCH 026/113] windows fix for last spandsp commit - coppice please have a look --- libs/spandsp/src/msvc/spandsp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/spandsp/src/msvc/spandsp.h b/libs/spandsp/src/msvc/spandsp.h index 806c9ce920..31e0affc1c 100644 --- a/libs/spandsp/src/msvc/spandsp.h +++ b/libs/spandsp/src/msvc/spandsp.h @@ -98,7 +98,7 @@ #include #include #include -#include +/*#include not sure why this is here I cant find it in the filesystem */ #include #include #include From 9d06412382e0b949cef6869313ef8b35008e3423 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 14 Mar 2013 08:49:41 -0500 Subject: [PATCH 027/113] FS-5172 --resolve --- libs/iksemel/src/sax.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libs/iksemel/src/sax.c b/libs/iksemel/src/sax.c index be534a5038..338a5cf7f9 100644 --- a/libs/iksemel/src/sax.c +++ b/libs/iksemel/src/sax.c @@ -566,6 +566,13 @@ sax_core (iksparser *prs, char *buf, int len) if ('>' == c) { old = pos + 1; prs->context = C_CDATA; + } else if (']' == c) { + /* ]]] scenario */ + if (prs->cdataHook) { + err = prs->cdataHook (prs->user_data, "]", 1); + if (IKS_OK != err) return err; + } + old = pos; } else { if (prs->cdataHook) { err = prs->cdataHook (prs->user_data, "]]", 2); From f2a260d81fb2736bd6f6f3e768087c9ccff94123 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 14 Mar 2013 10:58:17 -0500 Subject: [PATCH 028/113] FS-5171 Please try this. Get a similar trace and if you can, compare it to the trace without the SBC in place. --- src/mod/endpoints/mod_sofia/sofia_presence.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index f49b138566..09f6fcc801 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -3530,6 +3530,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, const char *contact_port = NULL; sofia_nat_parse_t np = { { 0 } }; int found_proto = 0; + const char *use_to_tag; char to_tag[13] = ""; char buf[32] = ""; int subbed = 0; @@ -3547,7 +3548,12 @@ void sofia_presence_handle_sip_i_subscribe(int status, return; } - switch_stun_random_string(to_tag, 12, NULL); + if (sip->sip_to && sip->sip_to->a_tag) { + use_to_tag = sip->sip_to->a_tag; + } else { + switch_stun_random_string(to_tag, 12, NULL); + use_to_tag = to_tag; + } if ( sip->sip_contact && sip->sip_contact->m_url ) { contact_host = sip->sip_contact->m_url->url_host; @@ -3711,7 +3717,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, event, contact_str, call_id, full_from, full_via, (long) switch_epoch_time_now(NULL) + exp_delta, full_agent, accept, profile->name, mod_sofia_globals.hostname, - np.network_port, np.network_ip, orig_proto, full_to, to_tag); + np.network_port, np.network_ip, orig_proto, full_to, use_to_tag); switch_assert(sql != NULL); @@ -3819,7 +3825,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, } } - sip_to_tag(nh->nh_home, sip->sip_to, to_tag); + sip_to_tag(nh->nh_home, sip->sip_to, use_to_tag); if (mod_sofia_globals.debug_presence > 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Responding to SUBSCRIBE with 202 Accepted\n"); From 43e8fb6be41e7e562984241bd78756d91485678c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 14 Mar 2013 11:06:02 -0500 Subject: [PATCH 029/113] FS-5176 --resolve --- src/mod/endpoints/mod_sofia/sofia_reg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 952c9b5774..b845395994 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -2503,10 +2503,10 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, } if (switch_xml_locate_user_merged("id", zstr(username) ? "nobody" : username, domain_name, ip, &user, params) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n" + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find user [%s@%s] from %s\n" "You must define a domain called '%s' in your directory and add a user with the id=\"%s\" attribute\n" "and you must configure your device to use the proper domain in it's authentication credentials.\n", username, domain_name, - domain_name, username); + ip, domain_name, username); ret = AUTH_FORBIDDEN; goto end; From 8523f22578177b394f47effc84362a094354241c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 14 Mar 2013 13:35:42 -0500 Subject: [PATCH 030/113] fix shutdown race in queue managers --- src/switch_core_sqldb.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 1b607910c3..4df6561113 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1409,16 +1409,22 @@ SWITCH_DECLARE(int) switch_sql_queue_manager_size(switch_sql_queue_manager_t *qm SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_stop(switch_sql_queue_manager_t *qm) { switch_status_t status = SWITCH_STATUS_FALSE; - uint32_t i; + uint32_t i, sanity = 100; - if (qm->thread_running) { - qm->thread_running = 0; + if (qm->thread_running == 1) { + qm->thread_running = -1; - for(i = 0; i < qm->numq; i++) { - switch_queue_push(qm->sql_queue[i], NULL); - switch_queue_interrupt_all(qm->sql_queue[i]); + while(--sanity && qm->thread_running == -1) { + for(i = 0; i < qm->numq; i++) { + switch_queue_push(qm->sql_queue[i], NULL); + switch_queue_interrupt_all(qm->sql_queue[i]); + } + qm_wake(qm); + + if (qm->thread_running == -1) { + switch_yield(100000); + } } - qm_wake(qm); status = SWITCH_STATUS_SUCCESS; } @@ -1498,13 +1504,14 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_destroy(switch_sql_queu SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_push(switch_sql_queue_manager_t *qm, const char *sql, uint32_t pos, switch_bool_t dup) { - if (sql_manager.paused) { + if (sql_manager.paused || qm->thread_running != 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "DROP [%s]\n", sql); if (!dup) free((char *)sql); qm_wake(qm); return SWITCH_STATUS_SUCCESS; } - if (!qm->thread_running) { + if (qm->thread_running != 1) { if (!dup) free((char *)sql); return SWITCH_STATUS_FALSE; } @@ -1529,6 +1536,13 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_push_confirm(switch_sql #ifdef EXEC_NOW switch_cache_db_handle_t *dbh; + if (sql_manager.paused || qm->thread_running != 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "DROP [%s]\n", sql); + if (!dup) free((char *)sql); + qm_wake(qm); + return SWITCH_STATUS_SUCCESS; + } + if (switch_cache_db_get_db_handle_dsn(&dbh, qm->dsn) == SWITCH_STATUS_SUCCESS) { switch_cache_db_execute_sql(dbh, (char *)sql, NULL); switch_cache_db_release_db_handle(&dbh); @@ -1547,7 +1561,7 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_push_confirm(switch_sql return SWITCH_STATUS_SUCCESS; } - if (!qm->thread_running) { + if (qm->thread_running != 1) { if (!dup) free((char *)sql); return SWITCH_STATUS_FALSE; } @@ -1889,9 +1903,9 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, do_flush(qm, i, qm->event_db); } - qm->thread_running = 0; - switch_cache_db_release_db_handle(&qm->event_db); + + qm->thread_running = 0; return NULL; } From 84709b8b610f71aec4afec8f38f3cbcd813c01ec Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 14 Mar 2013 15:18:51 -0500 Subject: [PATCH 031/113] FS-5180 --resolve --- src/mod/endpoints/mod_skinny/skinny_server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 652b7954c6..1637d151a2 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -524,6 +524,7 @@ int skinny_ring_lines_callback(void *pArg, int argc, char **argv, char **columnN device_name, device_instance, &listener); if(listener) { switch_channel_t *channel = switch_core_session_get_channel(helper->tech_pvt->session); + switch_channel_t *remchannel = switch_core_session_get_channel(helper->remote_session); helper->lines_count++; switch_channel_set_variable(channel, "effective_callee_id_number", value); switch_channel_set_variable(channel, "effective_callee_id_name", caller_name); @@ -554,7 +555,7 @@ int skinny_ring_lines_callback(void *pArg, int argc, char **argv, char **columnN skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance); send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_BLINK); send_set_ringer(listener, SKINNY_RING_INSIDE, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id); - switch_channel_mark_ring_ready(channel); + switch_channel_ring_ready(remchannel); } return 0; } From 69bd8edf419ecef8f2dccf437e3ba32d6fd71529 Mon Sep 17 00:00:00 2001 From: Di-Shi Sun Date: Fri, 15 Mar 2013 08:32:02 +0000 Subject: [PATCH 032/113] Rewrote mod_osp module and updated documentation. --- src/mod/applications/mod_osp/docs/mod_osp.txt | 354 +- src/mod/applications/mod_osp/mod_osp.c | 3796 +++++++++-------- 2 files changed, 2314 insertions(+), 1836 deletions(-) diff --git a/src/mod/applications/mod_osp/docs/mod_osp.txt b/src/mod/applications/mod_osp/docs/mod_osp.txt index a5686a4a03..a12e718740 100644 --- a/src/mod/applications/mod_osp/docs/mod_osp.txt +++ b/src/mod/applications/mod_osp/docs/mod_osp.txt @@ -1,84 +1,322 @@ FreeSWITCH Open Settlement Protocol (OSP) module -This module provides OSP based call authentication, authorization, routing lookup and call detail record (CDR) collection services using standard FreeSWITCH application and dailplan interfaces. +1 Introduction +FreeSWITCH OSP module provides OSP based call authentication, authorization, routing lookup and call detail record (CDR) collection services using standard FreeSWITCH application interface and state handlers. -The OSP module can be configured by the following parameters in osp.conf.xml: +2 Configuration Parameters +The OSP module can be configured by OSP module global parameters and OSP provider profile parameters in osp.conf.xml. -Global parameters: +2.1 Global Parameters +FreeSWITCH OSP module global configuration parameters can be set using the following format: - + Global parameter names and values can be: + - debug-info: Flag to show OSP module debug information. The default is "disabled". + - log-level: At which log level to show OSP module debug information. The default is "info". + - crypto-hardware: If to use hardware for OpenSSL. The default is "disabled". + - sip: Used SIP module and profile. The default is "sofia" and "external". + - h323: Used H.323 module and profile. The default is "h323" and "external". This option has not been implemented. + - iax: Used IAX2 module and profile. The default is "iax" and "external". This option has not been implemented. + - skype: Used Skype module and profile. The default is "skypopen" and "external". This option has not been implemented. + - default-protocol: The VoIP protocol for destinations with unknown/undefined protocol. The default is "sip". -debug-info: Flag to show OSP module debug information. The default is "disabled". -log-level: At which log level to show OSP module debug information. The default is "info". -crypto-hardware: If to use hardware for OpenSSL. The default is "disabled". -sip: Used SIP module and profile. The default is "sofia" and "external". -h323: Used H.323 module and profile. The default is "h323" and "external". This option has not been implemented. -iax: Used IAX2 module and profile. The default is "iax" and "external". This option has not been implemented. -skype: Used Skype module and profile. The default is "skypopen" and "external". This option has not been implemented. -default-protocol: The VoIP protocol for destinations with unknown/undefined protocol. The default is "sip". - -OSP provider parameters: +2.2 OSP Provider Parameters +FreeSWITCH OSP module OSP provider configuration parameters can be set using the following format: - - - + + + OSP provider parameter names ane values cab be: + - profile: OSP provider profile name. + - service-point-url: OSP service point URL. This parameter must be defined. Up to 8 URLs are allowed. + - device-ip: FreeSWITCH IP for OSP module. This parameter must be defined. + - ssl-lifetime: SSL lifetime. The default is 300 in seconds. + - http-max-connections: HTTP max connections. The default is 20. + - http-persistence: HTTP persistence. The default is 60 in seconds. + - http-retry-delay: HTTP retry delay. The default is 0 in seconds. + - http-retry-limit: HTTP retry times. The default is 2. + - http-timeout: HTTP timeout. The default is 10000 in ms. + - work-mode: OSP module work mode (direct and indirect). The default is "direct". + - service-type: OSP service type (voice and npquery). The default is "voice". + - max-destinations: Max destinations OSP server will return. It is up to 12. The default is 12. -profile: OSP provider profile name. -service-point-url: OSP service point URL. This parameter must be defined. Up to 8 URLs are allowed. -device-ip: FreeSWITCH IP for OSP module. This parameter must be defined. -ssl-lifetime: SSL lifetime. The default is 300 in seconds. -http-max-connections: HTTP max connections. The default is 20. -http-persistence: HTTP persistence. The default is 60 in seconds. -http-retry-delay: HTTP retry delay. The default is 0 in seconds. -http-retry-limit: HTTP retry times. The default is 2. -http-timeout: HTTP timeout. The default is 10000 in ms. -work-mode: OSP module work mode (direct and indirect). The default is "direct". -service-type: OSP service type (voice and npquery). The default is "voice". -max-destinations: Max destinations OSP server will return. It is up to 12. The default is 12. +3 OSP Applications +The OSP applications are called in dial plan like this: -The OSP application is called in dial plan like this: + and - +*PROFILE* is an OSP service provider profile name configured in osp.conf.xml. If data attribute is not provided or its value is empty, profile name "default" is used. -The OSP dialplan is called in dial plan like this: +3.1 OSPLookup Application +osplookup application does OSP authorization request and gets first supported destination for inbound calls. It exports a set channel variables for FreeSWITCH dial plan logic. +osplookup application accepts two sets of channel variables that are used to pass additional inbound call information and outbound control parameters to OSP module. It also exports a set of channel variables for outbound channels and FreeSWITCH dial plan logic. - +3.1.1 Inbound Call Information + - osp_source_device: Actual source device IP address channel variable. It is only for FreeSWITH OSP module running in indirect mode. + - osp_source_nid: Source device network ID channel variable. + - osp_custom_info_N: Up to 8 custom info channel variables. N is the index starting from 1. -For both OSP application and dialplan, the is an OSP service provider name configured in osp.conf.xml. If it is empty, profile "default" is used. +3.1.2 Outbound Control Parameters + - osp_networkid_userparam: The URI user parameter name that is used to present destination network ID. For example, sip:callednumber;networkid=dnid@host. + - osp_networkid_uriparam: The URI parameter name that is used to present destination network ID. For example, sip:callednumber @host;networkid=dnid. + - osp_user_phone: Flag to add "user=phone" URI parameter. The default is "disabled". + - osp_outbound_proxy: Outbound proxy IP address channel variable. -Both OSP application and dialplan accept a set of inbound channel variables that are used to pass additional call information to OSP module. These channel variables include: +3.1.3 Exported Parameters + - osp_profile_name: Used OSP provider profile name. It will be used by ospnext application and OSP module state handlers. + - osp_transaction_handle: OSP transaction handle. It will be used by ospnext application and OSP module state handlers. + - osp_transaction_id: OSP transaction ID. It will be used by ospnext application and OSP module state handlers for log purpose. + - osp_lookup_status: osplookup application status. It will be used by FreeSWITCH dial plan logic. 0 for no error. + - osp_route_total: Total number of destinations from OSP servers. It will be used by ospnext application and OSP module state handlers. + - osp_route_count: Destination index starting from 1. It will be used by ospnext application and OSP module state handlers. + - osp_auto_route: Bridge route string. It will be used by bridge application. + - osp_termiation_cause: Destination termination cause. It will be used by ospnext application and OSP module state handlers. -osp_source_device: Actual source device IP address channel variable. It is only for FreeSWITH OSP module running in indirect mode. -osp_source_nid: Source device network ID channel variable. -osp_custom_info_N: Up to 8 custom info channel variables. N is the index starting from 1. -osp_networkid_userparam: The URI user parameter name that is used to present destination network ID. -osp_networkid_uriparam: The URI parameter name that is used to present destination network ID. -osp_user_phone: Flag to add "user=phone" URI parameter. The default is "disabled". -osp_outbound_proxy: Outbound proxy IP address channel variable. +3.2 OSPNext Application +ospnext application gets next supported destination for inbound calls. It exports a set channel variables for FreeSWITCH dial plan logic. +ospnext application accepts a set of channel variables exported by osplookup application to pass OSP call transaction information to OSP module. It also exports a set of channel variables for outbound channels and FreeSWITCH dial plan logic. -Both OSP application and dialplan also export a set of channel variables for outbound channels and FreeSWITCH dial plan logic (for OSP dialplan, some exported channel variables are not visible for dial plan). These channel variables include: +3.2.1 Transaction Parameters + - osp_profile_name: Used OSP provider profile name. + - osp_transaction_handle: OSP transaction handle. + - osp_transaction_id: OSP transaction ID. It is for log purpose. + - osp_route_total: Total number of destinations from OSP servers. + - osp_route_count: destination index starting from 1. + - osp_termiation_cause: Destination termination cause. -osp_profile: Used OSP profile name. Used by outbound channels. -osp_transaction_id: OSP transaction ID. Used by outbound channels. -osp_calling: Original inbound calling number. Used by outbound channels. -osp_called: Original inbound called number. Used by outbound channels. -osp_start_time: Inbound call start time. Used by outbound channels. -osp_source_device: Actual source device. Used by outbound channels. It is only for FreeSWITH OSP module running in indirect mode. -osp_source_nid: Source network ID. Used by outbound channels. -osp_destination_total: Total number of destinations from OSP servers. Used by outbound channels. -osp_destination_count: Destination index. Used by outbound channels. -osp_destination_ip: Destination IP. Used by outbound channels. -osp_destination_nid: Destination network ID. Used by outbound channels. -osp_authreq_status: Authorization request result status. -osp_route_count: Number of supported destinations. -osp_route_N: Destination route string. N is the index starting from 1. -osp_auto_route: Bridge route string. +3.2.2 Exported Parameters + - osp_next_status: ospnext application status. It will be used by FreeSWITCH dial plan logic. 0 for no error. + - osp_route_count: Destination index starting from 1. It will be used by ospnext application and OSP module state handlers. + - osp_termiation_cause: Destination termination cause. It will be used by ospnext application and OSP module state handlers. + - osp_auto_route: Bridge route string. It will be used by bridge application. + +4 State Handler +OSP module state handler reports usage of calls. +OSP module state handler accepts a set of channel variables exported by osplookup and/or ospnext applications to pass OSP call transaction information to OSP module. + +4.1 Transaction Parameters + - osp_profile_name: Used OSP provider profile name. + - osp_transaction_handle: OSP transaction handle. + - osp_transaction_id: OSP transaction ID. It is for log purpose. + - osp_route_total: Total number of destinations from OSP servers. + - osp_route_count: destination index starting from 1. + - osp_termiation_cause: Destination termination cause. + +5 Appendix + +5.1 Sample Configuration + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5.2 Sample Dialplan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/applications/mod_osp/mod_osp.c b/src/mod/applications/mod_osp/mod_osp.c index 6f312386f4..52ccf7d2b1 100644 --- a/src/mod/applications/mod_osp/mod_osp.c +++ b/src/mod/applications/mod_osp/mod_osp.c @@ -35,15 +35,14 @@ #include /* OSP Buffer Size Constants */ -#define OSP_SIZE_NORSTR 256 /* OSP normal string buffer size */ +#define OSP_SIZE_NORSTR 512 /* OSP normal string buffer size */ #define OSP_SIZE_KEYSTR 1024 /* OSP certificate string buffer size */ -#define OSP_SIZE_ROUSTR 4096 /* OSP route buffer size */ -#define OSP_SIZE_TOKSTR 4096 /* OSP token string buffer size */ +#define OSP_SIZE_ROUSTR 1024 /* OSP route buffer size */ -/* OSP Settings Constants */ -#define OSP_MAX_SP 8 /* Max number of OSP service points */ -#define OSP_AUDIT_URL "localhost" /* OSP default Audit URL */ -#define OSP_LOCAL_VALID 1 /* OSP token validating method, locally */ +/* OSP Module Configuration Constants */ +#define OSP_CONFIG_FILE "osp.conf" /* OSP module configuration file name */ +#define OSP_DEF_PROFILE "default" /* Default OSP profile name */ +#define OSP_MAX_SPNUMBER 8 /* Max number of OSP service points */ #define OSP_DEF_LIFETIME 300 /* OSP default SSL lifetime */ #define OSP_MIN_MAXCONN 1 /* OSP min max connections */ #define OSP_MAX_MAXCONN 1000 /* OSP max max connections */ @@ -58,23 +57,29 @@ #define OSP_MIN_TIMEOUT 200 /* OSP min timeout in ms */ #define OSP_MAX_TIMEOUT 60000 /* OSP max timeout in ms */ #define OSP_DEF_TIMEOUT 10000 /* OSP default timeout in ms */ -#define OSP_CUSTOMER_ID "" /* OSP customer ID */ -#define OSP_DEVICE_ID "" /* OSP device ID */ #define OSP_MIN_MAXDEST 1 /* OSP min max destinations */ #define OSP_MAX_MAXDEST 12 /* OSP max max destinations */ #define OSP_DEF_MAXDEST OSP_MAX_MAXDEST /* OSP default max destinations */ -#define OSP_DEF_PROFILE "default" /* OSP default profile name */ -#define OSP_DEF_STRING "" /* OSP default empty string */ -#define OSP_DEF_CALLID "UNDEFINED" /* OSP default Call-ID */ -#define OSP_DEF_STATS -1 /* OSP default statistics */ -#define OSP_URI_DELIM '@' /* URI delimit */ -#define OSP_USER_DELIM ";:" /* URI userinfo delimit */ -#define OSP_HOST_DELIM ";>" /* URI hostport delimit */ -#define OSP_MAX_CINFO 8 /* Max number of custom info */ /* OSP Handle Constant */ #define OSP_INVALID_HANDLE -1 /* Invalid OSP handle, provider, transaction etc. */ +/* OSP Provider Contants */ +#define OSP_AUDIT_URL "localhost" /* OSP default Audit URL */ +#define OSP_LOCAL_VALID 1 /* OSP token validating method, locally */ +#define OSP_CUSTOMER_ID "" /* OSP customer ID */ +#define OSP_DEVICE_ID "" /* OSP device ID */ + +/* URI Contants */ +#define OSP_URI_DELIM '@' /* URI delimit */ +#define OSP_USER_DELIM ";:" /* URI userinfo delimit */ +#define OSP_HOST_DELIM ";>" /* URI hostport delimit */ + +/* OSP Module Other Contants */ +#define OSP_MAX_CINFO 8 /* Max number of custom info */ +#define OSP_DEF_STRING "" /* OSP default empty string */ +#define OSP_DEF_STATS -1 /* OSP default statistics */ + /* OSP Supported Signaling Protocols for Default Protocol */ #define OSP_PROTOCOL_SIP "sip" /* SIP protocol name */ #define OSP_PROTOCOL_H323 "h323" /* H.323 protocol name */ @@ -90,29 +95,26 @@ #define OSP_MODULE_IAX "mod_iax" /* FreeSWITCH IAX module name */ #define OSP_MODULE_SKYPE "mod_skypopen" /* FreeSWITCH Skype module name */ -/* OSP Variables Name */ -#define OSP_VAR_PROFILE "osp_profile" /* Profile name, in cookie */ -#define OSP_VAR_TRANSID "osp_transaction_id" /* Transaction ID, in cookie */ -#define OSP_VAR_CALLING "osp_calling" /* Original calling number, in cookie */ -#define OSP_VAR_CALLED "osp_called" /* Original called number, in cookie */ -#define OSP_VAR_START "osp_start_time" /* Inbound Call start time, in cookie */ -#define OSP_VAR_SRCDEV "osp_source_device" /* Source device IP, in cookie or inbound (actual source device)*/ -#define OSP_VAR_SRCNID "osp_source_nid" /* Source network ID, inbound and in cookie */ -#define OSP_VAR_DESTTOTAL "osp_destination_total" /* Total number of destinations in AuthRsp, in cookie */ -#define OSP_VAR_DESTCOUNT "osp_destination_count" /* Destination count, in cookie */ -#define OSP_VAR_DESTIP "osp_destination_ip" /* Destination IP, in cookie */ -#define OSP_VAR_DESTNID "osp_destination_nid" /* Destination network ID, in cookie */ -#define OSP_VAR_CUSTOMINFO "osp_custom_info_" /* Custom info */ -#define OSP_VAR_DNIDUSERPARAM "osp_networkid_userparam" /* Destination network ID user parameter name */ -#define OSP_VAR_DNIDURIPARAM "osp_networkid_uriparam" /* Destination network ID URI parameter name */ -#define OSP_VAR_USERPHONE "osp_user_phone" /* If to add "user=phone" */ -#define OSP_VAR_OUTPROXY "osp_outbound_proxy" /* Outbound proxy */ -#define OSP_VAR_AUTHSTATUS "osp_authreq_status" /* AuthReq Status */ -#define OSP_VAR_ROUTECOUNT "osp_route_count" /* Number of destinations */ -#define OSP_VAR_ROUTEPRE "osp_route_" /* Destination prefix */ +/* OSP Variable Names */ +#define OSP_VAR_SRCDEV "osp_source_device" /* Source device IP, inbound (actual source device)*/ +#define OSP_VAR_SRCNID "osp_source_nid" /* Source network ID, inbound */ +#define OSP_VAR_CUSTOMINFO "osp_custom_info_" /* Custom info, inbound */ +#define OSP_VAR_DNIDUSERPARAM "osp_networkid_userparam" /* Destination network ID user parameter name, outbound */ +#define OSP_VAR_DNIDURIPARAM "osp_networkid_uriparam" /* Destination network ID URI parameter name, outbound */ +#define OSP_VAR_USERPHONE "osp_user_phone" /* If to add "user=phone", outbound */ +#define OSP_VAR_OUTPROXY "osp_outbound_proxy" /* Outbound proxy, outbound */ +#define OSP_VAR_PROFILE "osp_profile_name" /* Profile name */ +#define OSP_VAR_TRANSACTION "osp_transaction_handle" /* Transaction handle */ +#define OSP_VAR_TRANSID "osp_transaction_id" /* Transaction ID */ +#define OSP_VAR_ROUTETOTAL "osp_route_total" /* Total number of destinations */ +#define OSP_VAR_ROUTECOUNT "osp_route_count" /* Destination count */ +#define OSP_VAR_TCCODE "osp_termination_cause" /* Terimation cause */ #define OSP_VAR_AUTOROUTE "osp_auto_route" /* Bridge route string */ +#define OSP_VAR_LOOKUPSTATUS "osp_lookup_status" /* OSP lookup function status */ +#define OSP_VAR_NEXTSTATUS "osp_next_status" /* OSP next function status */ -/* OSP Use Variable Name */ +/* OSP Using FreeSWITCH Variable Names */ +#define OSP_FS_CALLID "sip_call_id" /* Inbound SIP Call-ID */ #define OSP_FS_FROMUSER "sip_from_user" /* Inbound SIP From user */ #define OSP_FS_TOHOST "sip_to_host" /* Inbound SIP To host */ #define OSP_FS_TOPORT "sip_to_port" /* Inbound SIP To port */ @@ -120,26 +122,32 @@ #define OSP_FS_PAI "sip_P-Asserted-Identity" /* Inbound SIP P-Asserted-Identity header */ #define OSP_FS_DIV "sip_h_Diversion" /* Inbound SIP Diversion header */ #define OSP_FS_PCI "sip_h_P-Charge-Info" /* Inbound SIP P-Charge-Info header */ -#define OSP_FS_OUTCALLID "sip_call_id" /* Outbound SIP Call-ID */ #define OSP_FS_OUTCALLING "origination_caller_id_number" /* Outbound calling number */ -#define OSP_FS_SIPRELEASE "sip_hangup_disposition" /* SIP release source */ -#define OSP_FS_SRCCODEC "write_codec" /* Source codec */ -#define OSP_FS_DESTCODEC "read_codec" /* Destiantion codec */ -#define OSP_FS_RTPSRCREPOCTS "rtp_audio_out_media_bytes" /* Source->reporter octets */ -#define OSP_FS_RTPDESTREPOCTS "rtp_audio_in_media_bytes" /* Destination->reporter octets */ -#define OSP_FS_RTPSRCREPPKTS "rtp_audio_out_media_packet_count" /* Source->reporter packets */ -#define OSP_FS_RTPDESTREPPKTS "rtp_audio_in_media_packet_count" /* Destination->reporter packets */ +#define OSP_FS_SIPRELEASE "sip_hangup_disposition" /* Usage SIP release source */ +#define OSP_FS_SRCCODEC "write_codec" /* Usage source codec */ +#define OSP_FS_DESTCODEC "read_codec" /* Usage destiantion codec */ +#define OSP_FS_RTPSRCREPOCTS "rtp_audio_out_media_bytes" /* Usage source->reporter octets */ +#define OSP_FS_RTPDESTREPOCTS "rtp_audio_in_media_bytes" /* Usage destination->reporter octets */ +#define OSP_FS_RTPSRCREPPKTS "rtp_audio_out_media_packet_count" /* Usage source->reporter packets */ +#define OSP_FS_RTPDESTREPPKTS "rtp_audio_in_media_packet_count" /* Usage destination->reporter packets */ +#define OSP_FS_HANGUPCAUSE "last_bridge_hangup_cause" /* Termination cause */ -typedef struct osp_settings { - switch_bool_t debug; /* OSP module debug info flag */ - switch_log_level_t loglevel; /* Log level for debug info */ - switch_bool_t hardware; /* Crypto hardware flag */ - const char *modules[OSPC_PROTNAME_NUMBER]; /* Endpoint names */ - const char *profiles[OSPC_PROTNAME_NUMBER]; /* Endpoint profile names */ - OSPE_PROTOCOL_NAME protocol; /* Default signaling protocol */ - switch_bool_t shutdown; /* OSP module status */ - switch_memory_pool_t *pool; /* OSP module memory pool */ -} osp_settings_t; +/* FreeSWITCH Endpoint Parameters */ +typedef struct osp_endpoint { + const char *module; /* Endpoint module name */ + const char *profile; /* Endpoint profile name */ +} osp_endpoint_t; + +/* OSP Global Status */ +typedef struct osp_global { + switch_bool_t debug; /* OSP module debug flag */ + switch_log_level_t loglevel; /* Log level for debug messages */ + switch_bool_t hardware; /* Crypto hardware flag */ + osp_endpoint_t endpoint[OSPC_PROTNAME_NUMBER]; /* Used endpoints */ + OSPE_PROTOCOL_NAME protocol; /* Default signaling protocol */ + switch_bool_t shutdown; /* OSP module status */ + switch_memory_pool_t *pool; /* OSP module memory pool */ +} osp_global_t; /* OSP Work Modes */ typedef enum osp_workmode { @@ -153,28 +161,32 @@ typedef enum osp_srvtype { OSP_SRV_NPQUERY /* Number portability query service */ } osp_srvtype_t; +/* OSP Profile Parameters */ typedef struct osp_profile { - const char *name; /* OSP profile name */ - int spnum; /* Number of OSP service points */ - const char *spurls[OSP_MAX_SP]; /* OSP service point URLs */ - const char *device; /* OSP source IP */ - int lifetime; /* SSL life time */ - int maxconnect; /* Max number of HTTP connections */ - int persistence; /* HTTP persistence in seconds */ - int retrydelay; /* HTTP retry delay in seconds */ - int retrylimit; /* HTTP retry times */ - int timeout; /* HTTP timeout in ms */ - osp_workmode_t workmode; /* OSP work mode */ - osp_srvtype_t srvtype; /* OSP service type */ - int maxdest; /* Max destinations */ - OSPTPROVHANDLE provider; /* OSP provider handle */ - struct osp_profile *next; /* Next OSP profile */ + const char *name; /* OSP profile name */ + int spnumber; /* Number of OSP service points */ + const char *spurl[OSP_MAX_SPNUMBER]; /* OSP service point URLs */ + const char *deviceip; /* OSP client end IP */ + int lifetime; /* SSL life time */ + int maxconnect; /* Max number of HTTP connections */ + int persistence; /* HTTP persistence in seconds */ + int retrydelay; /* HTTP retry delay in seconds */ + int retrylimit; /* HTTP retry times */ + int timeout; /* HTTP timeout in ms */ + osp_workmode_t workmode; /* OSP work mode */ + osp_srvtype_t srvtype; /* OSP service type */ + int maxdest; /* Max destinations */ + OSPTPROVHANDLE provider; /* OSP provider handle */ + struct osp_profile *next; /* Next OSP profile */ } osp_profile_t; +/* OSP Inbound Parameters */ typedef struct osp_inbound { const char *actsrc; /* Actual source device IP address */ const char *srcdev; /* Source device IP address */ + const char *srcnid; /* Source network ID */ OSPE_PROTOCOL_NAME protocol; /* Inbound signaling protocol */ + const char *callid; /* Inbound Call-ID */ char calling[OSP_SIZE_NORSTR]; /* Inbound calling number */ char called[OSP_SIZE_NORSTR]; /* Inbound called number */ char nprn[OSP_SIZE_NORSTR]; /* Inbound NP routing number */ @@ -187,16 +199,20 @@ typedef struct osp_inbound { char divuser[OSP_SIZE_NORSTR]; /* Inbound user of SIP Diversion header */ char divhost[OSP_SIZE_NORSTR]; /* Inbound hostport of SIP Diversion header */ char pciuser[OSP_SIZE_NORSTR]; /* Inbound user of SIP P-Charge-Info header */ - const char *srcnid; /* Inbound source network ID */ - switch_time_t start; /* Call start time */ const char *cinfo[OSP_MAX_CINFO]; /* Custom info */ } osp_inbound_t; -typedef struct osp_destination { +/* OSP Route Parameters */ +typedef struct osp_results { + const char *profile; /* Profile name */ + OSPTTRANHANDLE transaction; /* Transaction handle */ + uint64_t transid; /* Transaction ID */ + unsigned int total; /* Total number of destinations */ + unsigned int count; /* Destination count starting from 1 */ unsigned int timelimit; /* Outbound duration limit */ - char dest[OSP_SIZE_NORSTR]; /* Destination IP address */ char calling[OSP_SIZE_NORSTR]; /* Outbound calling number, may be translated */ char called[OSP_SIZE_NORSTR]; /* Outbound called number, may be translated */ + char dest[OSP_SIZE_NORSTR]; /* Destination IP address */ char destnid[OSP_SIZE_NORSTR]; /* Destination network ID */ char nprn[OSP_SIZE_NORSTR]; /* Outbound NP routing number */ char npcic[OSP_SIZE_NORSTR]; /* Outbound NP carrier identification code */ @@ -204,35 +220,10 @@ typedef struct osp_destination { char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR]; /* Outbound Operator names */ OSPE_PROTOCOL_NAME protocol; /* Signaling protocol */ switch_bool_t supported; /* Supported by FreeRADIUS OSP module */ -} osp_destination_t; - -typedef struct osp_results { - const char *profile; /* Profile name */ - uint64_t transid; /* Transaction ID */ - switch_time_t start; /* Call start time */ - char calling[OSP_SIZE_NORSTR]; /* Original calling number */ - char called[OSP_SIZE_NORSTR]; /* Original called number */ - const char *srcdev; /* Source device IP */ - const char *srcnid; /* Source network ID */ - int status; /* AuthReq status */ - int numdest; /* Number of destinations */ - osp_destination_t dests[OSP_MAX_MAXDEST]; /* Destinations */ + switch_call_cause_t cause; /* Termination cause for current destination */ } osp_results_t; -typedef struct osp_cookie { - const char *profile; /* Profile name */ - uint64_t transid; /* Transaction ID */ - const char *calling; /* Original calling number */ - const char *called; /* Original called number */ - switch_time_t start; /* Call start time */ - const char *srcdev; /* Source Device IP */ - int desttotal; /* Total number of destinations in AuthRsp */ - int destcount; /* Destination count */ - const char *dest; /* Destination IP */ - const char *srcnid; /* Source network ID */ - const char *destnid; /* Destination network ID */ -} osp_cookie_t; - +/* OSP Outbound Parameters */ typedef struct osp_outbound { const char *dniduserparam; /* Destination network ID user parameter name */ const char *dniduriparam; /* Destination network ID URI parameter name */ @@ -240,55 +231,46 @@ typedef struct osp_outbound { const char *outproxy; /* Outbound proxy IP address */ } osp_outbound_t; +/* OSP Usage Parameters */ typedef struct osp_usage { - const char *srcdev; /* Source device IP */ - const char *callid; /* Call-ID */ - OSPE_PROTOCOL_NAME inprotocol; /* Inbound signaling protocol */ - OSPE_PROTOCOL_NAME outprotocol; /* Outbound signaling protocol */ - int release; /* Release source */ - switch_call_cause_t cause; /* Termination cause */ - switch_time_t alert; /* Call alert time */ - switch_time_t connect; /* Call answer time */ - switch_time_t end; /* Call end time */ - switch_time_t duration; /* Call duration */ - switch_time_t pdd; /* Post dial delay, in us */ - const char *srccodec; /* Source codec */ - const char *destcodec; /* Destination codec */ - int rtpsrcrepoctets; /* RTP source->reporter bytes */ - int rtpdestrepoctets; /* RTP destination->reporter bytes */ - int rtpsrcreppackets; /* RTP source->reporter packets */ - int rtpdestreppackets; /* RTP destiantion->reporter packets */ + OSPE_RELEASE release; /* Release source */ + switch_call_cause_t cause; /* Termination cause */ + switch_time_t start; /* Call start time */ + switch_time_t alert; /* Call alert time */ + switch_time_t connect; /* Call answer time */ + switch_time_t end; /* Call end time */ + switch_time_t duration; /* Call duration */ + switch_time_t pdd; /* Post dial delay, in us */ + const char *srccodec; /* Source codec */ + const char *destcodec; /* Destination codec */ + int rtpsrcrepoctets; /* RTP source->reporter bytes */ + int rtpdestrepoctets; /* RTP destination->reporter bytes */ + int rtpsrcreppackets; /* RTP source->reporter packets */ + int rtpdestreppackets; /* RTP destiantion->reporter packets */ } osp_usage_t; -typedef struct osp_threadarg { - OSPTTRANHANDLE transaction; /* Transaction handle */ - uint64_t transid; /* Transaction ID */ - switch_call_cause_t cause; /* Release code */ - time_t start; /* Call start time */ - time_t alert; /* Call alert time */ - time_t connect; /* Call connect time */ - time_t end; /* Call end time */ - int duration; /* Call duration */ - int pdd; /* Post dial delay, in ms */ - int release; /* EP that released the call */ -} osp_threadarg_t; +/* Macro functions for debug */ +#define OSP_DEBUG(_fmt, ...) if (osp_global.debug) { switch_log_printf(SWITCH_CHANNEL_LOG, osp_global.loglevel, "%s: "_fmt"\n", __SWITCH_FUNC__, __VA_ARGS__); } +#define OSP_DEBUG_MSG(_msg) OSP_DEBUG("%s", _msg) +#define OSP_DEBUG_START OSP_DEBUG_MSG("Start") +#define OSP_DEBUG_END OSP_DEBUG_MSG("End") +/* Macro to prevent NULL string */ +#define OSP_FILTER_NULLSTR(_str) (switch_strlen_zero(_str) ? OSP_DEF_STRING : (_str)) +/* Macro to prevent NULL integer */ +#define OSP_FILTER_NULLINT(_int) ((_int) ? *(_int) : 0) +/* Macro to adjust buffer length */ +#define OSP_ADJUST_LEN(_head, _size, _len) { (_len) = strlen(_head); (_head) += (_len); (_size) -= (_len); } -/* OSP module global settings */ -static osp_settings_t osp_globals; +/* OSP Module Global Status */ +static osp_global_t osp_global; /* OSP module profiles */ static osp_profile_t *osp_profiles = NULL; -/* switch_status_t mod_osp_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ -SWITCH_MODULE_LOAD_FUNCTION(mod_osp_load); -/* switch_status_t mod_osp_shutdown(void) */ -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_osp_shutdown); -/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) */ -SWITCH_MODULE_DEFINITION(mod_osp, mod_osp_load, mod_osp_shutdown, NULL); - -/* Macro to prevent NULL string */ -#define osp_filter_null(_str) switch_strlen_zero(_str) ? OSP_DEF_STRING : _str -#define osp_adjust_len(_head, _size, _len) { _len = strlen(_head); _head += _len; _size -= _len; } +/* OSP default certificates */ +static const char *B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm"; +static const char *B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9"; +static const char *B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0="; /* * Find OSP profile by name @@ -303,6 +285,8 @@ static switch_status_t osp_find_profile( osp_profile_t *p; switch_status_t status = SWITCH_STATUS_FALSE; + OSP_DEBUG_START; + if (name) { if (profile) { *profile = NULL; @@ -319,6 +303,14 @@ static switch_status_t osp_find_profile( } } + if (status == SWITCH_STATUS_SUCCESS) { + OSP_DEBUG("Found profile '%s'", name); + } else { + OSP_DEBUG("Unable to find profile '%s'", name); + } + + OSP_DEBUG_END; + return status; } @@ -327,11 +319,10 @@ static switch_status_t osp_find_profile( * param pool OSP module memory pool * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed, SWITCH_STATUS_MEMERR Memory Error. */ -static switch_status_t osp_load_settings( +static switch_status_t osp_load_config( switch_memory_pool_t *pool) { - char *cf = "osp.conf"; - switch_xml_t cfg, xml = NULL, param, settings, xprofile, profiles; + switch_xml_t xcfg, xml = NULL, xsettings, xparam, xprofile, xprofiles; const char *name; const char *value; const char *module; @@ -340,128 +331,162 @@ static switch_status_t osp_load_settings( int number; switch_status_t status = SWITCH_STATUS_SUCCESS; - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open '%s'\n", cf); - status = SWITCH_STATUS_FALSE; - return status; + OSP_DEBUG_START; + + /* Load OSP module configuration file */ + if (!(xml = switch_xml_open_cfg(OSP_CONFIG_FILE, &xcfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open OSP module configuration file '%s'\n", OSP_CONFIG_FILE); + OSP_DEBUG_END; + return SWITCH_STATUS_FALSE; } - memset(&osp_globals, 0, sizeof(osp_globals)); - osp_globals.loglevel = SWITCH_LOG_DEBUG; - osp_globals.pool = pool; - osp_globals.protocol = OSPC_PROTNAME_SIP; + OSP_DEBUG_MSG("Parsing settings"); - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - name = switch_xml_attr_soft(param, "name"); - value = switch_xml_attr_soft(param, "value"); - module = switch_xml_attr_soft(param, "module"); - context = switch_xml_attr_soft(param, "profile"); + /* Init OSP module global status */ + memset(&osp_global, 0, sizeof(osp_global)); + osp_global.loglevel = SWITCH_LOG_DEBUG; + osp_global.protocol = OSPC_PROTNAME_SIP; + osp_global.pool = pool; + + /* Get OSP module global settings */ + if ((xsettings = switch_xml_child(xcfg, "settings"))) { + for (xparam = switch_xml_child(xsettings, "param"); xparam; xparam = xparam->next) { + /* Settings parameter name */ + name = switch_xml_attr_soft(xparam, "name"); + /* Settings parameter value */ + value = switch_xml_attr_soft(xparam, "value"); + /* Endpoint module name */ + module = switch_xml_attr_soft(xparam, "module"); + /* Endpoint profile name */ + context = switch_xml_attr_soft(xparam, "profile"); + + /* Ignore parameter without name */ if (switch_strlen_zero(name)) { continue; } + if (!strcasecmp(name, "debug-info")) { + /* OSP module debug flag */ if (!switch_strlen_zero(value)) { - osp_globals.debug = switch_true(value); + osp_global.debug = switch_true(value); } + OSP_DEBUG("debug-info: '%d'", osp_global.debug); } else if (!strcasecmp(name, "log-level")) { + /* OSP module debug message log level */ if (switch_strlen_zero(value)) { continue; } else if (!strcasecmp(value, "console")) { - osp_globals.loglevel = SWITCH_LOG_CONSOLE; + osp_global.loglevel = SWITCH_LOG_CONSOLE; } else if (!strcasecmp(value, "alert")) { - osp_globals.loglevel = SWITCH_LOG_ALERT; + osp_global.loglevel = SWITCH_LOG_ALERT; } else if (!strcasecmp(value, "crit")) { - osp_globals.loglevel = SWITCH_LOG_CRIT; + osp_global.loglevel = SWITCH_LOG_CRIT; } else if (!strcasecmp(value, "error")) { - osp_globals.loglevel = SWITCH_LOG_ERROR; + osp_global.loglevel = SWITCH_LOG_ERROR; } else if (!strcasecmp(value, "warning")) { - osp_globals.loglevel = SWITCH_LOG_WARNING; + osp_global.loglevel = SWITCH_LOG_WARNING; } else if (!strcasecmp(value, "notice")) { - osp_globals.loglevel = SWITCH_LOG_NOTICE; + osp_global.loglevel = SWITCH_LOG_NOTICE; } else if (!strcasecmp(value, "info")) { - osp_globals.loglevel = SWITCH_LOG_INFO; + osp_global.loglevel = SWITCH_LOG_INFO; } else if (!strcasecmp(value, "debug")) { - osp_globals.loglevel = SWITCH_LOG_DEBUG; + osp_global.loglevel = SWITCH_LOG_DEBUG; } + OSP_DEBUG("log-level: '%d'", osp_global.loglevel); } else if (!strcasecmp(name, "crypto-hardware")) { + /* OSP module crypto hardware flag */ if (!switch_strlen_zero(value)) { - osp_globals.hardware = switch_true(value); + osp_global.hardware = switch_true(value); } + OSP_DEBUG("crypto-hardware: '%d'", osp_global.hardware); } else if (!strcasecmp(name, "default-protocol")) { + /* OSP module default signaling protocol */ if (switch_strlen_zero(value)) { continue; } else if (!strcasecmp(value, OSP_PROTOCOL_SIP)) { - osp_globals.protocol = OSPC_PROTNAME_SIP; + osp_global.protocol = OSPC_PROTNAME_SIP; } else if (!strcasecmp(value, OSP_PROTOCOL_H323)) { - osp_globals.protocol = OSPC_PROTNAME_Q931; + osp_global.protocol = OSPC_PROTNAME_Q931; } else if (!strcasecmp(value, OSP_PROTOCOL_IAX)) { - osp_globals.protocol = OSPC_PROTNAME_IAX; + osp_global.protocol = OSPC_PROTNAME_IAX; } else if (!strcasecmp(value, OSP_PROTOCOL_SKYPE)) { - osp_globals.protocol = OSPC_PROTNAME_SKYPE; + osp_global.protocol = OSPC_PROTNAME_SKYPE; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported default protocol '%s'\n", value); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported protocol '%s'\n", value); } - } else if (!strcasecmp(name, "sip")) { + OSP_DEBUG("default-protocol: '%d'", osp_global.protocol); + } else if (!strcasecmp(name, OSP_PROTOCOL_SIP)) { + /* SIP endpoint module */ if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_PROTNAME_SIP] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_SIP].module = switch_core_strdup(osp_global.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate SIP module name\n"); status = SWITCH_STATUS_MEMERR; break; } } + /* SIP endpoint profile */ if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_PROTNAME_SIP] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_SIP].profile = switch_core_strdup(osp_global.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate SIP profile name\n"); status = SWITCH_STATUS_MEMERR; break; } } - } else if (!strcasecmp(name, "h323")) { + OSP_DEBUG("SIP: '%s/%s'", osp_global.endpoint[OSPC_PROTNAME_SIP].module, osp_global.endpoint[OSPC_PROTNAME_SIP].profile); + } else if (!strcasecmp(name, OSP_PROTOCOL_H323)) { + /* H.323 endpoint module */ if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_PROTNAME_Q931] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_Q931].module = switch_core_strdup(osp_global.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate H.323 module name\n"); status = SWITCH_STATUS_MEMERR; break; } } + /* H.323 endpoint profile */ if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_PROTNAME_Q931] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_Q931].profile = switch_core_strdup(osp_global.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate H.323 profile name\n"); status = SWITCH_STATUS_MEMERR; break; } } - } else if (!strcasecmp(name, "iax")) { + OSP_DEBUG("H.323: '%s/%s'", osp_global.endpoint[OSPC_PROTNAME_Q931].module, osp_global.endpoint[OSPC_PROTNAME_Q931].profile); + } else if (!strcasecmp(name, OSP_PROTOCOL_IAX)) { + /* IAX endpoint module */ if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_PROTNAME_IAX] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_IAX].module = switch_core_strdup(osp_global.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate IAX module name\n"); status = SWITCH_STATUS_MEMERR; break; } } + /* IAX endpoint profile */ if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_PROTNAME_IAX] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_IAX].profile = switch_core_strdup(osp_global.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate IAX profile name\n"); status = SWITCH_STATUS_MEMERR; break; } } - } else if (!strcasecmp(name, "skype")) { + OSP_DEBUG("IAX: '%s/%s'", osp_global.endpoint[OSPC_PROTNAME_IAX].module, osp_global.endpoint[OSPC_PROTNAME_IAX].profile); + } else if (!strcasecmp(name, OSP_PROTOCOL_SKYPE)) { + /* Skype endpoint module */ if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_PROTNAME_SKYPE] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_SKYPE].module = switch_core_strdup(osp_global.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate Skype module name\n"); status = SWITCH_STATUS_MEMERR; break; } - } + } + /* Skype endpoint profile */ if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_PROTNAME_SKYPE] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_global.endpoint[OSPC_PROTNAME_SKYPE].profile = switch_core_strdup(osp_global.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate Skype profile name\n"); status = SWITCH_STATUS_MEMERR; break; } } + OSP_DEBUG("SKYPE: '%s/%s'", osp_global.endpoint[OSPC_PROTNAME_SKYPE].module, osp_global.endpoint[OSPC_PROTNAME_SKYPE].profile); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter '%s'\n", name); } @@ -469,26 +494,37 @@ static switch_status_t osp_load_settings( } if (status != SWITCH_STATUS_SUCCESS) { + /* Fail for SWITCH_STATUS_MEMERR */ switch_xml_free(xml); + OSP_DEBUG_END; return status; } - if ((profiles = switch_xml_child(cfg, "profiles"))) { - for (xprofile = switch_xml_child(profiles, "profile"); xprofile; xprofile = xprofile->next) { + /* Get OSP module profiles */ + if ((xprofiles = switch_xml_child(xcfg, "profiles"))) { + for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) { + /* Profile name */ name = switch_xml_attr_soft(xprofile, "name"); if (switch_strlen_zero(name)) { name = OSP_DEF_PROFILE; } + OSP_DEBUG("Parsing profile '%s'", name); + + /* Check duplate profile name */ if (osp_find_profile(name, NULL) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignored duplicate profile '%s'\n", name); continue; } - if (!(profile = switch_core_alloc(osp_globals.pool, sizeof(*profile)))) { + + /* Allocate profile */ + if (!(profile = switch_core_alloc(osp_global.pool, sizeof(*profile)))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to alloc profile\n"); status = SWITCH_STATUS_MEMERR; break; } - if (!(profile->name = switch_core_strdup(osp_globals.pool, name))) { + + /* Store profile name */ + if (!(profile->name = switch_core_strdup(osp_global.pool, name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate profile name\n"); status = SWITCH_STATUS_MEMERR; /* "profile" cannot free to pool in FreeSWITCH */ @@ -505,62 +541,80 @@ static switch_status_t osp_load_settings( profile->maxdest = OSP_DEF_MAXDEST; profile->provider = OSP_INVALID_HANDLE; - for (param = switch_xml_child(xprofile, "param"); param; param = param->next) { - name = switch_xml_attr_soft(param, "name"); - value = switch_xml_attr_soft(param, "value"); + for (xparam = switch_xml_child(xprofile, "param"); xparam; xparam = xparam->next) { + /* Profile parameter name */ + name = switch_xml_attr_soft(xparam, "name"); + /* Profile parameter value */ + value = switch_xml_attr_soft(xparam, "value"); + + /* Ignore profile parameter without name or value */ if (switch_strlen_zero(name) || switch_strlen_zero(value)) { continue; } + if (!strcasecmp(name, "service-point-url")) { - if (profile->spnum < OSP_MAX_SP) { - profile->spurls[profile->spnum] = switch_core_strdup(osp_globals.pool, value); - profile->spnum++; + /* OSP service point URL */ + if (profile->spnumber < OSP_MAX_SPNUMBER) { + profile->spurl[profile->spnumber] = switch_core_strdup(osp_global.pool, value); + OSP_DEBUG("service-point-url[%d]: '%s'", profile->spnumber, profile->spurl[profile->spnumber]); + profile->spnumber++; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignored excess service point '%s'\n", value); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignored service point '%s'\n", value); } } else if (!strcasecmp(name, "device-ip")) { - profile->device = switch_core_strdup(osp_globals.pool, value); + /* OSP client end IP */ + profile->deviceip = switch_core_strdup(osp_global.pool, value); + OSP_DEBUG("device-ip: '%s'", profile->deviceip); } else if (!strcasecmp(name, "ssl-lifetime")) { + /* SSL lifetime */ if (sscanf(value, "%d", &number) == 1) { profile->lifetime = number; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "ssl-lifetime must be a number\n"); } + OSP_DEBUG("ssl-lifetime: '%d'", profile->lifetime); } else if (!strcasecmp(name, "http-max-connections")) { + /* HTTP max connections */ if ((sscanf(value, "%d", &number) == 1) && (number >= OSP_MIN_MAXCONN) && (number <= OSP_MAX_MAXCONN)) { profile->maxconnect = number; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "http-max-connections must be between %d and %d\n", OSP_MIN_MAXCONN, OSP_MAX_MAXCONN); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "http-max-connections must be between %d and %d\n", OSP_MIN_MAXCONN, OSP_MAX_MAXCONN); } + OSP_DEBUG("http-max-connections: '%d'", profile->maxconnect); } else if (!strcasecmp(name, "http-persistence")) { + /* HTTP persistence */ if (sscanf(value, "%d", &number) == 1) { profile->persistence = number; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "http-persistence must be a number\n"); } + OSP_DEBUG("http-persistence: '%d'", profile->persistence); } else if (!strcasecmp(name, "http-retry-delay")) { + /* HTTP retry delay */ if ((sscanf(value, "%d", &number) == 1) && (number >= OSP_MIN_RETRYDELAY) && (number <= OSP_MAX_RETRYDELAY)) { profile->retrydelay = number; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "http-retry-delay must be between %d and %d\n", OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "http-retry-delay must be between %d and %d\n", OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY); } + OSP_DEBUG("http-retry-delay: '%d'", profile->retrydelay); } else if (!strcasecmp(name, "http-retry-limit")) { + /* HTTP retry limit */ if ((sscanf(value, "%d", &number) == 1) && (number >= OSP_MIN_RETRYLIMIT) && (number <= OSP_MAX_RETRYLIMIT)) { profile->retrylimit = number; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "http-retry-limit must be between %d and %d\n", OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "http-retry-limit must be between %d and %d\n", OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT); } + OSP_DEBUG("http-retry-limit: '%d'", profile->retrylimit); } else if (!strcasecmp(name, "http-timeout")) { + /* HTTP timeout value */ if ((sscanf(value, "%d", &number) == 1) && (number >= OSP_MIN_TIMEOUT) && (number <= OSP_MAX_TIMEOUT)) { profile->timeout = number; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "http-timeout must be between %d and %d\n", OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "http-timeout must be between %d and %d\n", OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT); } + OSP_DEBUG("http-timeout: '%d'", profile->timeout); } else if (!strcasecmp(name, "work-mode")) { + /* OSP work mode */ if (!strcasecmp(value, "direct")) { profile->workmode = OSP_MODE_DIRECT; } else if (!strcasecmp(value, "indirect")) { @@ -568,7 +622,9 @@ static switch_status_t osp_load_settings( } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown work mode '%s'\n", value); } + OSP_DEBUG("work-mode: '%d'", profile->workmode); } else if (!strcasecmp(name, "service-type")) { + /* OSP service type */ if (!strcasecmp(value, "voice")) { profile->srvtype = OSP_SRV_VOICE; } else if (!strcasecmp(value, "npquery")) { @@ -576,19 +632,22 @@ static switch_status_t osp_load_settings( } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown service type '%s'\n", value); } + OSP_DEBUG("service-type: '%d'", profile->srvtype); } else if (!strcasecmp(name, "max-destinations")) { + /* Max destinations */ if ((sscanf(value, "%d", &number) == 1) && (number >= OSP_MIN_MAXDEST) && (number <= OSP_MAX_MAXDEST)) { profile->maxdest = number; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "max-destinations must be between %d and %d\n", OSP_MIN_MAXDEST, OSP_MAX_MAXDEST); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "max-destinations must be between %d and %d\n", OSP_MIN_MAXDEST, OSP_MAX_MAXDEST); } + OSP_DEBUG("max-destinations: '%d'", profile->maxdest); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter '%s'\n", name); } } - if (!profile->spnum) { + /* Check number of service porints */ + if (!profile->spnumber) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Without service point URI in profile '%s'\n", profile->name); /* "profile" cannot free to pool in FreeSWITCH */ continue; @@ -601,14 +660,11 @@ static switch_status_t osp_load_settings( switch_xml_free(xml); + OSP_DEBUG_END; + return status; } -/* OSP default certificates */ -const char *B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm"; -const char *B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9"; -const char *B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0="; - /* * Init OSP client end * return @@ -625,16 +681,21 @@ static void osp_init_osptk(void) unsigned char cacertdata[OSP_SIZE_KEYSTR]; int error; - if (osp_globals.hardware) { + OSP_DEBUG_START; + + /* Init OSP Toolkit */ + if (osp_global.hardware) { if ((error = OSPPInit(OSPC_TRUE)) != OSPC_ERR_NO_ERROR) { + /* Unable to enable crypto hardware, disable it */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to enable crypto hardware, error '%d'\n", error); - osp_globals.hardware = SWITCH_FALSE; + osp_global.hardware = SWITCH_FALSE; OSPPInit(OSPC_FALSE); } } else { OSPPInit(OSPC_FALSE); } + /* Init OSP profile, using default certificates */ for (profile = osp_profiles; profile; profile = profile->next) { privatekey.PrivateKeyData = privatekeydata; privatekey.PrivateKeyLength = sizeof(privatekeydata); @@ -655,9 +716,10 @@ static void osp_init_osptk(void) } if (error == OSPC_ERR_NO_ERROR) { + /* Create provider handle */ error = OSPPProviderNew( - profile->spnum, /* Number of service points */ - profile->spurls, /* Service point URLs */ + profile->spnumber, /* Number of service points */ + profile->spurl, /* Service point URLs */ NULL, /* Weights */ OSP_AUDIT_URL, /* Audit URL */ &privatekey, /* Provate key */ @@ -677,21 +739,52 @@ static void osp_init_osptk(void) if (error != OSPC_ERR_NO_ERROR) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to create provider for profile %s, error '%d'\n", profile->name, error); profile->provider = OSP_INVALID_HANDLE; + } else { + OSP_DEBUG("Created provider handle for profile '%s'", profile->name); } } } + + OSP_DEBUG_END; +} + +/* + * Cleanup OSP client end + * return + */ +static void osp_cleanup_osptk(void) +{ + osp_profile_t *profile; + + OSP_DEBUG_START; + + for (profile = osp_profiles; profile; profile = profile->next) { + if (profile->provider != OSP_INVALID_HANDLE) { + /* Delete provider handle */ + OSPPProviderDelete(profile->provider, 0); + profile->provider = OSP_INVALID_HANDLE; + OSP_DEBUG("Deleted provider handle for profile '%s'", profile->name); + } + } + + /* Cleanup OSP Toolkit */ + OSPPCleanup(); + + OSP_DEBUG_END; } /* * Get protocol name - * param protocol Supported protocol + * param protocol Protocol * return protocol name */ -static const char *osp_get_protocol( +static const char *osp_get_protocolname( OSPE_PROTOCOL_NAME protocol) { const char *name; + OSP_DEBUG_START; + switch (protocol) { case OSPC_PROTNAME_UNKNOWN: name = OSP_PROTOCOL_UNKNO; @@ -721,15 +814,1593 @@ static const char *osp_get_protocol( name = OSP_PROTOCOL_UNSUP; break; } + OSP_DEBUG("Protocol %d: '%s'", protocol, name); + + OSP_DEBUG_END; return name; } /* - * Macro expands to: - * static switch_status_t osp_api_function(_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) + * Get protocol from module name + * param module Endpoint module name + * return protocol Endpoint protocol name */ -SWITCH_STANDARD_API(osp_api_function) +static OSPE_PROTOCOL_NAME osp_get_protocol( + const char *module) +{ + OSPE_PROTOCOL_NAME protocol; + + OSP_DEBUG_START; + + if (!strcasecmp(module, OSP_MODULE_SIP)) { + protocol = OSPC_PROTNAME_SIP; + } else if (!strcasecmp(module, OSP_MODULE_H323)) { + protocol = OSPC_PROTNAME_Q931; + } else if (!strcasecmp(module, OSP_MODULE_IAX)) { + protocol = OSPC_PROTNAME_IAX; + } else if (!strcasecmp(module, OSP_MODULE_SKYPE)) { + protocol = OSPC_PROTNAME_SKYPE; + } else { + protocol = OSPC_PROTNAME_UNKNOWN; + } + OSP_DEBUG("Module %s: '%d'", module, protocol); + + OSP_DEBUG_END; + + return protocol; +} + +/* + * Parse userinfo for user and LNP + * param userinfo SIP URI userinfo + * param user User part + * param usersize Size of user buffer + * param rn Routing number + * param rnsize Size of rn buffer + * param cic Carrier Identification Cod + * param cicsize Size of cic buffer + * param npdi NP Database Dip Indicator + * return + */ +static void osp_parse_userinfo( + const char *userinfo, + char *user, + switch_size_t usersize, + char *rn, + switch_size_t rnsize, + char *cic, + switch_size_t cicsize, + int *npdi) +{ + char buffer[OSP_SIZE_NORSTR]; + char *item; + char *tmp; + + OSP_DEBUG_START; + + /* Set default values */ + if (user && usersize) { + user[0] = '\0'; + } + if (rn && rnsize) { + rn[0] = '\0'; + } + if (cic && cicsize) { + cic[0] = '\0'; + } + if (npdi) { + *npdi = 0; + } + + /* Parse userinfo */ + if (!switch_strlen_zero(userinfo)) { + /* Copy userinfo to temporary buffer */ + switch_copy_string(buffer, userinfo, sizeof(buffer)); + + /* Parse user */ + item = strtok_r(buffer, OSP_USER_DELIM, &tmp); + if (user && usersize) { + switch_copy_string(user, item, usersize); + } + + /* Parse LNP parameters */ + for (item = strtok_r(NULL, OSP_USER_DELIM, &tmp); item; item = strtok_r(NULL, OSP_USER_DELIM, &tmp)) { + if (!strncasecmp(item, "rn=", 3)) { + /* Parsed routing number */ + if (rn && rnsize) { + switch_copy_string(rn, item + 3, rnsize); + } + } else if (!strncasecmp(item, "cic=", 4)) { + /* Parsed cic */ + if (cic && cicsize) { + switch_copy_string(cic, item + 4, cicsize); + } + } else if (!strcasecmp(item, "npdi")) { + /* Parsed npdi */ + if (npdi) { + *npdi = 1; + } + } + } + } + + OSP_DEBUG("user: '%s'", OSP_FILTER_NULLSTR(user)); + OSP_DEBUG("rn: '%s'", OSP_FILTER_NULLSTR(rn)); + OSP_DEBUG("cic: '%s'", OSP_FILTER_NULLSTR(cic)); + OSP_DEBUG("npdi: '%d'", OSP_FILTER_NULLINT(npdi)); + + OSP_DEBUG_END; +} + +/* + * Parse SIP header user + * param header SIP header + * param user SIP header user + * param usersize Size of user buffer + * return + */ +static void osp_parse_header_user( + const char *header, + char *user, + switch_size_t usersize) +{ + char buffer[OSP_SIZE_NORSTR]; + char *head; + char *tmp; + char *item; + + OSP_DEBUG_START; + + if (user && usersize) { + user[0] = '\0'; + + /* Parse user */ + if (!switch_strlen_zero(header) && user && usersize) { + /* Copy header to temporary buffer */ + switch_copy_string(buffer, header, sizeof(buffer)); + + if ((head = strstr(buffer, "sip:"))) { + head += 4; + if ((tmp = strchr(head, OSP_URI_DELIM))) { + *tmp = '\0'; + item = strtok_r(head, OSP_USER_DELIM, &tmp); + switch_copy_string(user, item, usersize); + } + } + } + + OSP_DEBUG("user: '%s'", user); + } + + OSP_DEBUG_END; +} + +/* + * Parse SIP header host + * param header SIP header + * param host SIP header host + * param hostsize Size of host buffer + * return + */ +static void osp_parse_header_host( + const char *header, + char *host, + switch_size_t hostsize) +{ + char buffer[OSP_SIZE_NORSTR]; + char *head; + char *tmp; + + OSP_DEBUG_START; + + if (hostsize) { + host[0] = '\0'; + + /* Parse host*/ + if (!switch_strlen_zero(header) && host && hostsize) { + /* Copy header to temporary buffer */ + switch_copy_string(buffer, header, sizeof(buffer)); + + if ((head = strstr(buffer, "sip:"))) { + head += 4; + if ((tmp = strchr(head, OSP_URI_DELIM))) { + head = tmp + 1; + } + tmp = strtok(head, OSP_HOST_DELIM); + switch_copy_string(host, tmp, hostsize); + } + } + + OSP_DEBUG("host: '%s'", host); + } + + OSP_DEBUG_END; +} + +/* + * Convert "address:port" to "[x.x.x.x]:port" or "hostname:port" format + * param src Source address string + * param dest Destination address string + * param destsize Size of dest buffer + * return + */ +static void osp_convert_inout( + const char *src, + char *dest, + int destsize) +{ + struct in_addr inp; + char buffer[OSP_SIZE_NORSTR]; + char *port; + + OSP_DEBUG_START; + + if (dest && destsize) { + dest[0] = '\0'; + + if (!switch_strlen_zero(src)) { + /* Copy IP address to temporary buffer */ + switch_copy_string(buffer, src, sizeof(buffer)); + + if((port = strchr(buffer, ':'))) { + *port = '\0'; + port++; + } + + if (inet_pton(AF_INET, buffer, &inp) == 1) { + if (port) { + switch_snprintf(dest, destsize, "[%s]:%s", buffer, port); + } else { + switch_snprintf(dest, destsize, "[%s]", buffer); + } + dest[destsize - 1] = '\0'; + } else { + switch_copy_string(dest, src, destsize); + } + } + + OSP_DEBUG("out: '%s'", dest); + } + + OSP_DEBUG_END; +} + +/* + * Convert "[x.x.x.x]:port" or "hostname:prot" to "address:port" format + * param src Source address string + * param dest Destination address string + * param destsize Size of dest buffer + * return + */ +static void osp_convert_outin( + const char *src, + char *dest, + int destsize) +{ + char buffer[OSP_SIZE_NORSTR]; + char *end; + char *port; + + OSP_DEBUG_START; + + if (dest && destsize) { + dest[0] = '\0'; + + if (!switch_strlen_zero(src)) { + switch_copy_string(buffer, src, sizeof(buffer)); + + if (buffer[0] == '[') { + if((port = strchr(buffer + 1, ':'))) { + *port = '\0'; + port++; + } + + if ((end = strchr(buffer + 1, ']'))) { + *end = '\0'; + } + + if (port) { + switch_snprintf(dest, destsize, "%s:%s", buffer + 1, port); + dest[destsize - 1] = '\0'; + } else { + switch_copy_string(dest, buffer + 1, destsize); + } + } else { + switch_copy_string(dest, src, destsize); + } + } + OSP_DEBUG("in: '%s'", dest); + } + + OSP_DEBUG_END; +} + +/* + * Always log AuthReq parameters + * param profile OSP profile + * param inbound Inbound info + * return + */ +static void osp_log_authreq( + osp_profile_t *profile, + osp_inbound_t *inbound) +{ + char *srvtype; + const char *source; + const char *srcdev; + char term[OSP_SIZE_NORSTR]; + int total; + + OSP_DEBUG_START; + + /* Get source device and source */ + if (profile->workmode == OSP_MODE_INDIRECT) { + source = inbound->srcdev; + if (switch_strlen_zero(inbound->actsrc)) { + srcdev = inbound->srcdev; + } else { + srcdev = inbound->actsrc; + } + } else { + source = profile->deviceip; + srcdev = inbound->srcdev; + } + + /* Get preferred destination for NP query */ + if (profile->srvtype == OSP_SRV_NPQUERY) { + srvtype = "npquery"; + if (switch_strlen_zero(inbound->tohost)) { + switch_copy_string(term, source, sizeof(term)); + } else { + if (switch_strlen_zero(inbound->toport)) { + switch_copy_string(term, inbound->tohost, sizeof(term)); + } else { + switch_snprintf(term, sizeof(term), "%s:%s", inbound->tohost, inbound->toport); + } + } + total = 1; + } else { + srvtype = "voice"; + term[0] = '\0'; + total = profile->maxdest; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, osp_global.loglevel, + "AuthReq: " + "srvtype '%s' " + "source '%s' " + "srcdev '%s' " + "srcnid '%s' " + "protocol '%s' " + "callid '%s' " + "calling '%s' " + "called '%s' " + "lnp '%s/%s/%d' " + "preferred '%s' " + "rpid '%s' " + "pai '%s' " + "div '%s/%s' " + "pci '%s' " + "cinfo '%s/%s/%s/%s/%s/%s/%s/%s' " + "maxcount '%d'\n", + srvtype, + source, + srcdev, + OSP_FILTER_NULLSTR(inbound->srcnid), + osp_get_protocolname(inbound->protocol), + OSP_FILTER_NULLSTR(inbound->callid), + inbound->calling, + inbound->called, + inbound->nprn, inbound->npcic, inbound->npdi, + term, + inbound->rpiduser, + inbound->paiuser, + inbound->divuser, inbound->divhost, + inbound->pciuser, + OSP_FILTER_NULLSTR(inbound->cinfo[0]), OSP_FILTER_NULLSTR(inbound->cinfo[1]), OSP_FILTER_NULLSTR(inbound->cinfo[2]), OSP_FILTER_NULLSTR(inbound->cinfo[3]), + OSP_FILTER_NULLSTR(inbound->cinfo[4]), OSP_FILTER_NULLSTR(inbound->cinfo[5]), OSP_FILTER_NULLSTR(inbound->cinfo[6]), OSP_FILTER_NULLSTR(inbound->cinfo[7]), + total); + + OSP_DEBUG_END; +} + +/* + * Always log AuthRsp parameters + * param results Routing info + * return + */ +static void osp_log_authrsp( + osp_results_t *results) +{ + OSP_DEBUG_START; + + switch_log_printf(SWITCH_CHANNEL_LOG, osp_global.loglevel, + "AuthRsp: " + "destcount '%d/%d' " + "transid '%"PRIu64"' " + "timelimit '%u' " + "calling '%s' " + "called '%s' " + "destination '%s' " + "destnid '%s' " + "lnp '%s/%s/%d' " + "protocol '%s' " + "supported '%d'\n", + results->count, + results->total, + results->transid, + results->timelimit, + results->calling, + results->called, + results->dest, + results->destnid, + results->nprn, results->npcic, results->npdi, + osp_get_protocolname(results->protocol), + results->supported); + + OSP_DEBUG_END; +} + +/* + * Alway log UsageInd parameters + * param results Route info + * param usage Usage info + * return + */ +static void osp_log_usageind( + osp_results_t *results, + osp_usage_t *usage) +{ + OSP_DEBUG_START; + + switch_log_printf(SWITCH_CHANNEL_LOG, osp_global.loglevel, + "UsageInd: " + "destcount '%d/%d' " + "transid '%"PRIu64"' " + "cause '%d' " + "release '%d' " + "times '%"PRId64"/%"PRId64"/%"PRId64"/%"PRId64"' " + "duration '%"PRId64"' " + "pdd '%"PRId64"' " + "codec '%s/%s' " + "rtpctets '%d/%d' " + "rtppackets '%d/%d'\n", + results->count, results->total, + results->transid, + results->cause ? results->cause : usage->cause, + usage->release, + usage->start / 1000000, usage->alert / 1000000, usage->connect / 1000000, usage->end / 1000000, + usage->duration / 1000000, + usage->pdd / 1000, + OSP_FILTER_NULLSTR(usage->srccodec), OSP_FILTER_NULLSTR(usage->destcodec), + usage->rtpsrcrepoctets, usage->rtpdestrepoctets, + usage->rtpsrcreppackets, usage->rtpdestreppackets); + + OSP_DEBUG_END; +} + +/* + * Get inbound info + * param channel Inbound channel + * param inbound Inbound info + * return + */ +static void osp_get_inbound( + switch_channel_t *channel, + osp_inbound_t *inbound) +{ + switch_caller_profile_t *caller; + const char *tmp; + int i; + char name[OSP_SIZE_NORSTR]; + + OSP_DEBUG_START; + + /* Cleanup buffer */ + memset(inbound, 0, sizeof(*inbound)); + + /* Get caller profile */ + caller = switch_channel_get_caller_profile(channel); + + /* osp_source_device */ + inbound->actsrc = switch_channel_get_variable(channel, OSP_VAR_SRCDEV); + OSP_DEBUG("actsrc: '%s'", OSP_FILTER_NULLSTR(inbound->actsrc)); + + /* Source device */ + inbound->srcdev = caller->network_addr; + OSP_DEBUG("srcdev: '%s'", OSP_FILTER_NULLSTR(inbound->srcdev)); + + /* osp_source_nid */ + inbound->srcnid = switch_channel_get_variable(channel, OSP_VAR_SRCNID); + OSP_DEBUG("srcnid: '%s'", OSP_FILTER_NULLSTR(inbound->srcnid)); + + /* Source signaling protocol */ + inbound->protocol = osp_get_protocol(caller->source); + OSP_DEBUG("protocol: '%d'", inbound->protocol); + + /* Call-ID */ + inbound->callid = switch_channel_get_variable(channel, OSP_FS_CALLID); + OSP_DEBUG("callid: '%s'", OSP_FILTER_NULLSTR(inbound->callid)); + + /* Calling number */ + if ((tmp = switch_channel_get_variable(channel, OSP_FS_FROMUSER))) { + osp_parse_userinfo(tmp, inbound->calling, sizeof(inbound->calling), NULL, 0, NULL, 0, NULL); + } else { + osp_parse_userinfo(caller->caller_id_number, inbound->calling, sizeof(inbound->calling), NULL, 0, NULL, 0, NULL); + } + OSP_DEBUG("calling: '%s'", inbound->calling); + + /* Called number and LNP parameters */ + osp_parse_userinfo(caller->destination_number, inbound->called, sizeof(inbound->called), inbound->nprn, sizeof(inbound->nprn), inbound->npcic, sizeof(inbound->npcic), + &inbound->npdi); + OSP_DEBUG("called: '%s'", inbound->called); + OSP_DEBUG("nprn: '%s'", inbound->nprn); + OSP_DEBUG("npcic: '%s'", inbound->npcic); + OSP_DEBUG("npdi: '%d'", inbound->npdi); + + /* To header */ + inbound->tohost = switch_channel_get_variable(channel, OSP_FS_TOHOST); + OSP_DEBUG("tohost: '%s'", OSP_FILTER_NULLSTR(inbound->tohost)); + inbound->toport = switch_channel_get_variable(channel, OSP_FS_TOPORT); + OSP_DEBUG("toport: '%s'", OSP_FILTER_NULLSTR(inbound->toport)); + + /* RPID calling number */ + if ((tmp = switch_channel_get_variable(channel, OSP_FS_RPID))) { + osp_parse_header_user(tmp, inbound->rpiduser, sizeof(inbound->rpiduser)); + } + OSP_DEBUG("RPID user: '%s'", inbound->rpiduser); + + /* PAI calling number */ + if ((tmp = switch_channel_get_variable(channel, OSP_FS_PAI))) { + osp_parse_userinfo(tmp, inbound->paiuser, sizeof(inbound->paiuser), NULL, 0, NULL, 0, NULL); + } + OSP_DEBUG("PAI user: '%s'", inbound->paiuser); + + /* DIV calling number */ + if ((tmp = switch_channel_get_variable(channel, OSP_FS_DIV))) { + osp_parse_header_user(tmp, inbound->divuser, sizeof(inbound->divuser)); + osp_parse_header_host(tmp, inbound->divhost, sizeof(inbound->divhost)); + } + OSP_DEBUG("DIV user: '%s'", inbound->divuser); + OSP_DEBUG("DIV host: '%s'", inbound->divhost); + + /* PCI calling number */ + if ((tmp = switch_channel_get_variable(channel, OSP_FS_PCI))) { + osp_parse_header_user(tmp, inbound->pciuser, sizeof(inbound->pciuser)); + } + OSP_DEBUG("PCI user: '%s'", inbound->pciuser); + + /* Custom info */ + for (i = 0; i < OSP_MAX_CINFO; i++) { + switch_snprintf(name, sizeof(name), "%s%d", OSP_VAR_CUSTOMINFO, i + 1); + inbound->cinfo[i] = switch_channel_get_variable(channel, name); + OSP_DEBUG("cinfo[%d]: '%s'", i, OSP_FILTER_NULLSTR(inbound->cinfo[i])); + } + + OSP_DEBUG_END; +} + +/* + * Get outbound settings + * param channel Inbound channel + * param outbound Outbound settings + * return + */ +static void osp_get_outbound( + switch_channel_t *channel, + osp_outbound_t *outbound) +{ + const char *tmp; + + OSP_DEBUG_START; + + /* Cleanup buffer */ + memset(outbound, 0, sizeof(*outbound)); + + /* Get destination network ID namd & location info */ + outbound->dniduserparam = switch_channel_get_variable(channel, OSP_VAR_DNIDUSERPARAM); + OSP_DEBUG("dniduserparam: '%s'", OSP_FILTER_NULLSTR(outbound->dniduserparam)); + outbound->dniduriparam = switch_channel_get_variable(channel, OSP_VAR_DNIDURIPARAM); + OSP_DEBUG("dniduriparam: '%s'", OSP_FILTER_NULLSTR(outbound->dniduriparam)); + + /* Get "user=phone" insert flag */ + tmp = switch_channel_get_variable(channel, OSP_VAR_USERPHONE); + if (!switch_strlen_zero(tmp)) { + outbound->userphone = switch_true(tmp); + } + OSP_DEBUG("userphone: '%d'", outbound->userphone); + + /* Get outbound proxy info */ + outbound->outproxy = switch_channel_get_variable(channel, OSP_VAR_OUTPROXY); + OSP_DEBUG("outporxy: '%s'", OSP_FILTER_NULLSTR(outbound->outproxy)); + + OSP_DEBUG_END; +} + +/* + * Get transaction info + * param channel Inbound channel + * param aleg If A-leg + * param results Route info + * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed + */ +static switch_status_t osp_get_transaction( + switch_channel_t *channel, + switch_bool_t aleg, + osp_results_t *results) +{ + const char *tmp; + osp_profile_t *profile; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + /* Get profile name */ + if (!(results->profile = switch_channel_get_variable(channel, OSP_VAR_PROFILE))) { + results->profile = OSP_DEF_PROFILE; + } + + /* Get transaction handle */ + if (osp_find_profile(results->profile, &profile) == SWITCH_STATUS_FALSE) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find profile '%s'\n", results->profile); + } else if (profile->provider == OSP_INVALID_HANDLE) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Disabled profile '%s'\n", results->profile); + } else if (!(tmp = switch_channel_get_variable(channel, OSP_VAR_TRANSACTION)) || (sscanf(tmp, "%d", &results->transaction) != 1)){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get transaction handle'\n"); + } else if (results->transaction == OSP_INVALID_HANDLE) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid transaction handle'\n"); + } else { + if (!(tmp = switch_channel_get_variable(channel, OSP_VAR_TRANSID)) || (sscanf(tmp, "%"PRIu64"", &results->transid) != 1)) { + results->transid = 0; + } + + /* Get destination total */ + if (!(tmp = switch_channel_get_variable(channel, OSP_VAR_ROUTETOTAL)) || (sscanf(tmp, "%u", &results->total) != 1)) { + results->total = 0; + } + + /* Get destination count */ + if (!(tmp = switch_channel_get_variable(channel, OSP_VAR_ROUTECOUNT)) || (sscanf(tmp, "%u", &results->count) != 1)) { + results->count = 0; + } + + /* + * Get termiantion cause + * The logic is + * 1. osp_next_function should get TCCode from last_bridge_hangup_cause + * 2. osp_on_reporting should get TCCode from osp_terimation_cause + */ + if (aleg) { + /* A-leg */ + if (!(tmp = switch_channel_get_variable(channel, OSP_VAR_TCCODE)) || (sscanf(tmp, "%u", &results->cause) != 1)) { + results->cause = 0; + } + } else { + /* B-leg */ + if ((tmp = switch_channel_get_variable(channel, OSP_FS_HANGUPCAUSE))) { + results->cause = switch_channel_str2cause(tmp); + } + } + + status = SWITCH_STATUS_SUCCESS; + } + OSP_DEBUG("profile: '%s'", results->profile); + OSP_DEBUG("transaction: '%d'", results->transaction); + OSP_DEBUG("transid: '%"PRIu64"'", results->transid); + OSP_DEBUG("total: '%d'", results->total); + OSP_DEBUG("count: '%d'", results->count); + OSP_DEBUG("cause: '%d'", results->cause); + + OSP_DEBUG_END; + + return status; +} + +/* + * Retrieve usage info + * param channel channel + * param originator Originator profile + * param terminator Terminator profile, not used at this time + * param results Route info + * param usage Usage info + * return + */ +static void osp_get_usage( + switch_channel_t *channel, + switch_caller_profile_t *originator, + switch_caller_profile_t *terminator_unused, + osp_results_t *results, + osp_usage_t *usage) +{ + const char *tmp; + switch_channel_timetable_t *times; + + OSP_DEBUG_START; + + /* Cleanup buffer */ + memset(usage, 0, sizeof(*usage)); + + /* Release source */ + usage->release = OSPC_RELEASE_UNKNOWN; + if (osp_get_protocol(originator->source) == OSPC_PROTNAME_SIP) { + tmp = switch_channel_get_variable(channel, OSP_FS_SIPRELEASE); + if (!tmp) { + usage->release = OSPC_RELEASE_UNDEFINED; + } else if (!strcasecmp(tmp, "send_bye")) { + usage->release = OSPC_RELEASE_DESTINATION; + } else if (!strcasecmp(tmp, "recv_bye")) { + usage->release = OSPC_RELEASE_SOURCE; + } else if (!strcasecmp(tmp, "send_refuse")) { + usage->release = OSPC_RELEASE_INTERNAL; + } else if (!strcasecmp(tmp, "send_cancel")) { + usage->release = OSPC_RELEASE_SOURCE; + } + } + OSP_DEBUG("release: '%d'", usage->release); + + /* Termiation cause */ + usage->cause = switch_channel_get_cause_q850(channel); + OSP_DEBUG("cause: '%d'", usage->cause); + + /* Timestamps */ + times = switch_channel_get_timetable(channel); + usage->start = times->created; + OSP_DEBUG("start: '%"PRIu64"'", usage->start); + usage->alert = times->progress; + OSP_DEBUG("alert: '%"PRIu64"'", usage->alert); + usage->connect = times->answered; + OSP_DEBUG("connect: '%"PRIu64"'", usage->connect); + usage->end = times->hungup; + OSP_DEBUG("end: '%"PRIu64"'", usage->end); + if (times->answered) { + usage->duration = times->hungup - times->answered; + OSP_DEBUG("duration: '%"PRIu64"'", usage->duration); + } + if (times->progress) { + usage->pdd = times->progress - usage->start; + OSP_DEBUG("pdd: '%"PRIu64"'", usage->pdd); + } + + /* Codecs */ + usage->srccodec = switch_channel_get_variable(channel, OSP_FS_SRCCODEC); + OSP_DEBUG("srccodec: '%s'", OSP_FILTER_NULLSTR(usage->srccodec)); + usage->destcodec = switch_channel_get_variable(channel, OSP_FS_DESTCODEC); + OSP_DEBUG("destcodec: '%s'", OSP_FILTER_NULLSTR(usage->destcodec)); + + /* QoS statistics */ + if (!(tmp = switch_channel_get_variable(channel, OSP_FS_RTPSRCREPOCTS)) || (sscanf(tmp, "%d", &usage->rtpsrcrepoctets) != 1)) { + usage->rtpsrcrepoctets = OSP_DEF_STATS; + } + OSP_DEBUG("rtpsrcrepoctets: '%d'", usage->rtpsrcrepoctets); + if (!(tmp = switch_channel_get_variable(channel, OSP_FS_RTPDESTREPOCTS)) || (sscanf(tmp, "%d", &usage->rtpdestrepoctets) != 1)) { + usage->rtpdestrepoctets = OSP_DEF_STATS; + } + OSP_DEBUG("rtpdestrepoctets: '%d'", usage->rtpdestrepoctets); + if (!(tmp = switch_channel_get_variable(channel, OSP_FS_RTPSRCREPPKTS)) || (sscanf(tmp, "%d", &usage->rtpsrcreppackets) != 1)) { + usage->rtpsrcreppackets = OSP_DEF_STATS; + } + OSP_DEBUG("rtpsrcreppackets: '%d'", usage->rtpsrcreppackets); + if (!(tmp = switch_channel_get_variable(channel, OSP_FS_RTPDESTREPPKTS)) || (sscanf(tmp, "%d", &usage->rtpdestreppackets) != 1)) { + usage->rtpdestreppackets = OSP_DEF_STATS; + } + OSP_DEBUG("rtpdestreppackets: '%d'", usage->rtpdestreppackets); + + OSP_DEBUG_END; +} + +/* + * Check destination + * param results Routing info + * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed + */ +static switch_status_t osp_check_destination( + osp_results_t *results) +{ + OSPE_DEST_OSPENABLED enabled; + OSPE_PROTOCOL_NAME protocol; + OSPE_OPERATOR_NAME type; + int error; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + if ((error = OSPPTransactionIsDestOSPEnabled(results->transaction, &enabled)) != OSPC_ERR_NO_ERROR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get destination OSP version, error '%d'\n", error); + } else if ((error = OSPPTransactionGetDestProtocol(results->transaction, &protocol)) != OSPC_ERR_NO_ERROR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get signaling protocol, error '%d'\n", error); + } else { + switch(protocol) { + case OSPC_PROTNAME_UNDEFINED: + case OSPC_PROTNAME_UNKNOWN: + protocol = osp_global.protocol; + case OSPC_PROTNAME_SIP: + case OSPC_PROTNAME_Q931: + case OSPC_PROTNAME_IAX: + case OSPC_PROTNAME_SKYPE: + results->protocol = protocol; + if (!switch_strlen_zero(osp_global.endpoint[protocol].module) && !switch_strlen_zero(osp_global.endpoint[protocol].profile)) { + results->supported = SWITCH_TRUE; + results->cause = 0; + status = SWITCH_STATUS_SUCCESS; + break; + } + case OSPC_PROTNAME_LRQ: + case OSPC_PROTNAME_T37: + case OSPC_PROTNAME_T38: + case OSPC_PROTNAME_SMPP: + case OSPC_PROTNAME_XMPP: + default: + results->protocol = protocol; + results->supported = SWITCH_FALSE; + /* Q.850 protocol error, unspecified */ + results->cause = 111; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported protocol '%d'\n", protocol); + break; + } + OSP_DEBUG("protocol: '%d'", results->protocol); + OSP_DEBUG("supported: '%d'", results->supported); + OSP_DEBUG("cause: '%d'", results->cause); + + if ((error = OSPPTransactionGetDestinationNetworkId(results->transaction, sizeof(results->destnid), results->destnid)) != OSPC_ERR_NO_ERROR) { + results->destnid[0] = '\0'; + } + OSP_DEBUG("destnid: '%s'", results->destnid); + + error = OSPPTransactionGetNumberPortabilityParameters( + results->transaction, + sizeof(results->nprn), + results->nprn, + sizeof(results->npcic), + results->npcic, + &results->npdi); + if (error != OSPC_ERR_NO_ERROR) { + results->nprn[0] = '\0'; + results->npcic[0] = '\0'; + results->npdi = 0; + } + OSP_DEBUG("nprn: '%s'", results->nprn); + OSP_DEBUG("npcic: '%s'", results->npcic); + OSP_DEBUG("npdi: '%d'", results->npdi); + + for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) { + if ((error = OSPPTransactionGetOperatorName(results->transaction, type, sizeof(results->opname[type]), results->opname[type])) != OSPC_ERR_NO_ERROR) { + results->opname[type][0] = '\0'; + } + OSP_DEBUG("opname[%d]: '%s'", type, results->opname[type]); + } + + osp_log_authrsp(results); + } + + OSP_DEBUG_END; + + return status; +} + +/* + * Build parameter string for each channel + * param results Route info + * param buffer Buffer + * param bufsize Buffer size + * return + */ +static void osp_build_eachparam( + osp_results_t *results, + char *buffer, + switch_size_t bufsize) +{ + OSP_DEBUG_START; + + if (results && buffer && bufsize) { + switch_snprintf(buffer, bufsize, "[%s=%s]", OSP_FS_OUTCALLING, results->calling); + OSP_DEBUG("eachparam: '%s'", buffer); + } + + OSP_DEBUG_END; +} + +/* + * Build endpoint string + * param results Route info + * param outbound Outbound settings + * param buffer Buffer + * param bufsize Buffer size + * return + */ +static void osp_build_endpoint( + osp_results_t *results, + osp_outbound_t *outbound, + char *buffer, + switch_size_t bufsize) +{ + char *head = buffer; + switch_size_t len, size = bufsize; + + OSP_DEBUG_START; + + if (results && buffer && bufsize) { + switch (results->protocol) { + case OSPC_PROTNAME_SIP: + /* module/profile/called */ + switch_snprintf(head, size, "%s/%s/%s", osp_global.endpoint[OSPC_PROTNAME_SIP].module, osp_global.endpoint[OSPC_PROTNAME_SIP].profile, results->called); + OSP_ADJUST_LEN(head, size, len); + + /* RN */ + if (!switch_strlen_zero_buf(results->nprn)) { + switch_snprintf(head, size, ";rn=%s", results->nprn); + OSP_ADJUST_LEN(head, size, len); + } + + /* CIC */ + if (!switch_strlen_zero_buf(results->npcic)) { + switch_snprintf(head, size, ";cic=%s", results->npcic); + OSP_ADJUST_LEN(head, size, len); + } + + /* NPDI */ + if (results->npdi) { + switch_snprintf(head, size, ";npdi"); + OSP_ADJUST_LEN(head, size, len); + } + + /* User parameter destination network ID */ + if (!switch_strlen_zero(outbound->dniduserparam) && !switch_strlen_zero_buf(results->destnid)) { + switch_snprintf(head, size, ";%s=%s", outbound->dniduserparam, results->destnid); + OSP_ADJUST_LEN(head, size, len); + } + + /* Destination */ + switch_snprintf(head, size, "@%s", results->dest); + OSP_ADJUST_LEN(head, size, len); + + /* URI parameter destination network ID */ + if (!switch_strlen_zero(outbound->dniduriparam) && !switch_strlen_zero_buf(results->destnid)) { + switch_snprintf(head, size, ";%s=%s", outbound->dniduriparam, results->destnid); + OSP_ADJUST_LEN(head, size, len); + } + + /* user=phone */ + if (outbound->userphone) { + switch_snprintf(head, size, ";user=phone"); + OSP_ADJUST_LEN(head, size, len); + } + + /* Outbound proxy */ + if (!switch_strlen_zero(outbound->outproxy)) { + switch_snprintf(head, size, ";fs_path=sip:%s", outbound->outproxy); + OSP_ADJUST_LEN(head, size, len); + } + break; + case OSPC_PROTNAME_Q931: + /* module/profile/called@destination */ + switch_snprintf(head, size, "%s/%s/%s@%s", osp_global.endpoint[OSPC_PROTNAME_Q931].module, osp_global.endpoint[OSPC_PROTNAME_Q931].profile, + results->called, results->dest); + OSP_ADJUST_LEN(head, size, len); + break; + case OSPC_PROTNAME_IAX: + /* module/profile/destination/called */ + switch_snprintf(head, size, "%s/%s/%s/%s", osp_global.endpoint[OSPC_PROTNAME_Q931].module, osp_global.endpoint[OSPC_PROTNAME_Q931].profile, + results->dest, results->called); + OSP_ADJUST_LEN(head, size, len); + break; + case OSPC_PROTNAME_SKYPE: + /* module/profile/called */ + switch_snprintf(head, size, "%s/%s/%s", osp_global.endpoint[OSPC_PROTNAME_Q931].module, osp_global.endpoint[OSPC_PROTNAME_Q931].profile, results->called); + OSP_ADJUST_LEN(head, size, len); + break; + default: + buffer[0] = '\0'; + break; + } + OSP_DEBUG("endpoint: '%s'", buffer); + } + + OSP_DEBUG_END; +} + +/* + * Create route string + * param outbound Outbound info + * param results Routing info + * param buffer Buffer + * param bufsize Buffer size + * return + */ +static void osp_create_route( + osp_outbound_t *outbound, + osp_results_t *results, + char *buffer, + switch_size_t bufsize) +{ + char eachparam[OSP_SIZE_NORSTR]; + char endpoint[OSP_SIZE_NORSTR]; + + OSP_DEBUG_START; + + /* Build dial string for each channel part */ + osp_build_eachparam(results, eachparam, sizeof(eachparam)); + + /* Build dial string for endpoint part */ + osp_build_endpoint(results, outbound, endpoint, sizeof(endpoint)); + + /* Build dail string */ + switch_snprintf(buffer, bufsize, "%s%s", eachparam, endpoint); + OSP_DEBUG("route: '%s'", buffer); + + OSP_DEBUG_END; +} + +/* + * Do AuthReq + * param profile OSP profile + * param inbound Call originator info + * param results Routing info + * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed + */ +static switch_status_t osp_request_auth( + osp_profile_t *profile, + osp_inbound_t *inbound, + osp_results_t *results) +{ + const char *source; + const char *srcdev; + char tmp[OSP_SIZE_NORSTR]; + char src[OSP_SIZE_NORSTR]; + char dev[OSP_SIZE_NORSTR]; + char term[OSP_SIZE_NORSTR]; + const char *preferred[2] = { NULL }; + OSPTTRANS *context; + int i, error; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + /* Set source network ID */ + OSPPTransactionSetNetworkIds(results->transaction, inbound->srcnid, NULL); + + /* Set source signaling protocol */ + OSPPTransactionSetProtocol(results->transaction, OSPC_PROTTYPE_SOURCE, inbound->protocol); + + /* Set source LNP parameters */ + OSPPTransactionSetNumberPortability(results->transaction, inbound->nprn, inbound->npcic, inbound->npdi); + + /* Set RPID */ + OSPPTransactionSetRemotePartyId(results->transaction, OSPC_NFORMAT_E164, inbound->rpiduser); + + /* Set PAI */ + OSPPTransactionSetAssertedId(results->transaction, OSPC_NFORMAT_E164, inbound->paiuser); + + /* Set diversion */ + osp_convert_inout(inbound->divhost, tmp, sizeof(tmp)); + OSPPTransactionSetDiversion(results->transaction, inbound->divuser, tmp); + + /* Set PCI */ + OSPPTransactionSetChargeInfo(results->transaction, OSPC_NFORMAT_E164, inbound->pciuser); + + /* Set custom info */ + for (i = 0; i < OSP_MAX_CINFO; i++) { + if (!switch_strlen_zero(inbound->cinfo[i])) { + OSPPTransactionSetCustomInfo(results->transaction, i, inbound->cinfo[i]); + } + } + + /* Device info and source */ + if (profile->workmode == OSP_MODE_INDIRECT) { + source = inbound->srcdev; + if (switch_strlen_zero(inbound->actsrc)) { + srcdev = inbound->srcdev; + } else { + srcdev = inbound->actsrc; + } + } else { + source = profile->deviceip; + srcdev = inbound->srcdev; + } + osp_convert_inout(source, src, sizeof(src)); + osp_convert_inout(srcdev, dev, sizeof(dev)); + + /* Preferred and max destinations */ + if (profile->srvtype == OSP_SRV_NPQUERY) { + OSPPTransactionSetServiceType(results->transaction, OSPC_SERVICE_NPQUERY); + + if (switch_strlen_zero(inbound->tohost)) { + switch_copy_string(term, src, sizeof(term)); + } else { + if (switch_strlen_zero(inbound->toport)) { + switch_copy_string(tmp, inbound->tohost, sizeof(tmp)); + } else { + switch_snprintf(tmp, sizeof(tmp), "%s:%s", inbound->tohost, inbound->toport); + } + osp_convert_inout(tmp, term, sizeof(term)); + } + preferred[0] = term; + + results->total = 1; + } else { + OSPPTransactionSetServiceType(results->transaction, OSPC_SERVICE_VOICE); + + results->total = profile->maxdest; + } + + OSP_DEBUG_MSG("RequestAuthorisation"); + + /* Request authorization */ + error = OSPPTransactionRequestAuthorisation( + results->transaction, /* Transaction handle */ + src, /* Source */ + dev, /* Source device */ + inbound->calling, /* Calling */ + OSPC_NFORMAT_E164, /* Calling format */ + inbound->called, /* Called */ + OSPC_NFORMAT_E164, /* Called format */ + NULL, /* User */ + 0, /* Number of callids */ + NULL, /* Callids */ + preferred, /* Preferred destinations */ + &results->total, /* Destination number */ + NULL, /* Log buffer size */ + NULL); /* Log buffer */ + if (error != OSPC_ERR_NO_ERROR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to request routing for '%s/%s', error '%d'\n", inbound->calling, inbound->called, error); + results->total = 0; + } else if (results->total == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Without destination\n"); + } else { + context = OSPPTransactionGetContext(results->transaction, &error); + if (error == OSPC_ERR_NO_ERROR) { + results->transid = context->TransactionID; + } else { + results->transid = 0; + } + status = SWITCH_STATUS_SUCCESS; + } + OSP_DEBUG("transid: '%"PRIu64"'", results->transid); + OSP_DEBUG("total: '%d'", results->total); + + OSP_DEBUG_END; + + return status; +} + +/* + * Get first destination + * param results Routing info + * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed + */ +static switch_status_t osp_get_first( + osp_results_t *results) +{ + int error; + char term[OSP_SIZE_NORSTR]; + unsigned int callidlen = 0, tokenlen = 0; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + /* Set destination count */ + results->count = 1; + + OSP_DEBUG_MSG("GetFirstDestination"); + + /* Get first destination */ + error = OSPPTransactionGetFirstDestination( + results->transaction, /* Transaction handle */ + 0, /* Timestamp buffer size */ + NULL, /* Valid after */ + NULL, /* Valid until */ + &results->timelimit, /* Call duration limit */ + &callidlen, /* Callid buffer size */ + NULL, /* Callid buffer */ + sizeof(results->called), /* Called buffer size */ + results->called, /* Called buffer */ + sizeof(results->calling), /* Calling buffer size */ + results->calling, /* Calling buffer */ + sizeof(term), /* Destination buffer size */ + term, /* Destination buffer */ + 0, /* Destination device buffer size */ + NULL, /* Destination device buffer */ + &tokenlen, /* Token buffer length */ + NULL); /* Token buffer */ + if (error != OSPC_ERR_NO_ERROR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get first destination, error '%d'\n", error); + } else { + osp_convert_outin(term, results->dest, sizeof(results->dest)); + + /* Check destination */ + status = osp_check_destination(results); + } + OSP_DEBUG("status: '%d'", status); + + OSP_DEBUG_END; + + return status; +} + +/* + * Get next destination + * param results Routing info + * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed + */ +static switch_status_t osp_get_next( + osp_results_t *results) +{ + int error; + char term[OSP_SIZE_NORSTR]; + unsigned int callidlen = 0, tokenlen = 0; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + while ((status == SWITCH_STATUS_FALSE) && (results->count < results->total)) { + /* Set destination count */ + results->count++; + + OSP_DEBUG_MSG("GetNextDestination"); + + /* Get next destination */ + error = OSPPTransactionGetNextDestination( + results->transaction, /* Transsaction handle */ + results->cause, /* Failure reason */ + 0, /* Timestamp buffer size */ + NULL, /* Valid after */ + NULL, /* Valid until */ + &results->timelimit, /* Call duration limit */ + &callidlen, /* Callid buffer size */ + NULL, /* Callid buffer */ + sizeof(results->called), /* Called buffer size */ + results->called, /* Called buffer */ + sizeof(results->calling), /* Calling buffer size */ + results->calling, /* Calling buffer */ + sizeof(term), /* Destination buffer size */ + term, /* Destination buffer */ + 0, /* Destination device buffer size */ + NULL, /* Destination device buffer */ + &tokenlen, /* Token buffer length */ + NULL); /* Token buffer */ + if (error != OSPC_ERR_NO_ERROR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get destination, error '%d'\n", error); + break; + } else { + osp_convert_outin(term, results->dest, sizeof(results->dest)); + + /* Check destination */ + status = osp_check_destination(results); + } + } + OSP_DEBUG("status: '%d'", status); + + OSP_DEBUG_END; + + return status; +} + +/* + * Report usage + * param results Route info + * param usage Usage info + * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed + */ +static switch_status_t osp_report_usage( + osp_results_t *results, + osp_usage_t *usage) +{ + int error; + unsigned int dummy = 0; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + /* Set role info */ + OSPPTransactionSetRoleInfo(results->transaction, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_FREESWITCH); + + /* Set termination cause */ + if (results->cause) { + OSPPTransactionRecordFailure(results->transaction, results->cause); + } else { + OSPPTransactionRecordFailure(results->transaction, usage->cause); + } + + /* Set codecs */ + if (!switch_strlen_zero(usage->srccodec)) { + OSPPTransactionSetCodec(results->transaction, OSPC_CODEC_SOURCE, usage->srccodec); + } + if (!switch_strlen_zero(usage->destcodec)) { + OSPPTransactionSetCodec(results->transaction, OSPC_CODEC_DESTINATION, usage->destcodec); + } + + /* Set QoS statistics */ + if (usage->rtpsrcrepoctets != OSP_DEF_STATS) { + OSPPTransactionSetOctets(results->transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, usage->rtpsrcrepoctets); + } + if (usage->rtpdestrepoctets != OSP_DEF_STATS) { + OSPPTransactionSetOctets(results->transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, usage->rtpdestrepoctets); + } + if (usage->rtpsrcreppackets != OSP_DEF_STATS) { + OSPPTransactionSetPackets(results->transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, usage->rtpsrcreppackets); + } + if (usage->rtpdestreppackets != OSP_DEF_STATS) { + OSPPTransactionSetPackets(results->transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, usage->rtpdestreppackets); + } + + OSP_DEBUG_MSG("ReportUsage"); + + /* Report usage */ + error = OSPPTransactionReportUsage( + results->transaction, /* Transaction handle */ + usage->duration / 1000000, /* Duration */ + usage->start / 1000000, /* Start time */ + usage->end / 1000000, /* End time */ + usage->alert / 1000000, /* Alert time */ + usage->connect / 1000000, /* Connect time */ + usage->alert, /* If PDD exist (call ringed) */ + usage->pdd / 1000, /* Post dial delay, in ms */ + usage->release, /* Release source */ + NULL, /* Conference ID */ + OSP_DEF_STATS, /* Loss packet sent */ + OSP_DEF_STATS, /* Loss fraction sent */ + OSP_DEF_STATS, /* Loss packet received */ + OSP_DEF_STATS, /* Loss fraction received */ + &dummy, /* Detail log buffer size */ + NULL); /* Detail log buffer */ + if (error != OSPC_ERR_NO_ERROR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to report usage, error '%d'\n", error); + } else { + status = SWITCH_STATUS_SUCCESS; + } + + /* Delete transaction handle */ + OSPPTransactionDelete(results->transaction); + + OSP_DEBUG_END; + + return status; +} + +/* + * Export OSP lookup status to channel + * param channel Originator channel + * param status OSP lookup status + * param outbound Outbound info + * param results Routing info + * return + */ +static void osp_export_lookup( + switch_channel_t *channel, + switch_status_t status, + osp_outbound_t *outbound, + osp_results_t *results) +{ + char value[OSP_SIZE_ROUSTR]; + + OSP_DEBUG_START; + + /* Profile name */ + switch_channel_set_variable_var_check(channel, OSP_VAR_PROFILE, results->profile, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_PROFILE, results->profile); + + /* Transaction handle */ + switch_snprintf(value, sizeof(value), "%d", results->transaction); + switch_channel_set_variable_var_check(channel, OSP_VAR_TRANSACTION, value, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_TRANSACTION, value); + + /* Transaction ID */ + switch_snprintf(value, sizeof(value), "%"PRIu64"", results->transid); + switch_channel_set_variable_var_check(channel, OSP_VAR_TRANSID, value, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_TRANSID, value); + + /* OSP lookup status */ + switch_snprintf(value, sizeof(value), "%d", status); + switch_channel_set_variable_var_check(channel, OSP_VAR_LOOKUPSTATUS, value, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_LOOKUPSTATUS, value); + + /* Destination total */ + switch_snprintf(value, sizeof(value), "%d", results->total); + switch_channel_set_variable_var_check(channel, OSP_VAR_ROUTETOTAL, value, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_ROUTETOTAL, value); + + /* Destination count */ + switch_snprintf(value, sizeof(value), "%d", results->count); + switch_channel_set_variable_var_check(channel, OSP_VAR_ROUTECOUNT, value, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_ROUTECOUNT, value); + + /* Dial string */ + if (status == SWITCH_STATUS_SUCCESS) { + osp_create_route(outbound, results, value, sizeof(value)); + switch_channel_set_variable_var_check(channel, OSP_VAR_AUTOROUTE, value, SWITCH_FALSE); + } else { + value[0] = '\0'; + switch_channel_set_variable(channel, OSP_VAR_AUTOROUTE, NULL); + } + OSP_DEBUG("%s: '%s'", OSP_VAR_AUTOROUTE, value); + + /* Termiantion cause */ + if (results->cause) { + switch_snprintf(value, sizeof(value), "%d", results->cause); + switch_channel_set_variable_var_check(channel, OSP_VAR_TCCODE, value, SWITCH_FALSE); + } else { + value[0] = '\0'; + switch_channel_set_variable(channel, OSP_VAR_TCCODE, NULL); + } + OSP_DEBUG("%s: '%s'", OSP_VAR_TCCODE, value); + + OSP_DEBUG_END; +} + +/* + * Export OSP next status to channel + * param channel Originator channel + * param status OSP next status + * param outbound Outbound info + * param results Routing info + * return + */ +static void osp_export_next( + switch_channel_t *channel, + switch_status_t status, + osp_outbound_t *outbound, + osp_results_t *results) +{ + char value[OSP_SIZE_NORSTR]; + + OSP_DEBUG_START; + + /* OSP next status */ + switch_snprintf(value, sizeof(value), "%d", status); + switch_channel_set_variable_var_check(channel, OSP_VAR_NEXTSTATUS, value, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_NEXTSTATUS, value); + + /* Destination count */ + switch_snprintf(value, sizeof(value), "%d", results->count); + switch_channel_set_variable_var_check(channel, OSP_VAR_ROUTECOUNT, value, SWITCH_FALSE); + OSP_DEBUG("%s: '%s'", OSP_VAR_ROUTECOUNT, value); + + /* Dial string */ + if (status == SWITCH_STATUS_SUCCESS) { + osp_create_route(outbound, results, value, sizeof(value)); + switch_channel_set_variable_var_check(channel, OSP_VAR_AUTOROUTE, value, SWITCH_FALSE); + } else { + value[0] = '\0'; + switch_channel_set_variable(channel, OSP_VAR_AUTOROUTE, NULL); + } + OSP_DEBUG("%s: '%s'", OSP_VAR_AUTOROUTE, value); + + /* Termiantion cause */ + if (results->cause) { + switch_snprintf(value, sizeof(value), "%d", results->cause); + switch_channel_set_variable_var_check(channel, OSP_VAR_TCCODE, value, SWITCH_FALSE); + } else { + value[0] = '\0'; + switch_channel_set_variable(channel, OSP_VAR_TCCODE, NULL); + } + OSP_DEBUG("%s: '%s'", OSP_VAR_TCCODE, value); + + OSP_DEBUG_END; +} + +/* + * Request auth and get first OSP route + * param channel Originator channel + * param results Routing info + * return + */ +static void osp_do_lookup( + switch_channel_t *channel, + osp_results_t *results) +{ + int error; + osp_profile_t *profile; + osp_inbound_t inbound; + osp_outbound_t outbound; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + if (osp_find_profile(results->profile, &profile) == SWITCH_STATUS_FALSE) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find profile '%s'\n", results->profile); + } else if (profile->provider == OSP_INVALID_HANDLE) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Disabled profile '%s'\n", results->profile); + } else if ((error = OSPPTransactionNew(profile->provider, &results->transaction)) != OSPC_ERR_NO_ERROR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create transaction handle, error '%d'\n", error); + } else { + /* Get inbound info */ + osp_get_inbound(channel, &inbound); + + /* Log AuthReq parameters */ + osp_log_authreq(profile, &inbound); + + /* Do AuthReq */ + if (osp_request_auth(profile, &inbound, results) == SWITCH_STATUS_SUCCESS) { + /* Get route */ + if ((osp_get_first(results) == SWITCH_STATUS_SUCCESS) || (osp_get_next(results) == SWITCH_STATUS_SUCCESS)) { + /* Get outbound info */ + osp_get_outbound(channel, &outbound); + status = SWITCH_STATUS_SUCCESS; + } + } + } + + /* Export OSP lookup info */ + osp_export_lookup(channel, status, &outbound, results); + + OSP_DEBUG_END; +} + +/* + * Get next OSP route + * param channel Originator channel + * param results Routing info + * return + */ +static void osp_do_next( + switch_channel_t *channel, + osp_results_t *results) +{ + osp_outbound_t outbound; + switch_status_t status = SWITCH_STATUS_FALSE; + + OSP_DEBUG_START; + + if (osp_get_transaction(channel, SWITCH_FALSE, results) == SWITCH_STATUS_SUCCESS) { + /* Get next OSP route */ + if ((status = osp_get_next(results)) == SWITCH_STATUS_SUCCESS) { + /* Get outbound info */ + osp_get_outbound(channel, &outbound); + } + } + + /* Export OSP next info */ + osp_export_next(channel, status, &outbound, results); + + OSP_DEBUG_END; +} + +/* + * Report OSP usage + * param channel Originator channel + * param originator Originate profile + * param terminator Terminate profile + * param results Routing info + * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed + */ +static switch_status_t osp_do_report( + switch_channel_t *channel, + switch_caller_profile_t *originator, + switch_caller_profile_t *terminator, + osp_results_t *results) +{ + osp_usage_t usage; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + OSP_DEBUG_START; + + if (osp_get_transaction(channel, SWITCH_TRUE, results) == SWITCH_STATUS_SUCCESS) { + /* Do not report usage for failed AuthReq */ + if (results->total) { + /* Get usage info */ + osp_get_usage(channel, originator, terminator, results, &usage); + + /* Log usage info */ + osp_log_usageind(results, &usage); + + /* Report OSP usage */ + status = osp_report_usage(results, &usage); + } else { + OSP_DEBUG_MSG("Do not report usage"); + } + } + + OSP_DEBUG_END; + + return status; +} + +/* + * OSP module CLI command + * Macro expands to: + * static switch_status_t osp_cli_function(_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) + */ +SWITCH_STANDARD_API(osp_cli_function) { int i, argc = 0; char *argv[2] = { 0 }; @@ -738,18 +2409,23 @@ SWITCH_STANDARD_API(osp_api_function) osp_profile_t *profile; char *loglevel; + OSP_DEBUG_START; + if (session) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This function cannot be called from the dialplan.\n"); + OSP_DEBUG_END; return SWITCH_STATUS_FALSE; } if (switch_strlen_zero(cmd)) { stream->write_function(stream, "Usage: osp status\n"); + OSP_DEBUG_END; return SWITCH_STATUS_SUCCESS; } if (!(params = switch_safe_strdup(cmd))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate parameters\n"); + OSP_DEBUG_END; return SWITCH_STATUS_MEMERR; } @@ -757,8 +2433,8 @@ SWITCH_STANDARD_API(osp_api_function) param = argv[0]; if (!strcasecmp(param, "status")) { stream->write_function(stream, "=============== OSP Module Settings & Status ===============\n"); - stream->write_function(stream, " debug-info: %s\n", osp_globals.debug ? "enabled" : "disabled"); - switch (osp_globals.loglevel) { + stream->write_function(stream, " debug-info: %s\n", osp_global.debug ? "enabled" : "disabled"); + switch (osp_global.loglevel) { case SWITCH_LOG_CONSOLE: loglevel = "console"; break; @@ -786,39 +2462,39 @@ SWITCH_STANDARD_API(osp_api_function) break; } stream->write_function(stream, " log-level: %s\n", loglevel); - stream->write_function(stream, " crypto-hardware: %s\n", osp_globals.hardware ? "enabled" : "disabled"); - if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_SIP]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_SIP])) { + stream->write_function(stream, " crypto-hardware: %s\n", osp_global.hardware ? "enabled" : "disabled"); + if (switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_SIP].module) || switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_SIP].profile)) { stream->write_function(stream, " sip: unsupported\n"); } else { stream->write_function(stream, " sip: %s/%s\n", - osp_globals.modules[OSPC_PROTNAME_SIP], osp_globals.profiles[OSPC_PROTNAME_SIP]); + osp_global.endpoint[OSPC_PROTNAME_SIP].module, osp_global.endpoint[OSPC_PROTNAME_SIP].profile); } - if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_Q931]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_Q931])) { + if (switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_Q931].module) || switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_Q931].profile)) { stream->write_function(stream, " h323: unsupported\n"); } else { stream->write_function(stream, " h323: %s/%s\n", - osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931]); + osp_global.endpoint[OSPC_PROTNAME_Q931].module, osp_global.endpoint[OSPC_PROTNAME_Q931].profile); } - if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_IAX]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_IAX])) { + if (switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_IAX].module) || switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_IAX].profile)) { stream->write_function(stream, " iax: unsupported\n"); } else { stream->write_function(stream, " iax: %s/%s\n", - osp_globals.modules[OSPC_PROTNAME_IAX], osp_globals.profiles[OSPC_PROTNAME_IAX]); + osp_global.endpoint[OSPC_PROTNAME_IAX].module, osp_global.endpoint[OSPC_PROTNAME_IAX].profile); } - if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_SKYPE]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_SKYPE])) { + if (switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_SKYPE].module) || switch_strlen_zero(osp_global.endpoint[OSPC_PROTNAME_SKYPE].profile)) { stream->write_function(stream, " skype: unsupported\n"); } else { stream->write_function(stream, " skype: %s/%s\n", - osp_globals.modules[OSPC_PROTNAME_SKYPE], osp_globals.profiles[OSPC_PROTNAME_SKYPE]); + osp_global.endpoint[OSPC_PROTNAME_SKYPE].module, osp_global.endpoint[OSPC_PROTNAME_SKYPE].profile); } - stream->write_function(stream, " default-protocol: %s\n", osp_get_protocol(osp_globals.protocol)); + stream->write_function(stream, " default-protocol: %s\n", osp_get_protocolname(osp_global.protocol)); stream->write_function(stream, "============== OSP Profile Settings & Status ==============\n"); for (profile = osp_profiles; profile; profile = profile->next) { stream->write_function(stream, "Profile: %s\n", profile->name); - for (i = 0; i < profile->spnum; i++) { - stream->write_function(stream, " service-point-url: %s\n", profile->spurls[i]); + for (i = 0; i < profile->spnumber; i++) { + stream->write_function(stream, " service-point-url: %s\n", profile->spurl[i]); } - stream->write_function(stream, " device-ip: %s\n", profile->device); + stream->write_function(stream, " device-ip: %s\n", profile->deviceip); stream->write_function(stream, " ssl-lifetime: %d\n", profile->lifetime); stream->write_function(stream, " http-max-connections: %d\n", profile->maxconnect); stream->write_function(stream, " http-persistence: %d\n", profile->persistence); @@ -855,1518 +2531,74 @@ SWITCH_STANDARD_API(osp_api_function) switch_safe_free(params); + OSP_DEBUG_END; + return SWITCH_STATUS_SUCCESS; } -/* - * Parse Userinfo for user and LNP - * param userinfo SIP URI userinfo - * param user User part - * param usersize Size of user buffer - * param rn Routing number - * param rnsize Size of rn buffer - * param cic Carrier Identification Cod - * param cicsize Size of cic buffer - * param npdi NP Database Dip Indicator - * return - */ -static void osp_parse_userinfo( - const char *userinfo, - char *user, - switch_size_t usersize, - char *rn, - switch_size_t rnsize, - char *cic, - switch_size_t cicsize, - int *npdi) -{ - char buffer[OSP_SIZE_NORSTR]; - char *item; - char *tmp; - - if (!switch_strlen_zero(userinfo)) { - switch_copy_string(buffer, userinfo, sizeof(buffer)); - item = strtok_r(buffer, OSP_USER_DELIM, &tmp); - if (user && usersize) { - switch_copy_string(user, item, usersize); - } - for (item = strtok_r(NULL, OSP_USER_DELIM, &tmp); item; item = strtok_r(NULL, OSP_USER_DELIM, &tmp)) { - if (!strncasecmp(item, "rn=", 3)) { - if (rn && rnsize) { - switch_copy_string(rn, item + 3, rnsize); - } - } else if (!strncasecmp(item, "cic=", 4)) { - if (cic && cicsize) { - switch_copy_string(cic, item + 4, cicsize); - } - } else if (!strcasecmp(item, "npdi")) { - *npdi = 1; - } - } - } -} - -/* - * Parse SIP header user - * param header SIP header - * param user SIP header user - * param usersize Size of user buffer - * return - */ -static void osp_parse_header_user( - const char *header, - char *user, - switch_size_t usersize) -{ - char buffer[OSP_SIZE_NORSTR]; - char *head; - char *tmp; - char *item; - - if (!switch_strlen_zero(header) && user && usersize) { - *user = '\0'; - switch_copy_string(buffer, header, sizeof(buffer)); - if ((head = strstr(buffer, "sip:"))) { - head += 4; - if ((tmp = strchr(head, OSP_URI_DELIM))) { - *tmp = '\0'; - item = strtok_r(head, OSP_USER_DELIM, &tmp); - switch_copy_string(user, item, usersize); - } - } - } -} - -/* - * Parse SIP header host - * param header SIP header - * param host SIP header host - * param hostsize Size of host buffer - * return - */ -static void osp_parse_header_host( - const char *header, - char *host, - switch_size_t hostsize) -{ - char buffer[OSP_SIZE_NORSTR]; - char *head; - char *tmp; - - if (!switch_strlen_zero(header) && host && hostsize) { - *host = '\0'; - switch_copy_string(buffer, header, sizeof(buffer)); - if ((head = strstr(buffer, "sip:"))) { - head += 4; - if ((tmp = strchr(head, OSP_URI_DELIM))) { - head = tmp + 1; - } - tmp = strtok(head, OSP_HOST_DELIM); - switch_copy_string(host, tmp, hostsize); - } - } -} - -/* - * Log AuthReq parameters - * param profile OSP profile - * param inbound Inbound info - * return - */ -static void osp_log_authreq( - osp_profile_t *profile, - osp_inbound_t *inbound) -{ - char *srvtype; - const char *source; - const char *srcdev; - char term[OSP_SIZE_NORSTR]; - int total; - - if (osp_globals.debug) { - if (profile->workmode == OSP_MODE_INDIRECT) { - source = inbound->srcdev; - if (switch_strlen_zero(inbound->actsrc)) { - srcdev = inbound->srcdev; - } else { - srcdev = inbound->actsrc; - } - } else { - source = profile->device; - srcdev = inbound->srcdev; - } - - if (profile->srvtype == OSP_SRV_NPQUERY) { - srvtype = "npquery"; - if (switch_strlen_zero(inbound->tohost)) { - switch_copy_string(term, source, sizeof(term)); - } else { - if (switch_strlen_zero(inbound->toport)) { - switch_copy_string(term, inbound->tohost, sizeof(term)); - } else { - switch_snprintf(term, sizeof(term), "%s:%s", inbound->tohost, inbound->toport); - } - } - total = 1; - } else { - srvtype = "voice"; - term[0] = '\0'; - total = profile->maxdest; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, osp_globals.loglevel, - "AuthReq: " - "srvtype '%s' " - "source '%s' " - "srcdev '%s' " - "protocol '%s' " - "calling '%s' " - "called '%s' " - "lnp '%s/%s/%d' " - "prefer '%s' " - "rpid '%s' " - "pai '%s' " - "div '%s/%s' " - "pci '%s' " - "srcnid '%s' " - "cinfo '%s/%s/%s/%s/%s/%s/%s/%s' " - "maxcount '%d'\n", - srvtype, - source, - srcdev, - osp_get_protocol(inbound->protocol), - inbound->calling, - inbound->called, - inbound->nprn, inbound->npcic, inbound->npdi, - term, - inbound->rpiduser, - inbound->paiuser, - inbound->divuser, inbound->divhost, - inbound->pciuser, - osp_filter_null(inbound->srcnid), - osp_filter_null(inbound->cinfo[0]), osp_filter_null(inbound->cinfo[1]), - osp_filter_null(inbound->cinfo[2]), osp_filter_null(inbound->cinfo[3]), - osp_filter_null(inbound->cinfo[4]), osp_filter_null(inbound->cinfo[5]), - osp_filter_null(inbound->cinfo[6]), osp_filter_null(inbound->cinfo[7]), - total); - } -} - -/* - * Get protocol from module name - * param module Module name - * return protocol name - */ -static OSPE_PROTOCOL_NAME osp_get_moduleprotocol( - const char *module) -{ - OSPE_PROTOCOL_NAME protocol; - - if (!strcasecmp(module, OSP_MODULE_SIP)) { - protocol = OSPC_PROTNAME_SIP; - } else if (!strcasecmp(module, OSP_MODULE_H323)) { - protocol = OSPC_PROTNAME_Q931; - } else if (!strcasecmp(module, OSP_MODULE_IAX)) { - protocol = OSPC_PROTNAME_IAX; - } else if (!strcasecmp(module, OSP_MODULE_SKYPE)) { - protocol = OSPC_PROTNAME_SKYPE; - } else { - protocol = OSPC_PROTNAME_UNKNOWN; - } - - return protocol; -} - -/* - * Get inbound info - * param channel Inbound channel - * param inbound Inbound info - * return - */ -static void osp_get_inbound( - switch_channel_t *channel, - osp_inbound_t *inbound) -{ - switch_caller_profile_t *caller; - switch_channel_timetable_t *times; - const char *tmp; - int i; - char name[OSP_SIZE_NORSTR]; - - memset(inbound, 0, sizeof(*inbound)); - - caller = switch_channel_get_caller_profile(channel); - - inbound->actsrc = switch_channel_get_variable(channel, OSP_VAR_SRCDEV); - inbound->srcdev = caller->network_addr; - inbound->protocol = osp_get_moduleprotocol(caller->source); - if ((tmp = switch_channel_get_variable(channel, OSP_FS_FROMUSER))) { - osp_parse_userinfo(tmp, inbound->calling, sizeof(inbound->calling), NULL, 0, NULL, 0, NULL); - } else { - osp_parse_userinfo(caller->caller_id_number, inbound->calling, sizeof(inbound->calling), NULL, 0, NULL, 0, NULL); - } - osp_parse_userinfo(caller->destination_number, inbound->called, sizeof(inbound->called), inbound->nprn, sizeof(inbound->nprn), - inbound->npcic, sizeof(inbound->npcic), &inbound->npdi); - - inbound->tohost = switch_channel_get_variable(channel, OSP_FS_TOHOST); - inbound->toport = switch_channel_get_variable(channel, OSP_FS_TOPORT); - - if ((tmp = switch_channel_get_variable(channel, OSP_FS_RPID))) { - osp_parse_header_user(tmp, inbound->rpiduser, sizeof(inbound->rpiduser)); - } - if ((tmp = switch_channel_get_variable(channel, OSP_FS_PAI))) { - osp_parse_userinfo(tmp, inbound->paiuser, sizeof(inbound->paiuser), NULL, 0, NULL, 0, NULL); - } - if ((tmp = switch_channel_get_variable(channel, OSP_FS_DIV))) { - osp_parse_header_user(tmp, inbound->divuser, sizeof(inbound->divuser)); - osp_parse_header_host(tmp, inbound->divhost, sizeof(inbound->divhost)); - } - if ((tmp = switch_channel_get_variable(channel, OSP_FS_PCI))) { - osp_parse_header_user(tmp, inbound->pciuser, sizeof(inbound->pciuser)); - } - - inbound->srcnid = switch_channel_get_variable(channel, OSP_VAR_SRCNID); - - times = switch_channel_get_timetable(channel); - inbound->start = times->created; - - for (i = 0; i < OSP_MAX_CINFO; i++) { - switch_snprintf(name, sizeof(name), "%s%d", OSP_VAR_CUSTOMINFO, i + 1); - inbound->cinfo[i] = switch_channel_get_variable(channel, name); - } -} - -/* - * Get outbound settings - * param channel Inbound channel - * param outbound Outbound settings - * return - */ -static void osp_get_outbound( - switch_channel_t *channel, - osp_outbound_t *outbound) -{ - const char *value; - - memset(outbound, 0, sizeof(*outbound)); - - /* Get destination network ID namd & location info */ - outbound->dniduserparam = switch_channel_get_variable(channel, OSP_VAR_DNIDUSERPARAM); - outbound->dniduriparam = switch_channel_get_variable(channel, OSP_VAR_DNIDURIPARAM); - - /* Get "user=phone" insert flag */ - value = switch_channel_get_variable(channel, OSP_VAR_USERPHONE); - if (!switch_strlen_zero(value)) { - outbound->userphone = switch_true(value); - } - - /* Get outbound proxy info */ - outbound->outproxy = switch_channel_get_variable(channel, OSP_VAR_OUTPROXY); -} - -/* - * Convert "address:port" to "[x.x.x.x]:port" or "hostname:port" format - * param src Source address string - * param dest Destination address string - * param destsize Size of dest buffer - * return - */ -static void osp_convert_inout( - const char *src, - char *dest, - int destsize) -{ - struct in_addr inp; - char buffer[OSP_SIZE_NORSTR]; - char *port; - - if (dest && (destsize > 0)) { - if (!switch_strlen_zero(src)) { - switch_copy_string(buffer, src, sizeof(buffer)); - - if((port = strchr(buffer, ':'))) { - *port = '\0'; - port++; - } - - if (inet_pton(AF_INET, buffer, &inp) == 1) { - if (port) { - switch_snprintf(dest, destsize, "[%s]:%s", buffer, port); - } else { - switch_snprintf(dest, destsize, "[%s]", buffer); - } - dest[destsize - 1] = '\0'; - } else { - switch_copy_string(dest, src, destsize); - } - } else { - *dest = '\0'; - } - } -} - -/* - * Convert "[x.x.x.x]:port" or "hostname:prot" to "address:port" format - * param src Source address string - * param dest Destination address string - * param destsize Size of dest buffer - * return - */ -static void osp_convert_outin( - const char *src, - char *dest, - int destsize) -{ - char buffer[OSP_SIZE_NORSTR]; - char *end; - char *port; - - if (dest && (destsize > 0)) { - if (!switch_strlen_zero(src)) { - switch_copy_string(buffer, src, sizeof(buffer)); - - if (buffer[0] == '[') { - if((port = strchr(buffer + 1, ':'))) { - *port = '\0'; - port++; - } - - if ((end = strchr(buffer + 1, ']'))) { - *end = '\0'; - } - - if (port) { - switch_snprintf(dest, destsize, "%s:%s", buffer + 1, port); - dest[destsize - 1] = '\0'; - } else { - switch_copy_string(dest, buffer + 1, destsize); - } - } else { - switch_copy_string(dest, src, destsize); - } - } else { - *dest = '\0'; - } - } -} - -/* - * Check destination - * param transaction Transaction handle - * param dest Destination - * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed - */ -static switch_status_t osp_check_destination( - OSPTTRANHANDLE transaction, - osp_destination_t *dest) -{ - OSPE_DEST_OSPENABLED enabled; - OSPE_PROTOCOL_NAME protocol; - OSPE_OPERATOR_NAME type; - int error; - switch_status_t status = SWITCH_STATUS_FALSE; - - if ((transaction == OSP_INVALID_HANDLE) || !dest) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid parameters\n"); - return status; - } - - dest->supported = SWITCH_FALSE; - - if ((error = OSPPTransactionIsDestOSPEnabled(transaction, &enabled)) != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get destination OSP version, error '%d'\n", error); - return status; - } - - if ((error = OSPPTransactionGetDestProtocol(transaction, &protocol)) != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get signaling protocol, error '%d'\n", error); - return status; - } - - switch(protocol) { - case OSPC_PROTNAME_UNDEFINED: - case OSPC_PROTNAME_UNKNOWN: - protocol = osp_globals.protocol; - case OSPC_PROTNAME_SIP: - case OSPC_PROTNAME_Q931: - case OSPC_PROTNAME_IAX: - case OSPC_PROTNAME_SKYPE: - dest->protocol = protocol; - if (!switch_strlen_zero(osp_globals.modules[protocol]) && !switch_strlen_zero(osp_globals.profiles[protocol])) { - dest->supported = SWITCH_TRUE; - status = SWITCH_STATUS_SUCCESS; - } - break; - case OSPC_PROTNAME_LRQ: - case OSPC_PROTNAME_T37: - case OSPC_PROTNAME_T38: - case OSPC_PROTNAME_SMPP: - case OSPC_PROTNAME_XMPP: - default: - dest->protocol = protocol; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported protocol '%d'\n", protocol); - break; - } - - if ((error = OSPPTransactionGetDestinationNetworkId(transaction, sizeof(dest->destnid), dest->destnid)) != OSPC_ERR_NO_ERROR) { - dest->destnid[0] = '\0'; - } - - error = OSPPTransactionGetNumberPortabilityParameters( - transaction, - sizeof(dest->nprn), - dest->nprn, - sizeof(dest->npcic), - dest->npcic, - &dest->npdi); - if (error != OSPC_ERR_NO_ERROR) { - dest->nprn[0] = '\0'; - dest->npcic[0] = '\0'; - dest->npdi = 0; - } - - for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) { - if ((error = OSPPTransactionGetOperatorName(transaction, type, sizeof(dest->opname[type]), dest->opname[type])) != OSPC_ERR_NO_ERROR) { - dest->opname[type][0] = '\0'; - } - } - - return status; -} - -/* - * Log AuthRsp parameters - * param results Routing info - * return - */ -static void osp_log_authrsp( - osp_results_t *results) -{ - int i; - - if (osp_globals.debug) { - for (i = 0; i < results->numdest; i++) { - switch_log_printf(SWITCH_CHANNEL_LOG, osp_globals.loglevel, - "AuthRsp: " - "transid '%"PRIu64"' " - "destcount '%d' " - "timelimit '%u' " - "destination '%s' " - "calling '%s' " - "called '%s' " - "destnid '%s' " - "lnp '%s/%s/%d' " - "protocol '%s' " - "supported '%d'\n", - results->transid, - i + 1, - results->dests[i].timelimit, - results->dests[i].dest, - results->dests[i].calling, - results->dests[i].called, - results->dests[i].destnid, - results->dests[i].nprn, results->dests[i].npcic, results->dests[i].npdi, - osp_get_protocol(results->dests[i].protocol), - results->dests[i].supported); - } - } -} - -/* - * Do auth/routing request - * param profile OSP profile - * param transaction Transaction handle - * param inbound Call originator info - * param results Routing info - * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed - */ -static switch_status_t osp_do_request( - osp_profile_t *profile, - OSPTTRANHANDLE transaction, - osp_inbound_t *inbound, - osp_results_t *results) -{ - OSPTTRANS *context; - osp_destination_t *dest; - char tmp[OSP_SIZE_NORSTR]; - const char *source; - const char *srcdev; - char src[OSP_SIZE_NORSTR]; - char dev[OSP_SIZE_NORSTR]; - char term[OSP_SIZE_NORSTR]; - const char *preferred[2] = { NULL }; - unsigned int callidlen = 0, tokenlen = 0, total; - int count, error; - switch_status_t status = SWITCH_STATUS_FALSE; - - osp_log_authreq(profile, inbound); - - OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_SOURCE, inbound->protocol); - - OSPPTransactionSetNumberPortability(transaction, inbound->nprn, inbound->npcic, inbound->npdi); - - OSPPTransactionSetRemotePartyId(transaction, OSPC_NFORMAT_E164, inbound->rpiduser); - OSPPTransactionSetAssertedId(transaction, OSPC_NFORMAT_E164, inbound->paiuser); - osp_convert_inout(inbound->divhost, tmp, sizeof(tmp)); - OSPPTransactionSetDiversion(transaction, inbound->divuser, tmp); - OSPPTransactionSetChargeInfo(transaction, OSPC_NFORMAT_E164, inbound->pciuser); - - OSPPTransactionSetNetworkIds(transaction, inbound->srcnid, NULL); - - for (count = 0; count < OSP_MAX_CINFO; count++) { - if (!switch_strlen_zero(inbound->cinfo[count])) { - OSPPTransactionSetCustomInfo(transaction, count, inbound->cinfo[count]); - } - } - - if (profile->workmode == OSP_MODE_INDIRECT) { - source = inbound->srcdev; - if (switch_strlen_zero(inbound->actsrc)) { - srcdev = inbound->srcdev; - } else { - srcdev = inbound->actsrc; - } - } else { - source = profile->device; - srcdev = inbound->srcdev; - } - osp_convert_inout(source, src, sizeof(src)); - osp_convert_inout(srcdev, dev, sizeof(dev)); - - if (profile->srvtype == OSP_SRV_NPQUERY) { - OSPPTransactionSetServiceType(transaction, OSPC_SERVICE_NPQUERY); - - if (switch_strlen_zero(inbound->tohost)) { - switch_copy_string(term, src, sizeof(term)); - } else { - if (switch_strlen_zero(inbound->toport)) { - switch_copy_string(tmp, inbound->tohost, sizeof(tmp)); - } else { - switch_snprintf(tmp, sizeof(tmp), "%s:%s", inbound->tohost, inbound->toport); - } - osp_convert_inout(tmp, term, sizeof(term)); - } - preferred[0] = term; - - total = 1; - } else { - OSPPTransactionSetServiceType(transaction, OSPC_SERVICE_VOICE); - - total = profile->maxdest; - } - - error = OSPPTransactionRequestAuthorisation( - transaction, /* Transaction handle */ - src, /* Source */ - dev, /* Source device */ - inbound->calling, /* Calling */ - OSPC_NFORMAT_E164, /* Calling format */ - inbound->called, /* Called */ - OSPC_NFORMAT_E164, /* Called format */ - NULL, /* User */ - 0, /* Number of callids */ - NULL, /* Callids */ - preferred, /* Preferred destinations */ - &total, /* Destination number */ - NULL, /* Log buffer size */ - NULL); /* Log buffer */ - if (error != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to request routing for '%s/%s', error '%d'\n", - inbound->calling, inbound->called, error); - results->status = error; - results->numdest = 0; - return status; - } else if (!total) { - results->status = error; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Without destination\n"); - results->status = error; - results->numdest = 0; - return status; - } - - context = OSPPTransactionGetContext(transaction, &error); - if (error == OSPC_ERR_NO_ERROR) { - results->transid = context->TransactionID; - } else { - results->transid = 0; - } - - switch_copy_string(results->calling, inbound->calling, sizeof(results->calling)); - switch_copy_string(results->called, inbound->called, sizeof(results->called)); - results->srcdev = srcdev; - results->srcnid = inbound->srcnid; - results->start = inbound->start; - - count = 0; - dest = &results->dests[count]; - error = OSPPTransactionGetFirstDestination( - transaction, /* Transaction handle */ - 0, /* Timestamp buffer size */ - NULL, /* Valid after */ - NULL, /* Valid until */ - &dest->timelimit, /* Call duration limit */ - &callidlen, /* Callid buffer size */ - NULL, /* Callid buffer */ - sizeof(dest->called), /* Called buffer size */ - dest->called, /* Called buffer */ - sizeof(dest->calling), /* Calling buffer size */ - dest->calling, /* Calling buffer */ - sizeof(term), /* Destination buffer size */ - term, /* Destination buffer */ - 0, /* Destination device buffer size */ - NULL, /* Destination device buffer */ - &tokenlen, /* Token buffer length */ - NULL); /* Token buffer */ - if (error != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get first destination, error '%d'\n", error); - results->status = error; - results->numdest = 0; - return status; - } - - osp_convert_outin(term, dest->dest, sizeof(dest->dest)); - osp_check_destination(transaction, dest); - - for (count = 1; count < total; count++) { - dest = &results->dests[count]; - error = OSPPTransactionGetNextDestination( - transaction, /* Transsaction handle */ - OSPC_FAIL_NONE, /* Failure reason */ - 0, /* Timestamp buffer size */ - NULL, /* Valid after */ - NULL, /* Valid until */ - &dest->timelimit, /* Call duration limit */ - &callidlen, /* Callid buffer size */ - NULL, /* Callid buffer */ - sizeof(dest->called), /* Called buffer size */ - dest->called, /* Called buffer */ - sizeof(dest->calling), /* Calling buffer size */ - dest->calling, /* Calling buffer */ - sizeof(term), /* Destination buffer size */ - term, /* Destination buffer */ - 0, /* Destination device buffer size */ - NULL, /* Destination device buffer */ - &tokenlen, /* Token buffer length */ - NULL); /* Token buffer */ - if (error == OSPC_ERR_NO_ERROR) { - osp_convert_outin(term, dest->dest, sizeof(dest->dest)); - osp_check_destination(transaction, dest); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get destination, error '%d'\n", error); - break; - } - } - if (count == total) { - results->status = OSPC_ERR_NO_ERROR; - results->numdest = total; - osp_log_authrsp(results); - status = SWITCH_STATUS_SUCCESS; - } else { - results->status = error; - results->numdest = 0; - } - - return status; -} - -/* - * Request auth/routing info - * param channel Originator channel - * param profile Profile name - * param results Routing info - * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed - */ -static switch_status_t osp_request_routing( - switch_channel_t *channel, - const char *profilename, - osp_results_t *results) -{ - osp_profile_t *profile; - OSPTTRANHANDLE transaction; - osp_inbound_t inbound; - int error; - switch_status_t status = SWITCH_STATUS_FALSE; - - if (osp_find_profile(profilename, &profile) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find profile '%s'\n", profilename); - return status; - } - - if (profile->provider == OSP_INVALID_HANDLE) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Disabled profile '%s'\n", profilename); - return status; - } - - results->profile = profilename; - - if ((error = OSPPTransactionNew(profile->provider, &transaction)) != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create transaction handle, error '%d'\n", error); - return status; - } - - osp_get_inbound(channel, &inbound); - - status = osp_do_request(profile, transaction, &inbound, results); - - OSPPTransactionDelete(transaction); - - return status; -} - -/* - * Build parameter string for all channels - * param results Routing results - * param buffer Buffer - * param bufsize Buffer size - * return - */ -static void osp_build_allparam( - osp_results_t *results, - char *buffer, - switch_size_t bufsize) -{ - char *head = buffer; - switch_size_t len, size = bufsize; - - if (results && head && size) { - switch_snprintf(head, size, - "{%s=%s,%s=%"PRIu64",%s=%s,%s=%s,%s=%"PRId64",%s=%s,%s=%d", - OSP_VAR_PROFILE, results->profile, - OSP_VAR_TRANSID, results->transid, - OSP_VAR_CALLING, results->calling, - OSP_VAR_CALLED, results->called, - OSP_VAR_START, results->start, - OSP_VAR_SRCDEV, results->srcdev, - OSP_VAR_DESTTOTAL, results->numdest); - osp_adjust_len(head, size, len); - - if (!switch_strlen_zero(results->srcnid)) { - switch_snprintf(head, size, ",%s=%s", OSP_VAR_SRCNID, results->srcnid); - } - osp_adjust_len(head, size, len); - - switch_snprintf(head, size, "}"); - osp_adjust_len(head, size, len); - } -} - -/* - * Build parameter string for each channel - * param count Destination count - * param dest Destination - * param buffer Buffer - * param bufsize Buffer size - * return - */ -static void osp_build_eachparam( - int count, - osp_destination_t *dest, - char *buffer, - switch_size_t bufsize) -{ - char *head = buffer; - switch_size_t len, size = bufsize; - - if ((count > 0) && dest && head && size) { - switch_snprintf(buffer, bufsize, - "[%s=%d,%s=%s,%s=%s", - OSP_VAR_DESTCOUNT, count, - OSP_VAR_DESTIP, dest->dest, - OSP_FS_OUTCALLING, dest->calling); - osp_adjust_len(head, size, len); - - if (!switch_strlen_zero_buf(dest->destnid)) { - switch_snprintf(head, size, ",%s=%s", OSP_VAR_DESTNID, dest->destnid); - } - osp_adjust_len(head, size, len); - - switch_snprintf(head, size, "]"); - osp_adjust_len(head, size, len); - } -} - -/* - * Build endpoint string - * param dest Destination - * param outbound Outbound settings - * param buffer Buffer - * param bufsize Buffer size - * return - */ -static void osp_build_endpoint( - osp_destination_t *dest, - osp_outbound_t *outbound, - char *buffer, - switch_size_t bufsize) -{ - char *head = buffer; - switch_size_t len, size = bufsize; - - if (head && size) { - switch (dest->protocol) { - case OSPC_PROTNAME_SIP: - switch_snprintf(head, size, "%s/%s/%s", osp_globals.modules[OSPC_PROTNAME_SIP], osp_globals.profiles[OSPC_PROTNAME_SIP], - dest->called); - osp_adjust_len(head, size, len); - - if (!switch_strlen_zero_buf(dest->nprn)) { - switch_snprintf(head, size, ";rn=%s", dest->nprn); - osp_adjust_len(head, size, len); - } - if (!switch_strlen_zero_buf(dest->npcic)) { - switch_snprintf(head, size, ";cic=%s", dest->npcic); - osp_adjust_len(head, size, len); - } - if (dest->npdi) { - switch_snprintf(head, size, ";npdi"); - osp_adjust_len(head, size, len); - } - - if (!switch_strlen_zero(outbound->dniduserparam) && !switch_strlen_zero_buf(dest->destnid)) { - switch_snprintf(head, size, ";%s=%s", outbound->dniduserparam, dest->destnid); - osp_adjust_len(head, size, len); - } - - switch_snprintf(head, size, "@%s", dest->dest); - osp_adjust_len(head, size, len); - - if (!switch_strlen_zero(outbound->dniduriparam) && !switch_strlen_zero_buf(dest->destnid)) { - switch_snprintf(head, size, ";%s=%s", outbound->dniduriparam, dest->destnid); - osp_adjust_len(head, size, len); - } - - if (outbound->userphone) { - switch_snprintf(head, size, ";user=phone"); - osp_adjust_len(head, size, len); - } - - if (!switch_strlen_zero(outbound->outproxy)) { - switch_snprintf(head, size, ";fs_path=sip:%s", outbound->outproxy); - osp_adjust_len(head, size, len); - } - break; - case OSPC_PROTNAME_Q931: - switch_snprintf(head, size, "%s/%s/%s@%s", osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931], - dest->called, dest->dest); - osp_adjust_len(head, size, len); - break; - case OSPC_PROTNAME_IAX: - switch_snprintf(head, size, "%s/%s/%s/%s", osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931], - dest->dest, dest->called); - osp_adjust_len(head, size, len); - break; - case OSPC_PROTNAME_SKYPE: - switch_snprintf(head, size, "%s/%s/%s", osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931], - dest->called); - osp_adjust_len(head, size, len); - break; - default: - buffer[0] = '\0'; - break; - } - } -} - -/* - * Create route string - * param channel Originator channel - * param results Routing info - * return - */ -static void osp_create_route( - switch_channel_t *channel, - osp_results_t *results) -{ - osp_destination_t *dest; - char name[OSP_SIZE_NORSTR]; - char value[OSP_SIZE_ROUSTR]; - char allparam[OSP_SIZE_NORSTR]; - char eachparam[OSP_SIZE_NORSTR]; - char endpoint[OSP_SIZE_NORSTR]; - osp_outbound_t outbound; - char tmp[OSP_SIZE_ROUSTR]; - char buffer[OSP_SIZE_ROUSTR]; - int i, len, count, size = sizeof(buffer); - char *head = buffer; - switch_event_header_t *hi; - char *var; - - osp_get_outbound(channel, &outbound); - - /* Cleanup OSP varibales in originator */ - if ((hi = switch_channel_variable_first(channel))) { - for (; hi; hi = hi->next) { - var = hi->name; - if (var && !strncmp(var, "osp_", 4)) { - switch_channel_set_variable(channel, var, NULL); - } - } - switch_channel_variable_last(channel); - } - - switch_snprintf(value, sizeof(value), "%d", results->status); - switch_channel_set_variable_var_check(channel, OSP_VAR_AUTHSTATUS, value, SWITCH_FALSE); - - osp_build_allparam(results, head, size); - switch_copy_string(allparam, head, sizeof(allparam)); - osp_adjust_len(head, size, len); - - for (count = 0, i = 0; i < results->numdest; i++) { - dest = &results->dests[i]; - if (dest->supported) { - count++; - osp_build_eachparam(i + 1, dest, eachparam, sizeof(eachparam)); - osp_build_endpoint(dest, &outbound, endpoint, sizeof(endpoint)); - - switch_snprintf(name, sizeof(name), "%s%d", OSP_VAR_ROUTEPRE, count); - switch_snprintf(value, sizeof(value), "%s%s%s", allparam, eachparam, endpoint); - switch_channel_set_variable_var_check(channel, name, value, SWITCH_FALSE); - - switch_snprintf(tmp, sizeof(tmp), "%s%s", eachparam, endpoint); - switch_snprintf(head, size, "%s|", tmp); - osp_adjust_len(head, size, len); - } - } - - switch_snprintf(value, sizeof(value), "%d", count); - switch_channel_set_variable_var_check(channel, OSP_VAR_ROUTECOUNT, value, SWITCH_FALSE); - - if (count) { - *(buffer + strlen(buffer) - 1) = '\0'; - } else { - buffer[0] = '\0'; - } - switch_channel_set_variable_var_check(channel, OSP_VAR_AUTOROUTE, buffer, SWITCH_FALSE); -} - -/* - * Export AuthReq status to channel - * param channel Originator channel - * param results Routing info - * return - */ -static void osp_export_failure( - switch_channel_t *channel, - osp_results_t *results) -{ - char value[OSP_SIZE_NORSTR]; - switch_event_header_t *hi; - char *var; - - /* Cleanup OSP varibales in originator */ - if ((hi = switch_channel_variable_first(channel))) { - for (; hi; hi = hi->next) { - var = hi->name; - if (var && !strncmp(var, "osp_", 4)) { - switch_channel_set_variable(channel, var, NULL); - } - } - switch_channel_variable_last(channel); - } - - switch_snprintf(value, sizeof(value), "%d", results->status); - switch_channel_set_variable_var_check(channel, OSP_VAR_AUTHSTATUS, value, SWITCH_FALSE); - - switch_snprintf(value, sizeof(value), "%d", results->numdest); - switch_channel_set_variable_var_check(channel, OSP_VAR_ROUTECOUNT, value, SWITCH_FALSE); -} - /* * Macro expands to: - * static void osp_app_function(switch_core_session_t *session, const char *data) + * static void osp_lookup_function(switch_core_session_t *session, const char *data) */ -SWITCH_STANDARD_APP(osp_app_function) +SWITCH_STANDARD_APP(osp_lookup_function) { + switch_channel_t *channel; int argc = 0; char *argv[2] = { 0 }; char *params = NULL; - char *profile = NULL; - switch_channel_t *channel; osp_results_t results; - switch_status_t retval; - if (osp_globals.shutdown) { + OSP_DEBUG_START; + + if (osp_global.shutdown) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "OSP application inavailable\n"); - return; - } - - /* Make sure there is a valid channel when starting the OSP application */ - if (!(channel = switch_core_session_get_channel(session))) { + } else if (!(channel = switch_core_session_get_channel(session))) { + /* Make sure there is a valid channel when starting the OSP application */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to find origiantor channel\n"); - return; - } - - if (!(params = switch_core_session_strdup(session, data))) { + } else if (!(params = switch_core_session_strdup(session, data))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to alloc parameters\n"); - return; - } - - if ((argc = switch_separate_string(params, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { - profile = argv[0]; } else { - profile = OSP_DEF_PROFILE; - } - - retval = osp_request_routing(channel, profile, &results); - if (retval == SWITCH_STATUS_SUCCESS) { - osp_create_route(channel, &results); - } else { - osp_export_failure(channel, &results); - } -} - -/* - * Add application - * param session - * param channel Originator channel - * param extenstion - * param results OSP routing info - * return - */ -static void osp_add_application( - switch_core_session_t *session, - switch_channel_t *channel, - switch_caller_extension_t **extension, - osp_results_t *results) -{ - osp_destination_t *dest; - char allparam[OSP_SIZE_NORSTR]; - char eachparam[OSP_SIZE_NORSTR]; - char endpoint[OSP_SIZE_NORSTR]; - osp_outbound_t outbound; - char name[OSP_SIZE_NORSTR]; - char value[OSP_SIZE_ROUSTR]; - int i, count; - switch_event_header_t *hi; - char *var; - - if ((*extension = switch_caller_extension_new(session, results->called, results->called)) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to create extension\n"); - return; - } - - osp_get_outbound(channel, &outbound); - - switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true"); - - /* Cleanup OSP varibales in originator */ - if ((hi = switch_channel_variable_first(channel))) { - for (; hi; hi = hi->next) { - var = hi->name; - if (var && !strncmp(var, "osp_", 4)) { - switch_channel_set_variable(channel, var, NULL); - } + memset(&results, 0, sizeof(osp_results_t)); + if ((argc = switch_separate_string(params, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + results.profile = argv[0]; + } else { + results.profile = OSP_DEF_PROFILE; } - switch_channel_variable_last(channel); + results.transaction = OSP_INVALID_HANDLE; + results.protocol = OSPC_PROTNAME_UNKNOWN; + + /* Do OSP lookup */ + osp_do_lookup(channel, &results); } - switch_snprintf(value, sizeof(value), "%d", results->status); - switch_channel_set_variable_var_check(channel, OSP_VAR_AUTHSTATUS, value, SWITCH_FALSE); - - osp_build_allparam(results, allparam, sizeof(allparam)); - - for (count = 0, i = 0; i < results->numdest; i++) { - dest = &results->dests[i]; - if (dest->supported) { - count++; - osp_build_eachparam(i + 1, dest, eachparam, sizeof(eachparam)); - osp_build_endpoint(dest, &outbound, endpoint, sizeof(endpoint)); - - switch_snprintf(name, sizeof(name), "%s%d", OSP_VAR_ROUTEPRE, count); - switch_snprintf(value, sizeof(value), "%s%s%s", allparam, eachparam, endpoint); - switch_channel_set_variable_var_check(channel, name, value, SWITCH_FALSE); - - switch_caller_extension_add_application(session, *extension, "bridge", value); - } - } - - switch_snprintf(value, sizeof(value), "%d", count); - switch_channel_set_variable_var_check(channel, OSP_VAR_ROUTECOUNT, value, SWITCH_FALSE); + OSP_DEBUG_END; } /* * Macro expands to: - * switch_caller_extension_t * osp_dialplan_function(switch_core_session_t *session, void *arg, switch_caller_profile_t *caller_profile) + * static void osp_next_function(switch_core_session_t *session, const char *data) */ -SWITCH_STANDARD_DIALPLAN(osp_dialplan_function) +SWITCH_STANDARD_APP(osp_next_function) { - int argc = 0; - char *argv[2] = { 0 }; - char *profile = NULL; - switch_caller_extension_t *extension = NULL; - switch_channel_t *channel = switch_core_session_get_channel(session); + switch_channel_t *channel; osp_results_t results; - switch_status_t retval; - if (osp_globals.shutdown) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "OSP dialplan inavailable\n"); - return extension; - } + OSP_DEBUG_START; - if ((argc = switch_separate_string((char *)arg, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { - profile = argv[0]; + if (osp_global.shutdown) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "OSP application inavailable\n"); + } else if (!(channel = switch_core_session_get_channel(session))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to find origiantor channel\n"); } else { - profile = OSP_DEF_PROFILE; + memset(&results, 0, sizeof(osp_results_t)); + results.transaction = OSP_INVALID_HANDLE; + results.protocol = OSPC_PROTNAME_UNKNOWN; + + /* Do OSP next */ + osp_do_next(channel, &results); } - retval = osp_request_routing(channel, profile, &results); - if (retval == SWITCH_STATUS_SUCCESS) { - osp_add_application(session, channel, &extension, &results); - } else { - osp_export_failure(channel, &results); - } - - return extension; -} - -/* - * Retrieve cookie - * param channel Destination channel - * param cookie Cookie - * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed - */ -static switch_status_t osp_get_cookie( - switch_channel_t *channel, - osp_cookie_t *cookie) -{ - const char *strvar; - - if (!(cookie->profile = switch_channel_get_variable(channel, OSP_VAR_PROFILE))) { - return SWITCH_STATUS_FALSE; - } - - if (!(strvar = switch_channel_get_variable(channel, OSP_VAR_TRANSID)) || (sscanf(strvar, "%"PRIu64"", &cookie->transid) != 1)) { - cookie->transid = 0; - } - - cookie->calling = switch_channel_get_variable(channel, OSP_VAR_CALLING); - cookie->called = switch_channel_get_variable(channel, OSP_VAR_CALLED); - - if (!(strvar = switch_channel_get_variable(channel, OSP_VAR_START)) || (sscanf(strvar, "%"PRId64"", &cookie->start) != 1)) { - cookie->start = 0; - } - - cookie->srcdev = switch_channel_get_variable(channel, OSP_VAR_SRCDEV); - - if (!(strvar = switch_channel_get_variable(channel, OSP_VAR_DESTTOTAL)) || (sscanf(strvar, "%d", &cookie->desttotal) != 1)) { - cookie->desttotal = 0; - } - - if (!(strvar = switch_channel_get_variable(channel, OSP_VAR_DESTCOUNT)) || (sscanf(strvar, "%d", &cookie->destcount) != 1)) { - cookie->destcount = 0; - } - - cookie->dest = switch_channel_get_variable(channel, OSP_VAR_DESTIP); - - cookie->srcnid = switch_channel_get_variable(channel, OSP_VAR_SRCNID); - - cookie->destnid = switch_channel_get_variable(channel, OSP_VAR_DESTNID); - - return SWITCH_STATUS_SUCCESS; -} - -/* - * Retrieve usage info - * param channel Destination channel - * param originator Originator channel - * param cookie Cookie - * param usage Usage info - * return - */ -static void osp_get_usage( - switch_channel_t *channel, - switch_caller_profile_t *originator, - osp_cookie_t *cookie, - osp_usage_t *usage) -{ - const char *strvar; - switch_caller_profile_t *terminator; - switch_channel_timetable_t *times; - - memset(usage, 0, sizeof(*usage)); - - usage->callid = switch_channel_get_variable(channel, OSP_FS_OUTCALLID); - if (switch_strlen_zero(usage->callid)) { - usage->callid = OSP_DEF_CALLID; - } - - /* Originator had been checked by osp_on_reporting */ - if (originator) { - usage->srcdev = originator->network_addr; - usage->inprotocol = osp_get_moduleprotocol(originator->source); - } - - terminator = switch_channel_get_caller_profile(channel); - usage->outprotocol = osp_get_moduleprotocol(terminator->source); - if (usage->outprotocol == OSPC_PROTNAME_SIP) { - strvar = switch_channel_get_variable(channel, OSP_FS_SIPRELEASE); - if (!strvar || !strcasecmp(strvar, "recv_bye")) { - usage->release = 1; - } - } - usage->cause = switch_channel_get_cause_q850(channel); - times = switch_channel_get_timetable(channel); - usage->alert = times->progress; - usage->connect = times->answered; - usage->end = times->hungup; - if (times->answered) { - usage->duration = times->hungup - times->answered; - usage->pdd = times->answered - cookie->start; - } - - usage->srccodec = switch_channel_get_variable(channel, OSP_FS_SRCCODEC); - usage->destcodec = switch_channel_get_variable(channel, OSP_FS_DESTCODEC); - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPSRCREPOCTS)) || - (sscanf(strvar, "%d", &usage->rtpsrcrepoctets) != 1)) - { - usage->rtpsrcrepoctets = OSP_DEF_STATS; - } - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPDESTREPOCTS)) || - (sscanf(strvar, "%d", &usage->rtpdestrepoctets) != 1)) - { - usage->rtpdestrepoctets = OSP_DEF_STATS; - } - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPSRCREPPKTS)) || - (sscanf(strvar, "%d", &usage->rtpsrcreppackets) != 1)) - { - usage->rtpsrcreppackets = OSP_DEF_STATS; - } - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPDESTREPPKTS)) || - (sscanf(strvar, "%d", &usage->rtpdestreppackets) != 1)) - { - usage->rtpdestreppackets = OSP_DEF_STATS; - } -} - -/* - * Report OSP usage thread function - * param threadarg Thread argments - * return - */ -static OSPTTHREADRETURN osp_report_thread( - void *threadarg) -{ - int i, error; - osp_threadarg_t *info; - - info = (osp_threadarg_t *)threadarg; - - OSPPTransactionRecordFailure(info->transaction, info->cause); - - for (i = 0; i < 3; i++) { - error = OSPPTransactionReportUsage( - info->transaction, /* Transaction handle */ - info->duration, /* Call duration */ - info->start, /* Call start time */ - info->end, /* Call end time */ - info->alert, /* Call alert time */ - info->connect, /* Call connect time */ - info->pdd != 0, /* Post dial delay present */ - info->pdd, /* Post dial delay */ - info->release, /* Release source */ - NULL, /* Conference ID */ - -1, /* Packets not received by peer */ - -1, /* Fraction of packets not received by peer */ - -1, /* Packets not received that were expected */ - -1, /* Fraction of packets expected but not received */ - NULL, /* Log buffer size */ - NULL); /* Log buffer */ - if (error != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Failed to report usage for '%"PRIu64"' attempt '%d'\n", - info->transid, - i + 1); - } else { - break; - } - } - - OSPPTransactionDelete(info->transaction); - - switch_safe_free(info); - - OSPTTHREADRETURN_NULL(); -} - -/* - * Report usage - * param cookie Cookie - * param usage Usage - * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed - */ -static switch_status_t osp_report_usage( - osp_cookie_t *cookie, - osp_usage_t *usage) -{ - osp_profile_t *profile; - char source[OSP_SIZE_NORSTR]; - char destination[OSP_SIZE_NORSTR]; - char srcdev[OSP_SIZE_NORSTR]; - OSPTTRANHANDLE transaction; - osp_threadarg_t *info; - OSPTTHREADID threadid; - OSPTTHRATTR threadattr; - int error; - switch_status_t status = SWITCH_STATUS_FALSE; - - if (osp_find_profile(cookie->profile, &profile) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find profile '%s'\n", cookie->profile); - return status; - } - - if ((error = OSPPTransactionNew(profile->provider, &transaction)) != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create transaction handle, error '%d'\n", error); - return status; - } - - if (profile->workmode == OSP_MODE_INDIRECT) { - osp_convert_inout(usage->srcdev, source, sizeof(source)); - } else { - osp_convert_inout(profile->device, source, sizeof(source)); - } - - osp_convert_inout(cookie->dest, destination, sizeof(destination)); - - osp_convert_inout(cookie->srcdev, srcdev, sizeof(srcdev)); - - error = OSPPTransactionBuildUsageFromScratch( - transaction, /* Transaction handle */ - cookie->transid, /* Transaction ID */ - OSPC_ROLE_SOURCE, /* CDR type, source */ - source, /* Source */ - destination, /* Destination */ - srcdev, /* Source device */ - OSP_DEF_STRING, /* Destination device */ - cookie->calling, /* Calling */ - OSPC_NFORMAT_E164, /* Calling format */ - cookie->called, /* Called */ - OSPC_NFORMAT_E164, /* Called format */ - strlen(usage->callid), /* Size of Call-ID */ - usage->callid, /* Call-ID */ - 0, /* Failure reason */ - NULL, /* Log buffer size */ - NULL); /* Log buffer */ - if (error != OSPC_ERR_NO_ERROR) { - OSPPTransactionDelete(transaction); - return status; - } - - status = SWITCH_STATUS_SUCCESS; - - OSPPTransactionSetDestinationCount(transaction, cookie->destcount); - - OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_SOURCE, usage->inprotocol); - OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_DESTINATION, usage->outprotocol); - - if (!switch_strlen_zero(cookie->srcnid)) { - OSPPTransactionSetSrcNetworkId(transaction, cookie->srcnid); - } - - if (!switch_strlen_zero(cookie->destnid)) { - OSPPTransactionSetDestNetworkId(transaction, cookie->destnid); - } - - if (!switch_strlen_zero(usage->srccodec)) { - OSPPTransactionSetCodec(transaction, OSPC_CODEC_SOURCE, usage->srccodec); - } - if (!switch_strlen_zero(usage->destcodec)) { - OSPPTransactionSetCodec(transaction, OSPC_CODEC_DESTINATION, usage->destcodec); - } - - if (usage->rtpsrcrepoctets != OSP_DEF_STATS) { - OSPPTransactionSetOctets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, usage->rtpsrcrepoctets); - } - if (usage->rtpdestrepoctets != OSP_DEF_STATS) { - OSPPTransactionSetOctets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, usage->rtpdestrepoctets); - } - if (usage->rtpsrcreppackets != OSP_DEF_STATS) { - OSPPTransactionSetPackets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, usage->rtpsrcreppackets); - } - if (usage->rtpdestreppackets != OSP_DEF_STATS) { - OSPPTransactionSetPackets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, usage->rtpdestreppackets); - } - -/* TODO: The logic to identify the last call attempt needs improvement. - if ((cookie->destcount == cookie->desttotal) || (usage->cause == SWITCH_CAUSE_NORMAL_CLEARING)) { - OSPPTransactionSetRoleInfo(transaction, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_FREESWITCH); - } else { - OSPPTransactionSetRoleInfo(transaction, OSPC_RSTATE_INTERIM, OSPC_RFORMAT_OSP, OSPC_RVENDOR_FREESWITCH); - } -*/ - OSPPTransactionSetRoleInfo(transaction, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_FREESWITCH); - - info = (osp_threadarg_t *)malloc(sizeof(osp_threadarg_t)); - info->transaction = transaction; - info->transid = cookie->transid; - info->cause = usage->cause; - info->start = cookie->start / 1000000; - info->alert = usage->alert / 1000000; - info->connect = usage->connect / 1000000; - info->end = usage->end / 1000000; - info->duration = usage->duration / 1000000; - info->pdd = usage->pdd / 1000; - info->release = usage->release; - - OSPM_THRATTR_INIT(threadattr, error); - OSPM_SETDETACHED_STATE(threadattr, error); - OSPM_CREATE_THREAD(threadid, &threadattr, osp_report_thread, info, error); - OSPM_THRATTR_DESTROY(threadattr); - - /* transaction and info will be released by osp_report_thread */ - - return status; -} - -/* - * Log UsageInd parameters - * param cookie Cookie - * param usage Usage info - * return - */ -static void osp_log_usageind( - osp_cookie_t *cookie, - osp_usage_t *usage) -{ - if (osp_globals.debug) { - switch_log_printf(SWITCH_CHANNEL_LOG, osp_globals.loglevel, - "UsageInd: " - "transid '%"PRIu64"' " - "destcount '%d' " - "callid '%s' " - "calling '%s' " - "called '%s' " - "srcdev '%s' " - "dest '%s' " - "nid '%s/%s' " - "protocol '%s/%s' " - "cause '%d' " - "release '%s' " - "times '%"PRId64"/%"PRId64"/%"PRId64"/%"PRId64"' " - "duration '%"PRId64"' " - "pdd '%"PRId64"' " - "outsessionid '%s' " - "codec '%s/%s' " - "rtpctets '%d/%d' " - "rtppackets '%d/%d'\n", - cookie->transid, - cookie->destcount, - usage->callid, - cookie->calling, - cookie->called, - cookie->srcdev, - cookie->dest, - osp_filter_null(cookie->srcnid), osp_filter_null(cookie->destnid), - osp_get_protocol(usage->inprotocol), osp_get_protocol(usage->outprotocol), - usage->cause, - usage->release ? "term" : "orig", - cookie->start / 1000000, usage->alert / 1000000, usage->connect / 1000000, usage->end / 1000000, - usage->duration / 1000000, - usage->pdd / 1000000, - usage->callid, - osp_filter_null(usage->srccodec), osp_filter_null(usage->destcodec), - usage->rtpsrcrepoctets, usage->rtpdestrepoctets, - usage->rtpsrcreppackets, usage->rtpdestreppackets); - } + OSP_DEBUG_END; } /* @@ -2378,30 +2610,40 @@ static switch_status_t osp_on_reporting( switch_core_session_t *session) { switch_channel_t *channel; - osp_cookie_t cookie; - osp_usage_t usage; switch_caller_profile_t *originator; - switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_caller_profile_t *terminator; + osp_results_t results; + switch_status_t status = SWITCH_STATUS_FALSE; - if (osp_globals.shutdown) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "OSP application inavailable\n"); - return status; + OSP_DEBUG_START; + + if (osp_global.shutdown) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OSP application inavailable\n"); + } else if (!(channel = switch_core_session_get_channel(session))) { + /* Make sure there is a valid channel when starting the OSP application */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to find origiantor channel\n"); + } else if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + /* A-leg */ + OSP_DEBUG_MSG("A-leg"); + + /* Get originator profile */ + if ((originator = switch_channel_get_caller_profile(channel))) { + /* Get terminator profile, may be NULL */ + terminator = switch_channel_get_originatee_caller_profile(channel); + + memset(&results, 0, sizeof(osp_results_t)); + results.transaction = OSP_INVALID_HANDLE; + results.protocol = OSPC_PROTNAME_UNKNOWN; + + /* Do OSP usage report */ + status = osp_do_report(channel, originator, terminator, &results); + } + } else { + /* B-leg */ + OSP_DEBUG_MSG("B-leg"); } - /* Only report for B-leg */ - if (!(channel = switch_core_session_get_channel(session)) || !(originator = switch_channel_get_originator_caller_profile(channel))) { - return status; - } - - if (osp_get_cookie(channel, &cookie) != SWITCH_STATUS_SUCCESS) { - return status; - } - - osp_get_usage(channel, originator, &cookie, &usage); - - osp_log_usageind(&cookie, &usage); - - osp_report_usage(&cookie, &usage); + OSP_DEBUG_END; return status; } @@ -2409,7 +2651,7 @@ static switch_status_t osp_on_reporting( /* * OSP module state handlers */ -static switch_state_handler_table_t state_handlers = { +static switch_state_handler_table_t osp_handlers = { NULL, /*.on_init */ NULL, /*.on_routing */ NULL, /*.on_execute */ @@ -2423,59 +2665,53 @@ static switch_state_handler_table_t state_handlers = { osp_on_reporting /*.on_reporting */ }; +/* switch_status_t mod_osp_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ +SWITCH_MODULE_LOAD_FUNCTION(mod_osp_load); +/* switch_status_t mod_osp_shutdown(void) */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_osp_shutdown); +/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) */ +SWITCH_MODULE_DEFINITION(mod_osp, mod_osp_load, mod_osp_shutdown, NULL); + /* + * Called when OSP module is loaded * Macro expands to: * switch_status_t mod_osp_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ SWITCH_MODULE_LOAD_FUNCTION(mod_osp_load) { - switch_api_interface_t *api_interface; + switch_api_interface_t *cli_interface; switch_application_interface_t *app_interface; - switch_dialplan_interface_t *dp_interface; switch_status_t status = SWITCH_STATUS_SUCCESS; - /* Load OSP configuration */ - if ((status = osp_load_settings(pool)) != SWITCH_STATUS_SUCCESS) { + OSP_DEBUG_START; + + /* Load OSP module configuration */ + if ((status = osp_load_config(pool)) != SWITCH_STATUS_SUCCESS) { + OSP_DEBUG_END; return status; } - /* Init OSP Toolkit */ + /* Init OSP client end */ osp_init_osptk(); - /* Connect OSP internal structure to the blank pointer passed to OSP module */ + /* Connect OSP module internal structure to the blank pointer passed to OSP module */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); - /* Add CLI OSP command */ - SWITCH_ADD_API(api_interface, "osp", "OSP", osp_api_function, "status"); + /* Add CLI osp status command */ + SWITCH_ADD_API(cli_interface, "osp", "OSP", osp_cli_function, "status"); switch_console_set_complete("add osp status"); - /* Add OSP application */ - SWITCH_ADD_APP(app_interface, "osp", "Perform an OSP lookup", "Perform an OSP lookup", osp_app_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + /* Add OSP module applications */ + SWITCH_ADD_APP(app_interface, "osplookup", "Perform an OSP lookup", "Perform an OSP lookup", osp_lookup_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "ospnext", "Retrive next OSP route", "Retrive next OSP route", osp_next_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); - /* Add OSP dialplan */ - SWITCH_ADD_DIALPLAN(dp_interface, "osp", osp_dialplan_function); + /* Add OSP module state handlers */ + switch_core_add_state_handler(&osp_handlers); - /* Add OSP state handlers */ - switch_core_add_state_handler(&state_handlers); + OSP_DEBUG_END; /* Indicate that the module should continue to be loaded */ - return status; -} - -/* - * Cleanup OSP client end - * return - */ -static void osp_cleanup_osptk(void) -{ - osp_profile_t *profile; - - for (profile = osp_profiles; profile; profile = profile->next) { - OSPPProviderDelete(profile->provider, 0); - profile->provider = OSP_INVALID_HANDLE; - } - - OSPPCleanup(); + return SWITCH_STATUS_SUCCESS; } /* @@ -2485,14 +2721,18 @@ static void osp_cleanup_osptk(void) */ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_osp_shutdown) { - /* Shutdown OSP module */ - osp_globals.shutdown = SWITCH_TRUE; + OSP_DEBUG_START; - /* Cleanup OSP Toolkit */ + /* Shutdown OSP module */ + osp_global.shutdown = SWITCH_TRUE; + + /* Cleanup OSP client end */ osp_cleanup_osptk(); - /* Remoeve OSP state handlers */ - switch_core_remove_state_handler(&state_handlers); + /* Remoeve OSP module state handlers */ + switch_core_remove_state_handler(&osp_handlers); + + OSP_DEBUG_END; return SWITCH_STATUS_SUCCESS; } From efaa3a6d3de8f1ddca7f5c0a953118be0cdc16f1 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Fri, 15 Mar 2013 23:17:47 +0800 Subject: [PATCH 033/113] Small cleanup of image handling --- libs/spandsp/src/msvc/spandsp.h | 1 - libs/spandsp/src/spandsp/t42.h | 53 +++++++++++++++- libs/spandsp/src/spandsp/t85.h | 103 ++++++++++++++++++-------------- libs/spandsp/src/t42.c | 6 -- libs/spandsp/src/t85_encode.c | 12 ++-- 5 files changed, 115 insertions(+), 60 deletions(-) diff --git a/libs/spandsp/src/msvc/spandsp.h b/libs/spandsp/src/msvc/spandsp.h index 31e0affc1c..fbdfac8e49 100644 --- a/libs/spandsp/src/msvc/spandsp.h +++ b/libs/spandsp/src/msvc/spandsp.h @@ -98,7 +98,6 @@ #include #include #include -/*#include not sure why this is here I cant find it in the filesystem */ #include #include #include diff --git a/libs/spandsp/src/spandsp/t42.h b/libs/spandsp/src/spandsp/t42.h index fe2c83aeab..b864b17536 100644 --- a/libs/spandsp/src/spandsp/t42.h +++ b/libs/spandsp/src/spandsp/t42.h @@ -104,26 +104,60 @@ SPAN_DECLARE(int) t42_encode_set_row_read_handler(t42_encode_state_t *s, \return A pointer to the logging context */ SPAN_DECLARE(logging_state_t *) t42_encode_get_logging_state(t42_encode_state_t *s); +/*! \brief Restart a T.42 encode context. + \param s The T.42 context. + \param image image_width The image width, in pixels. + \param image image_width The image length, in pixels. + \return 0 for success, otherwise -1. */ SPAN_DECLARE(int) t42_encode_restart(t42_encode_state_t *s, uint32_t image_width, uint32_t image_length); +/*! \brief Prepare to encode an image in T.42 format. + \param s The T.42 context. + \param image_width Image width, in pixels. + \param image_length Image length, in pixels. + \param handler A callback routine to handle encoded image rows. + \param user_data An opaque pointer passed to handler. + \return A pointer to the context, or NULL if there was a problem. */ SPAN_DECLARE(t42_encode_state_t *) t42_encode_init(t42_encode_state_t *s, uint32_t image_width, uint32_t image_length, t4_row_read_handler_t handler, void *user_data); +/*! \brief Release a T.42 encode context. + \param s The T.42 encode context. + \return 0 for OK, else -1. */ SPAN_DECLARE(int) t42_encode_release(t42_encode_state_t *s); +/*! \brief Free a T.42 encode context. + \param s The T.42 encode context. + \return 0 for OK, else -1. */ SPAN_DECLARE(int) t42_encode_free(t42_encode_state_t *s); SPAN_DECLARE(void) t42_decode_rx_status(t42_decode_state_t *s, int status); +/*! \brief Decode a chunk of T.42 data. + \param s The T.42 context. + \param data The data to be decoded. + \param len The length of the data to be decoded. + \return 0 for OK. */ SPAN_DECLARE(int) t42_decode_put(t42_decode_state_t *s, const uint8_t data[], size_t len); +/*! \brief Set the row handler routine. + \param s The T.42 context. + \param handler A callback routine to handle decoded image rows. + \param user_data An opaque pointer passed to handler. + \return 0 for OK. */ SPAN_DECLARE(int) t42_decode_set_row_write_handler(t42_decode_state_t *s, t4_row_write_handler_t handler, void *user_data); +/*! \brief Set the comment handler routine. + \param s The T.42 context. + \param max_comment_len The maximum length of comment to be passed to the handler. + \param handler A callback routine to handle decoded comment. + \param user_data An opaque pointer passed to handler. + \return 0 for OK. */ SPAN_DECLARE(int) t42_decode_set_comment_handler(t42_decode_state_t *s, uint32_t max_comment_len, t4_row_write_handler_t handler, @@ -133,14 +167,18 @@ SPAN_DECLARE(int) t42_decode_set_image_size_constraints(t42_decode_state_t *s, uint32_t max_xd, uint32_t max_yd); +/*! \brief Get the width of the image. + \param s The T.42 context. + \return The width of the image, in pixels. */ SPAN_DECLARE(uint32_t) t42_decode_get_image_width(t42_decode_state_t *s); +/*! \brief Get the length of the image. + \param s The T.42 context. + \return The length of the image, in pixels. */ SPAN_DECLARE(uint32_t) t42_decode_get_image_length(t42_decode_state_t *s); SPAN_DECLARE(int) t42_decode_get_compressed_image_size(t42_decode_state_t *s); -SPAN_DECLARE(int) t42_decode_new_plane(t42_decode_state_t *s); - /*! Get the logging context associated with a T.42 decode context. \brief Get the logging context associated with a T.42 decode context. \param s The T.42 decode context. @@ -149,12 +187,23 @@ SPAN_DECLARE(logging_state_t *) t42_decode_get_logging_state(t42_decode_state_t SPAN_DECLARE(int) t42_decode_restart(t42_decode_state_t *s); +/*! \brief Prepare to decode an image in T.42 format. + \param s The T.42 context. + \param handler A callback routine to handle decoded image rows. + \param user_data An opaque pointer passed to handler. + \return A pointer to the context, or NULL if there was a problem. */ SPAN_DECLARE(t42_decode_state_t *) t42_decode_init(t42_decode_state_t *s, t4_row_write_handler_t handler, void *user_data); +/*! \brief Release a T.42 decode context. + \param s The T.42 decode context. + \return 0 for OK, else -1. */ SPAN_DECLARE(int) t42_decode_release(t42_decode_state_t *s); +/*! \brief Free a T.42 decode context. + \param s The T.42 decode context. + \return 0 for OK, else -1. */ SPAN_DECLARE(int) t42_decode_free(t42_decode_state_t *s); #if defined(__cplusplus) diff --git a/libs/spandsp/src/spandsp/t85.h b/libs/spandsp/src/spandsp/t85.h index 29bd6ad7c1..d229026197 100644 --- a/libs/spandsp/src/spandsp/t85.h +++ b/libs/spandsp/src/spandsp/t85.h @@ -93,31 +93,6 @@ SPAN_DECLARE(int) t85_encode_set_row_read_handler(t85_encode_state_t *s, \return A pointer to the logging context */ SPAN_DECLARE(logging_state_t *) t85_encode_get_logging_state(t85_encode_state_t *s); -/*! \brief Prepare to encode an image in T.85 format. - \param s The T.85 context. - \param image_width Image width, in pixels. - \param image_length Image length, in pixels. - \param handler A callback routine to handle encoded image rows. - \param user_data An opaque pointer passed to handler. - \return A pointer to the context, or NULL if there was a problem. */ -SPAN_DECLARE(t85_encode_state_t *) t85_encode_init(t85_encode_state_t *s, - uint32_t image_width, - uint32_t image_length, - t4_row_read_handler_t handler, - void *user_data); - -/*! \brief Restart a T.85 encode context. - \param s The T.85 context. - \param image width The image width, in pixels. - \return 0 for success, otherwise -1. */ -SPAN_DECLARE(int) t85_encode_restart(t85_encode_state_t *s, - uint32_t image_width, - uint32_t image_length); - -SPAN_DECLARE(int) t85_encode_release(t85_encode_state_t *s); - -SPAN_DECLARE(int) t85_encode_free(t85_encode_state_t *s); - /*! \brief Set the T.85 options \param s The T.85 context. \brief l0 ??? @@ -138,7 +113,7 @@ SPAN_DECLARE(void) t85_encode_comment(t85_encode_state_t *s, /*! \brief Set the image width. \param s The T.85 context. - \param width The width of the image. + \param image_width The width of the image. \return 0 for success, otherwise -1. */ SPAN_DECLARE(int) t85_encode_set_image_width(t85_encode_state_t *s, uint32_t image_width); @@ -147,9 +122,9 @@ SPAN_DECLARE(int) t85_encode_set_image_width(t85_encode_state_t *s, uint32_t ima will be silently adjusted to the current length. Therefore, adjust the length to 1 will make the currently encoded length the final length. \param s The T.85 context. - \param length The new image length, in pixels. + \param image_length The new image length, in pixels. \return 0 if OK, or -1 if the request was not valid. */ -SPAN_DECLARE(int) t85_encode_set_image_length(t85_encode_state_t *s, uint32_t length); +SPAN_DECLARE(int) t85_encode_set_image_length(t85_encode_state_t *s, uint32_t image_length); /*! \brief Get the width of the image. \param s The T.85 context. @@ -170,29 +145,44 @@ SPAN_DECLARE(int) t85_encode_get_compressed_image_size(t85_encode_state_t *s); \param s The T.85 context. */ SPAN_DECLARE(void) t85_encode_abort(t85_encode_state_t *s); +/*! \brief Restart a T.85 encode context. + \param s The T.85 context. + \param image_width The image width, in pixels. + \param image_length The image length, in pixels. + \return 0 for success, otherwise -1. */ +SPAN_DECLARE(int) t85_encode_restart(t85_encode_state_t *s, + uint32_t image_width, + uint32_t image_length); + +/*! \brief Prepare to encode an image in T.85 format. + \param s The T.85 context. + \param image_width The image width, in pixels. + \param image_length The image length, in pixels. + \param handler A callback routine to handle encoded image rows. + \param user_data An opaque pointer passed to handler. + \return A pointer to the context, or NULL if there was a problem. */ +SPAN_DECLARE(t85_encode_state_t *) t85_encode_init(t85_encode_state_t *s, + uint32_t image_width, + uint32_t image_length, + t4_row_read_handler_t handler, + void *user_data); + +/*! \brief Release a T.85 encode context. + \param s The T.85 encode context. + \return 0 for OK, else -1. */ +SPAN_DECLARE(int) t85_encode_release(t85_encode_state_t *s); + +/*! \brief Free a T.85 encode context. + \param s The T.85 encode context. + \return 0 for OK, else -1. */ +SPAN_DECLARE(int) t85_encode_free(t85_encode_state_t *s); + /*! Get the logging context associated with a T.85 decode context. \brief Get the logging context associated with a T.85 decode context. \param s The T.85 decode context. \return A pointer to the logging context */ SPAN_DECLARE(logging_state_t *) t85_decode_get_logging_state(t85_decode_state_t *s); -/*! \brief Prepare to decode an image in T.85 format. - \param s The T.85 context. - \param handler A callback routine to handle decoded image rows. - \param user_data An opaque pointer passed to handler. - \return A pointer to the context, or NULL if there was a problem. */ -SPAN_DECLARE(t85_decode_state_t *) t85_decode_init(t85_decode_state_t *s, - t4_row_write_handler_t handler, - void *user_data); - -SPAN_DECLARE(int) t85_decode_new_plane(t85_decode_state_t *s); - -SPAN_DECLARE(int) t85_decode_restart(t85_decode_state_t *s); - -SPAN_DECLARE(int) t85_decode_release(t85_decode_state_t *s); - -SPAN_DECLARE(int) t85_decode_free(t85_decode_state_t *s); - /*! \brief Get the width of the image. \param s The T.85 context. \return The width of the image, in pixels. */ @@ -208,6 +198,8 @@ SPAN_DECLARE(uint32_t) t85_decode_get_image_length(t85_decode_state_t *s); \return The size of the compressed image, in bits. */ SPAN_DECLARE(int) t85_decode_get_compressed_image_size(t85_decode_state_t *s); +SPAN_DECLARE(int) t85_decode_new_plane(t85_decode_state_t *s); + /*! \brief Set the row handler routine. \param s The T.85 context. \param handler A callback routine to handle decoded image rows. @@ -263,6 +255,27 @@ SPAN_DECLARE(void) t85_decode_rx_status(t85_decode_state_t *s, int status); \return 0 for OK. */ SPAN_DECLARE(int) t85_decode_put(t85_decode_state_t *s, const uint8_t data[], size_t len); +SPAN_DECLARE(int) t85_decode_restart(t85_decode_state_t *s); + +/*! \brief Prepare to decode an image in T.85 format. + \param s The T.85 context. + \param handler A callback routine to handle decoded image rows. + \param user_data An opaque pointer passed to handler. + \return A pointer to the context, or NULL if there was a problem. */ +SPAN_DECLARE(t85_decode_state_t *) t85_decode_init(t85_decode_state_t *s, + t4_row_write_handler_t handler, + void *user_data); + +/*! \brief Release a T.85 decode context. + \param s The T.85 decode context. + \return 0 for OK, else -1. */ +SPAN_DECLARE(int) t85_decode_release(t85_decode_state_t *s); + +/*! \brief Free a T.85 decode context. + \param s The T.85 decode context. + \return 0 for OK, else -1. */ +SPAN_DECLARE(int) t85_decode_free(t85_decode_state_t *s); + #if defined(__cplusplus) } #endif diff --git a/libs/spandsp/src/t42.c b/libs/spandsp/src/t42.c index c8ed0a0804..3028c03472 100644 --- a/libs/spandsp/src/t42.c +++ b/libs/spandsp/src/t42.c @@ -1361,12 +1361,6 @@ SPAN_DECLARE(int) t42_decode_get_compressed_image_size(t42_decode_state_t *s) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) t42_decode_new_plane(t42_decode_state_t *s) -{ - return 0; -} -/*- End of function --------------------------------------------------------*/ - SPAN_DECLARE(logging_state_t *) t42_decode_get_logging_state(t42_decode_state_t *s) { return &s->logging; diff --git a/libs/spandsp/src/t85_encode.c b/libs/spandsp/src/t85_encode.c index 6ce2cae6fb..ed8e47364f 100644 --- a/libs/spandsp/src/t85_encode.c +++ b/libs/spandsp/src/t85_encode.c @@ -529,13 +529,13 @@ SPAN_DECLARE(int) t85_encode_set_image_width(t85_encode_state_t *s, uint32_t ima } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) t85_encode_set_image_length(t85_encode_state_t *s, uint32_t length) +SPAN_DECLARE(int) t85_encode_set_image_length(t85_encode_state_t *s, uint32_t image_length) { /* We must have variable length enabled. We do not allow the length to be changed multiple times. We only allow an image to be shrunk, and not stretched. We do not allow the length to become zero. */ - if (!(s->options & T85_VLENGTH) || s->newlen == NEWLEN_HANDLED || length >= s->yd || length < 1) + if (!(s->options & T85_VLENGTH) || s->newlen == NEWLEN_HANDLED || image_length >= s->yd || image_length < 1) { /* Invalid parameter */ return -1; @@ -544,12 +544,12 @@ SPAN_DECLARE(int) t85_encode_set_image_length(t85_encode_state_t *s, uint32_t le { /* TODO: If we are already beyond the new length, we scale back the new length silently. Is there any downside to this? */ - if (length < s->y) - length = s->y; - if (s->yd != length) + if (image_length < s->y) + image_length = s->y; + if (s->yd != image_length) s->newlen = NEWLEN_PENDING; } - s->yd = length; + s->yd = image_length; if (s->y == s->yd) { /* We are already at the end of the image, so finish it off. */ From a28f19b7a27091cd6a9cd58aed70cea5eae1ffd5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 15 Mar 2013 09:24:47 -0500 Subject: [PATCH 034/113] FS-5011 update to this version and repost the same trace if you still have problems --- src/switch_core_io.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 696de1cab0..4298942eb6 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -104,7 +104,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi { switch_io_event_hook_read_frame_t *ptr; switch_status_t status = SWITCH_STATUS_FALSE; - int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0; + int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0, tap_only = 0; switch_codec_implementation_t codec_impl; unsigned int flag = 0; int i; @@ -251,6 +251,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_media_bug_t *bp; switch_bool_t ok = SWITCH_TRUE; int prune = 0; + + tap_only = 1; switch_thread_rwlock_rdlock(session->bug_rwlock); @@ -268,6 +270,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi } if (bp->ready) { + if (!switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) { + tap_only = 0; + } + if (switch_test_flag(bp, SMBF_TAP_NATIVE_READ)) { if (bp->callback) { bp->native_read_frame = *frame; @@ -331,6 +337,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi need_codec = 0; } + if (tap_only) { + need_codec = 0; + } + if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) { switch_core_session_t *other_session; From ee308f00deb27ce6c2402549dc68d354837d1666 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 15 Mar 2013 09:36:57 -0500 Subject: [PATCH 035/113] FS-4875 --resolve --- src/switch_ivr_originate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index ad70f150fc..e273e76ed6 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2238,6 +2238,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } } + if ((var_val = switch_event_get_header(var_event, "fax_enable_t38_request"))) { + switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ignore_early_media", "true"); + } + if ((var_val = switch_event_get_header(var_event, "ignore_early_media"))) { if (switch_true(var_val)) { oglobals.early_ok = 0; From 424738e9c508adfb4fc9ae94e2aa201fb0262580 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 15 Mar 2013 09:40:01 -0500 Subject: [PATCH 036/113] FS-5184 --resolve never too much logging --- src/mod/applications/mod_voicemail/mod_voicemail.c | 6 ++++++ src/mod/endpoints/mod_skinny/mod_skinny.c | 1 + 2 files changed, 7 insertions(+) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index e3fe91da88..b18b64ec9c 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1855,6 +1855,8 @@ static void update_mwi(vm_profile_t *profile, const char *id, const char *domain switch_event_t *event; switch_event_t *message_event; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Update MWI: Processing for %s@%s in %s\n", id, domain_name, myfolder); + message_count(profile, id, domain_name, myfolder, &total_new_messages, &total_saved_messages, &total_new_urgent_messages, &total_saved_urgent_messages); @@ -1876,6 +1878,10 @@ static void update_mwi(vm_profile_t *profile, const char *id, const char *domain switch_event_fire(&event); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Update MWI: Messages Waiting %s\n", yn); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Update MWI: Update Reason %s\n", update_reason); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Update MWI: Message Account %s@%s\n", id, domain_name); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Update MWI: Voice Message %d/%d\n", total_new_messages, total_saved_messages); switch_event_create_subclass(&message_event, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "VM-Action", "mwi-update"); diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index cb5597487b..5325db6be0 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -2112,6 +2112,7 @@ static void skinny_message_waiting_event_handler(switch_event_t *event) switch_assert(dup_account != NULL); switch_split_user_domain(dup_account, &user, &host); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "MWI Event received for account %s with messages waiting %s\n", account, yn); if ((pname = switch_event_get_header(event, "skinny-profile"))) { if (!(profile = skinny_find_profile(pname))) { From e917202d5ec1f59b7fe0775b5038d22cdd7d5111 Mon Sep 17 00:00:00 2001 From: Christopher Rienzo Date: Fri, 15 Mar 2013 19:53:13 -0400 Subject: [PATCH 037/113] FS-5188 --resolve Allow full path to grammar in mod_pocketsphinx --- src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c b/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c index 995fe737d2..2730011967 100644 --- a/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c +++ b/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c @@ -125,7 +125,12 @@ static switch_status_t pocketsphinx_asr_load_grammar(switch_asr_handle_t *ah, co } if (switch_is_file_path(grammar)) { - jsgf = switch_mprintf("%s.gram", grammar); + char *dot = strrchr(grammar, '.'); + if (dot && !strcmp(dot, ".gram")) { + jsgf = strdup(grammar); + } else { + jsgf = switch_mprintf("%s.gram", grammar); + } } else { jsgf = switch_mprintf("%s%s%s.gram", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, grammar); } From a684e7511d617ae97c305f5475829bfdcf072af1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 15 Mar 2013 14:20:40 -0500 Subject: [PATCH 038/113] fix cache file messup --- src/mod/applications/mod_httapi/mod_httapi.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 4b53b87fe5..fd84b8e86b 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -2289,7 +2289,7 @@ SWITCH_STANDARD_APP(httapi_function) static char *load_cache_data(http_file_context_t *context, const char *url) { - char *ext = NULL; + char *ext = NULL, *dext = NULL, *p; char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 }; char meta_buffer[1024] = ""; int fd; @@ -2308,6 +2308,14 @@ static char *load_cache_data(http_file_context_t *context, const char *url) ext = "wav"; } } + + if (ext && (p = strchr(ext, '?'))) { + dext = strdup(ext); + if ((p = strchr(dext, '?'))) { + *p = '\0'; + ext = dext; + } else free(dext); + } context->cache_file_base = switch_core_sprintf(context->pool, "%s%s%s", globals.cache_path, SWITCH_PATH_SEPARATOR, digest); context->cache_file = switch_core_sprintf(context->pool, "%s%s%s.%s", globals.cache_path, SWITCH_PATH_SEPARATOR, digest, ext); @@ -2329,6 +2337,8 @@ static char *load_cache_data(http_file_context_t *context, const char *url) close(fd); } + switch_safe_free(dext); + return context->cache_file; } @@ -2600,6 +2610,12 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char if (newext) { + char *p; + + if ((p = strrchr(context->cache_file, '.'))) { + *p = '\0'; + } + context->cache_file = switch_core_sprintf(context->pool, "%s.%s", context->cache_file, newext); } From bd72a7fc602a3cd18dbdd47f8abc34116d20b11b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 15 Mar 2013 15:09:58 -0500 Subject: [PATCH 039/113] fix seg when piggybacking mono files with stereo in file stream --- src/mod/applications/mod_dptools/mod_dptools.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 3f6bc9339b..bd1a82fc80 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -4508,6 +4508,12 @@ static switch_status_t next_file(switch_file_handle_t *handle) goto top; } + if (handle->dbuflen) { + free(handle->dbuf); + handle->dbuflen = 0; + handle->dbuf = NULL; + } + handle->samples = context->fh.samples; //handle->samplerate = context->fh.samplerate; //handle->channels = context->fh.channels; @@ -4564,6 +4570,7 @@ static switch_status_t file_string_file_open(switch_file_handle_t *handle, const context->index = -1; handle->private_info = context; + handle->pre_buffer_datalen = 0; return next_file(handle); } From abdc4bf09120cbba4d8685489d7e46128696bd40 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 15 Mar 2013 15:24:55 -0500 Subject: [PATCH 040/113] add some more mime types for wav and mp3 --- src/include/switch_utils.h | 1 + src/mod/applications/mod_httapi/mod_httapi.c | 5 +++-- src/switch_utils.c | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 89b60ed82d..f3e5d33a18 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -898,6 +898,7 @@ SWITCH_DECLARE(const char *) switch_cut_path(const char *in); SWITCH_DECLARE(char *) switch_string_replace(const char *string, const char *search, const char *replace); SWITCH_DECLARE(switch_status_t) switch_string_match(const char *string, size_t string_len, const char *search, size_t search_len); +SWITCH_DECLARE(int) switch_strcasecmp_any(const char *str, ...); /*! \brief Quote shell argument diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index fd84b8e86b..9026333004 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -2601,9 +2601,10 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char if ((!context->url_params || !switch_event_get_header(context->url_params, "ext")) && headers && (ct = switch_event_get_header(headers, "content-type"))) { - if (!strcasecmp(ct, "audio/mpeg")) { + if (switch_strcasecmp_any(ct, "audio/mpeg", "audio/x-mpeg", "audio/mp3", "audio/x-mp3", "audio/mpeg3", + "audio/x-mpeg3", "audio/mpg", "audio/x-mpg", "audio/x-mpegaudio")) { newext = "mp3"; - } else if (!strcasecmp(ct, "audio/wav")) { + } else if (switch_strcasecmp_any(ct, "audio/wav", "audio/x-wave", "audio/wav")) { newext = "wav"; } } diff --git a/src/switch_utils.c b/src/switch_utils.c index 3051f156cf..efbc335486 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -122,6 +122,26 @@ SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame) return SWITCH_STATUS_SUCCESS; } +SWITCH_DECLARE(int) switch_strcasecmp_any(const char *str, ...) +{ + va_list ap; + const char *next_str = 0; + int r = 0; + + va_start(ap, str); + + while ((next_str = va_arg(ap, const char *))) { + if (!strcasecmp(str, next_str)) { + r = 1; + break; + } + } + + va_end(ap); + + return r; +} + SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool) { From f3683699457fdd819ed961aa8e32375f7970a278 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 15 Mar 2013 20:47:03 -0500 Subject: [PATCH 041/113] FS-5187 --resolve A 1 character typo.... --- src/mod/applications/mod_conference/mod_conference.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 25b5f29d69..c5b3049a38 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -4130,7 +4130,7 @@ static void conference_send_all_dtmf(conference_member_t *member, conference_obj switch_zmalloc(dt, sizeof(*dt)); *dt = digit; - switch_queue_push(member->dtmf_queue, dt); + switch_queue_push(imember->dtmf_queue, dt); switch_core_session_kill_channel(imember->session, SWITCH_SIG_BREAK); } } From 6af84a870c21836e20077f27a85d94fd382a02be Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sat, 16 Mar 2013 15:35:39 +0800 Subject: [PATCH 042/113] Cleanup of modem filters --- libs/spandsp/src/Makefile.am | 110 ++-- libs/spandsp/src/async.c | 53 +- libs/spandsp/src/libspandsp.2005.vcproj | 31 +- libs/spandsp/src/libspandsp.2008.vcproj | 27 +- libs/spandsp/src/make_modem_filter.c | 206 +++---- libs/spandsp/src/spandsp/private/async.h | 2 + libs/spandsp/src/t30.c | 2 +- libs/spandsp/src/t30_api.c | 2 + libs/spandsp/src/t4_rx.c | 66 ++- .../src/v17_v32bis_tx_constellation_maps.h | 501 +++++++++--------- libs/spandsp/src/v17rx.c | 7 +- libs/spandsp/src/v17tx.c | 36 +- libs/spandsp/src/v22bis_rx.c | 7 +- libs/spandsp/src/v22bis_tx.c | 4 +- libs/spandsp/src/v27ter_rx.c | 64 +-- libs/spandsp/src/v27ter_tx.c | 7 +- libs/spandsp/src/v29rx.c | 16 +- libs/spandsp/src/v29tx.c | 11 +- libs/spandsp/src/v29tx_constellation_maps.h | 66 +-- libs/spandsp/tests/regression_tests.sh | 9 + 20 files changed, 606 insertions(+), 621 deletions(-) diff --git a/libs/spandsp/src/Makefile.am b/libs/spandsp/src/Makefile.am index 95e9932c3c..aad3b91dd7 100644 --- a/libs/spandsp/src/Makefile.am +++ b/libs/spandsp/src/Makefile.am @@ -391,133 +391,89 @@ t42.lo: cielab_luts.h cielab_luts.h: make_cielab_luts$(EXEEXT) ./make_cielab_luts$(EXEEXT) >cielab_luts.h -V17_V32BIS_RX_INCL = v17_v32bis_rx_fixed_rrc.h \ - v17_v32bis_rx_floating_rrc.h +V17_V32BIS_RX_INCL = v17_v32bis_rx_rrc.h v17rx.$(OBJEXT): ${V17_V32BIS_RX_INCL} v17rx.lo: ${V17_V32BIS_RX_INCL} -v17_v32bis_rx_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.17 -i -r >v17_v32bis_rx_fixed_rrc.h +v17_v32bis_rx_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.17 -r >v17_v32bis_rx_rrc.h -v17_v32bis_rx_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.17 -r >v17_v32bis_rx_floating_rrc.h - -V17_V32BIS_TX_INCL = v17_v32bis_tx_fixed_rrc.h \ - v17_v32bis_tx_floating_rrc.h +V17_V32BIS_TX_INCL = v17_v32bis_tx_rrc.h v17tx.$(OBJEXT): ${V17_V32BIS_TX_INCL} v17tx.lo: ${V17_V32BIS_TX_INCL} -v17_v32bis_tx_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.17 -i -t >v17_v32bis_tx_fixed_rrc.h +v17_v32bis_tx_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.17 -t >v17_v32bis_tx_rrc.h -v17_v32bis_tx_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.17 -t >v17_v32bis_tx_floating_rrc.h - -V22BIS_RX_INCL = v22bis_rx_1200_fixed_rrc.h \ - v22bis_rx_2400_fixed_rrc.h \ - v22bis_rx_1200_floating_rrc.h \ - v22bis_rx_2400_floating_rrc.h +V22BIS_RX_INCL = v22bis_rx_1200_rrc.h \ + v22bis_rx_2400_rrc.h v22bis_rx.$(OBJEXT): ${V22BIS_RX_INCL} v22bis_rx.lo: ${V22BIS_RX_INCL} -v22bis_rx_1200_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.22bis1200 -i -r >v22bis_rx_1200_fixed_rrc.h +v22bis_rx_1200_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.22bis1200 -r >v22bis_rx_1200_rrc.h -v22bis_rx_2400_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.22bis2400 -i -r >v22bis_rx_2400_fixed_rrc.h +v22bis_rx_2400_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.22bis2400 -r >v22bis_rx_2400_rrc.h -v22bis_rx_1200_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.22bis1200 -r >v22bis_rx_1200_floating_rrc.h - -v22bis_rx_2400_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.22bis2400 -r >v22bis_rx_2400_floating_rrc.h - -V22BIS_TX_INCL = v22bis_tx_fixed_rrc.h \ - v22bis_tx_floating_rrc.h +V22BIS_TX_INCL = v22bis_tx_rrc.h v22bis_tx.$(OBJEXT): ${V22BIS_TX_INCL} v22bis_tx.lo: ${V22BIS_TX_INCL} -v22bis_tx_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.22bis -i -t >v22bis_tx_fixed_rrc.h +v22bis_tx_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.22bis -t >v22bis_tx_rrc.h -v22bis_tx_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.22bis -t >v22bis_tx_floating_rrc.h - -V27_RX_INCL = v27ter_rx_2400_fixed_rrc.h \ - v27ter_rx_4800_fixed_rrc.h \ - v27ter_rx_2400_floating_rrc.h \ - v27ter_rx_4800_floating_rrc.h +V27_RX_INCL = v27ter_rx_2400_rrc.h \ + v27ter_rx_4800_rrc.h v27ter_rx.$(OBJEXT): ${V27_RX_INCL} v27ter_rx.lo: ${V27_RX_INCL} -v27ter_rx_2400_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter2400 -i -r >v27ter_rx_2400_fixed_rrc.h +v27ter_rx_2400_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.27ter2400 -r >v27ter_rx_2400_rrc.h -v27ter_rx_4800_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter4800 -i -r >v27ter_rx_4800_fixed_rrc.h +v27ter_rx_4800_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.27ter4800 -r >v27ter_rx_4800_rrc.h -v27ter_rx_2400_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter2400 -r >v27ter_rx_2400_floating_rrc.h - -v27ter_rx_4800_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter4800 -r >v27ter_rx_4800_floating_rrc.h - -V27TER_TX_INCL = v27ter_tx_2400_fixed_rrc.h \ - v27ter_tx_4800_fixed_rrc.h \ - v27ter_tx_2400_floating_rrc.h \ - v27ter_tx_4800_floating_rrc.h +V27TER_TX_INCL = v27ter_tx_2400_rrc.h \ + v27ter_tx_4800_rrc.h v27ter_tx_.$(OBJEXT): ${V27TER_TX_INCL} v27ter_tx.lo: ${V27TER_TX_INCL} -v27ter_tx_2400_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter2400 -i -t >v27ter_tx_2400_fixed_rrc.h +v27ter_tx_2400_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.27ter2400 -t >v27ter_tx_2400_rrc.h -v27ter_tx_4800_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter4800 -i -t >v27ter_tx_4800_fixed_rrc.h +v27ter_tx_4800_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.27ter4800 -t >v27ter_tx_4800_rrc.h -v27ter_tx_2400_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter2400 -t >v27ter_tx_2400_floating_rrc.h - -v27ter_tx_4800_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.27ter4800 -t >v27ter_tx_4800_floating_rrc.h - -V29_RX_INCL = v29rx_fixed_rrc.h \ - v29rx_floating_rrc.h +V29_RX_INCL = v29rx_rrc.h v29rx.$(OBJEXT): ${V29_RX_INCL} v29rx.lo: ${V29_RX_INCL} -v29rx_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.29 -i -r >v29rx_fixed_rrc.h +v29rx_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.29 -r >v29rx_rrc.h -v29rx_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.29 -r >v29rx_floating_rrc.h - -V29_TX_INCL = v29tx_fixed_rrc.h \ - v29tx_floating_rrc.h +V29_TX_INCL = v29tx_rrc.h v29tx.$(OBJEXT): ${V29_TX_INCL} v29tx.lo: ${V29_TX_INCL} -v29tx_fixed_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.29 -i -t >v29tx_fixed_rrc.h - -v29tx_floating_rrc.h: make_modem_filter$(EXEEXT) - ./make_modem_filter$(EXEEXT) -m V.29 -t >v29tx_floating_rrc.h +v29tx_rrc.h: make_modem_filter$(EXEEXT) + ./make_modem_filter$(EXEEXT) -m V.29 -t >v29tx_rrc.h DSP = libspandsp.dsp VCPROJ8 = libspandsp.2005.vcproj diff --git a/libs/spandsp/src/async.c b/libs/spandsp/src/async.c index 4df12dffb6..fb381bb7bc 100644 --- a/libs/spandsp/src/async.c +++ b/libs/spandsp/src/async.c @@ -212,42 +212,46 @@ SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data) { async_tx_state_t *s; int bit; + int parity_bit; s = (async_tx_state_t *) user_data; if (s->bitpos == 0) { + if (s->presend_bits > 0) + { + s->presend_bits--; + return 1; + } if ((s->byte_in_progress = s->get_byte(s->user_data)) < 0) { - /* No more data */ - bit = SIG_STATUS_END_OF_DATA; + if (s->byte_in_progress != SIG_STATUS_LINK_IDLE) + return s->byte_in_progress; + /* Idle for a bit time. If the get byte call configured a presend + time we might idle for longer. */ + return 1; + } + s->byte_in_progress &= (0xFFFF >> (16 - s->data_bits)); + if (s->parity != ASYNC_PARITY_NONE) + { + parity_bit = parity8(s->byte_in_progress); + if (s->parity == ASYNC_PARITY_ODD) + parity_bit ^= 1; + s->byte_in_progress |= (parity_bit << s->data_bits); + s->byte_in_progress |= (0xFFFF << (s->data_bits + 1)); } else { - /* Start bit */ - bit = 0; - s->parity_bit = 0; - s->bitpos++; + s->byte_in_progress |= (0xFFFF << s->data_bits); } - } - else if (s->bitpos <= s->data_bits) - { - bit = s->byte_in_progress & 1; - s->byte_in_progress >>= 1; - s->parity_bit ^= bit; - s->bitpos++; - } - else if (s->parity && s->bitpos == s->data_bits + 1) - { - if (s->parity == ASYNC_PARITY_ODD) - s->parity_bit ^= 1; - bit = s->parity_bit; + /* Start bit */ + bit = 0; s->bitpos++; } else { - /* Stop bit(s) */ - bit = 1; - if (++s->bitpos > s->data_bits + s->stop_bits) + bit = s->byte_in_progress & 1; + s->byte_in_progress >>= 1; + if (++s->bitpos > s->total_bits) s->bitpos = 0; } return bit; @@ -278,16 +282,15 @@ SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s, flow control does not exist, so V.14 stuffing is not needed. */ s->data_bits = data_bits; s->parity = parity; - s->stop_bits = stop_bits; + s->total_bits = data_bits + stop_bits; if (parity != ASYNC_PARITY_NONE) - s->stop_bits++; + s->total_bits++; s->get_byte = get_byte; s->user_data = user_data; s->byte_in_progress = 0; s->bitpos = 0; - s->parity_bit = 0; s->presend_bits = 0; return s; } diff --git a/libs/spandsp/src/libspandsp.2005.vcproj b/libs/spandsp/src/libspandsp.2005.vcproj index 4ed3af322a..a89a59b23d 100644 --- a/libs/spandsp/src/libspandsp.2005.vcproj +++ b/libs/spandsp/src/libspandsp.2005.vcproj @@ -92,6 +92,7 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + @@ -123,12 +124,14 @@ + + @@ -143,6 +146,8 @@ + + @@ -154,8 +159,13 @@ + + + + + @@ -174,6 +184,7 @@ + @@ -205,8 +216,10 @@ + + @@ -222,8 +235,6 @@ - - @@ -234,8 +245,16 @@ + + + + + + + + @@ -253,6 +272,7 @@ + @@ -271,6 +291,7 @@ + @@ -293,7 +314,13 @@ + + + + + + diff --git a/libs/spandsp/src/libspandsp.2008.vcproj b/libs/spandsp/src/libspandsp.2008.vcproj index bd4e236b17..96af303167 100644 --- a/libs/spandsp/src/libspandsp.2008.vcproj +++ b/libs/spandsp/src/libspandsp.2008.vcproj @@ -342,6 +342,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -702,18 +706,15 @@ - - - + + @@ -842,6 +843,10 @@ RelativePath="spandsp/ima_adpcm.h" > + + @@ -878,6 +883,10 @@ RelativePath="spandsp/power_meter.h" > + + @@ -950,6 +959,10 @@ RelativePath="spandsp/private/ima_adpcm.h" > + + diff --git a/libs/spandsp/src/make_modem_filter.c b/libs/spandsp/src/make_modem_filter.c index 593f894cbf..8ceac8aab9 100644 --- a/libs/spandsp/src/make_modem_filter.c +++ b/libs/spandsp/src/make_modem_filter.c @@ -66,7 +66,6 @@ static void make_tx_filter(int coeff_sets, double carrier, double baud_rate, double excess_bandwidth, - int fixed_point, const char *tag) { int i; @@ -75,8 +74,9 @@ static void make_tx_filter(int coeff_sets, int total_coeffs; double alpha; double beta; - double gain; - double scaling; + double floating_gain; + double fixed_gain; + double fixed_scaling; double peak; double coeffs[MAX_COEFF_SETS*MAX_COEFFS_PER_FILTER + 1]; @@ -87,63 +87,63 @@ static void make_tx_filter(int coeff_sets, compute_raised_cosine_filter(coeffs, total_coeffs, TRUE, FALSE, alpha, beta); /* Find the DC gain of the filter, and adjust the filter to unity gain. */ - gain = 0.0; + floating_gain = 0.0; for (i = coeff_sets/2; i < total_coeffs; i += coeff_sets) - gain += coeffs[i]; + floating_gain += coeffs[i]; /* Normalise the gain to 1.0 */ for (i = 0; i < total_coeffs; i++) - coeffs[i] /= gain; - gain = 1.0; + coeffs[i] /= floating_gain; + floating_gain = 1.0; + fixed_gain = 1.0; - if (fixed_point) + peak = -1.0; + for (i = 0; i < total_coeffs; i++) { - peak = -1.0; - for (i = 0; i < total_coeffs; i++) - { - if (fabs(coeffs[i]) > peak) - peak = fabs(coeffs[i]); - } - scaling = 32767.0; - if (peak >= 1.0) - { - scaling /= peak; - gain = 1.0/peak; - } - for (i = 0; i < total_coeffs; i++) - coeffs[i] *= scaling; + if (fabs(coeffs[i]) > peak) + peak = fabs(coeffs[i]); + } + fixed_scaling = 32767.0f; + if (peak >= 1.0) + { + fixed_scaling /= peak; + fixed_gain = 1.0/peak; } /* Churn out the data as a C source code header file, which can be directly included by the modem code. */ - printf("#define TX_PULSESHAPER%s_GAIN %ff\n", tag, gain); + printf("#if defined(SPANDSP_USE_FIXED_POINT)\n"); + printf("#define TX_PULSESHAPER%s_SCALE(x) ((int16_t) (%f*x + ((x >= 0.0) ? 0.5 : -0.5)))\n", tag, fixed_scaling); + printf("#define TX_PULSESHAPER%s_GAIN %ff\n", tag, fixed_gain); + printf("#else\n"); + printf("#define TX_PULSESHAPER%s_SCALE(x) (x)\n", tag); + printf("#define TX_PULSESHAPER%s_GAIN %ff\n", tag, floating_gain); + printf("#endif\n"); printf("#define TX_PULSESHAPER%s_COEFF_SETS %d\n", tag, coeff_sets); - printf("static const %s tx_pulseshaper%s[TX_PULSESHAPER%s_COEFF_SETS][%d] =\n", - (fixed_point) ? "int16_t" : "float", + printf("\n"); + printf("#if defined(SPANDSP_USE_FIXED_POINT)\n"); + printf("static const int16_t tx_pulseshaper%s[TX_PULSESHAPER%s_COEFF_SETS][%d] =\n", tag, tag, coeffs_per_filter); + printf("#else\n"); + printf("static const float tx_pulseshaper%s[TX_PULSESHAPER%s_COEFF_SETS][%d] =\n", + tag, + tag, + coeffs_per_filter); + printf("#endif\n"); printf("{\n"); for (j = 0; j < coeff_sets; j++) { x = j; printf(" {\n"); - if (fixed_point) - printf(" %8d, /* Filter %d */\n", (int) coeffs[x], j); - else - printf(" %15.10ff, /* Filter %d */\n", coeffs[x], j); + printf(" TX_PULSESHAPER%s_SCALE(%15.10ff), /* Filter %d */\n", tag, coeffs[x], j); for (i = 1; i < coeffs_per_filter - 1; i++) { x = i*coeff_sets + j; - if (fixed_point) - printf(" %8d,\n", (int) coeffs[x]); - else - printf(" %15.10ff,\n", coeffs[x]); + printf(" TX_PULSESHAPER%s_SCALE(%15.10ff),\n", tag, coeffs[x]); } x = i*coeff_sets + j; - if (fixed_point) - printf(" %8d\n", (int) coeffs[x]); - else - printf(" %15.10ff\n", coeffs[x]); + printf(" TX_PULSESHAPER%s_SCALE(%15.10ff)\n", tag, coeffs[x]); if (j < coeff_sets - 1) printf(" },\n"); else @@ -158,7 +158,6 @@ static void make_rx_filter(int coeff_sets, double carrier, double baud_rate, double excess_bandwidth, - int fixed_point, const char *tag) { int i; @@ -169,14 +168,12 @@ static void make_rx_filter(int coeff_sets, int total_coeffs; double alpha; double beta; - double gain; + double floating_gain; + double fixed_gain; + double fixed_scaling; double peak; double coeffs[MAX_COEFF_SETS*MAX_COEFFS_PER_FILTER + 1]; -#if 0 - complex_t co[MAX_COEFFS_PER_FILTER]; -#else double cox[MAX_COEFFS_PER_FILTER]; -#endif total_coeffs = coeff_sets*coeffs_per_filter + 1; alpha = baud_rate/(2.0*(double) (coeff_sets*SAMPLE_RATE)); @@ -186,84 +183,54 @@ static void make_rx_filter(int coeff_sets, compute_raised_cosine_filter(coeffs, total_coeffs, TRUE, FALSE, alpha, beta); /* Find the DC gain of the filter, and adjust the filter to unity gain. */ - gain = 0.0; + floating_gain = 0.0; for (i = coeff_sets/2; i < total_coeffs; i += coeff_sets) - gain += coeffs[i]; + floating_gain += coeffs[i]; /* Normalise the gain to 1.0 */ for (i = 0; i < total_coeffs; i++) - coeffs[i] /= gain; - gain = 1.0; + coeffs[i] /= floating_gain; + floating_gain = 1.0; + fixed_gain = 1.0; - if (fixed_point) + peak = -1.0; + for (i = 0; i < total_coeffs; i++) { - peak = -1.0; - for (i = 0; i < total_coeffs; i++) - { - if (fabs(coeffs[i]) > peak) - peak = fabs(coeffs[i]); - } - gain = 32767.0; - if (peak >= 1.0) - gain /= peak; - for (i = 0; i < total_coeffs; i++) - coeffs[i] *= gain; + if (fabs(coeffs[i]) > peak) + peak = fabs(coeffs[i]); + } + fixed_scaling = 32767.0f; + if (peak >= 1.0) + { + fixed_scaling /= peak; + fixed_gain = 1.0/peak; } /* Churn out the data as a C source code header file, which can be directly included by the modem code. */ - printf("#define RX_PULSESHAPER%s_GAIN %ff\n", tag, gain); + printf("#if defined(SPANDSP_USE_FIXED_POINT)\n"); + printf("#define RX_PULSESHAPER%s_SCALE(x) ((int16_t) (%f*x + ((x >= 0.0) ? 0.5 : -0.5)))\n", tag, fixed_scaling); + printf("#define RX_PULSESHAPER%s_GAIN %ff\n", tag, fixed_gain); + printf("#else\n"); + printf("#define RX_PULSESHAPER%s_SCALE(x) (x)\n", tag); + printf("#define RX_PULSESHAPER%s_GAIN %ff\n", tag, floating_gain); + printf("#endif\n"); printf("#define RX_PULSESHAPER%s_COEFF_SETS %d\n", tag, coeff_sets); -#if 0 - printf("static const %s rx_pulseshaper%s[RX_PULSESHAPER%s_COEFF_SETS][%d] =\n", - (fixed_point) ? "complexi16_t" : "complexf_t", - tag, - tag, - coeffs_per_filter); - printf("{\n"); - for (j = 0; j < coeff_sets; j++) - { - /* Complex modulate the filter, to make it a complex pulse shaping bandpass filter - centred at the nominal carrier frequency. Use the same phase for all the coefficient - sets. This means the modem can step the carrier in whole samples, and not worry about - the fractional sample shift caused by selecting amongst the various coefficient sets. */ - for (i = 0; i < coeffs_per_filter; i++) - { - m = i - (coeffs_per_filter >> 1); - x = i*coeff_sets + j; - co[i].re = coeffs[x]*cos(carrier*m); - co[i].im = coeffs[x]*sin(carrier*m); - } - printf(" {\n"); - if (fixed_point) - printf(" {%8d, %8d}, /* Filter %d */\n", (int) co[i].re, (int) co[i].im, j); - else - printf(" {%15.10ff, %15.10ff}, /* Filter %d */\n", co[0].re, co[0].im, j); - for (i = 1; i < coeffs_per_filter - 1; i++) - { - if (fixed_point) - printf(" {%8d, %8d},\n", (int) co[i].re, (int) co[i].im); - else - printf(" {%15.10ff, %15.10ff},\n", co[i].re, co[i].im); - } - if (fixed_point) - printf(" {%8d, %8d}\n", (int) co[i].re, (int) co[i].im); - else - printf(" {%15.10ff, %15.10ff}\n", co[i].re, co[i].im); - if (j < coeff_sets - 1) - printf(" },\n"); - else - printf(" }\n"); - } - printf("};\n"); -#else for (k = 0; k < 2; k++) { - printf("static const %s rx_pulseshaper%s_%s[RX_PULSESHAPER%s_COEFF_SETS][%d] =\n", - (fixed_point) ? "int16_t" : "float", + printf("\n"); + printf("#if defined(SPANDSP_USE_FIXED_POINT)\n"); + printf("static const int16_t rx_pulseshaper%s_%s[RX_PULSESHAPER%s_COEFF_SETS][%d] =\n", tag, (k == 0) ? "re" : "im", tag, coeffs_per_filter); + printf("#else\n"); + printf("static const float rx_pulseshaper%s_%s[RX_PULSESHAPER%s_COEFF_SETS][%d] =\n", + tag, + (k == 0) ? "re" : "im", + tag, + coeffs_per_filter); + printf("#endif\n"); printf("{\n"); for (j = 0; j < coeff_sets; j++) { @@ -281,21 +248,10 @@ static void make_rx_filter(int coeff_sets, cox[i] = coeffs[x]*sin(carrier*m); } printf(" {\n"); - if (fixed_point) - printf(" %8d, /* Filter %d */\n", (int) cox[0], j); - else - printf(" %15.10ff, /* Filter %d */\n", cox[0], j); + printf(" RX_PULSESHAPER%s_SCALE(%15.10ff), /* Filter %d */\n", tag, cox[0], j); for (i = 1; i < coeffs_per_filter - 1; i++) - { - if (fixed_point) - printf(" %8d,\n", (int) cox[i]); - else - printf(" %15.10ff,\n", cox[i]); - } - if (fixed_point) - printf(" %8d\n", (int) cox[i]); - else - printf(" %15.10ff\n", cox[i]); + printf(" RX_PULSESHAPER%s_SCALE(%15.10ff),\n", tag, cox[i]); + printf(" RX_PULSESHAPER%s_SCALE(%15.10ff)\n", tag, cox[i]); if (j < coeff_sets - 1) printf(" },\n"); else @@ -303,13 +259,12 @@ static void make_rx_filter(int coeff_sets, } printf("};\n"); } -#endif } /*- End of function --------------------------------------------------------*/ static void usage(void) { - fprintf(stderr, "Usage: make_modem_rx_filter -m [-i] [-r] [-t]\n"); + fprintf(stderr, "Usage: make_modem_rx_filter -m [-r] [-t]\n"); } /*- End of function --------------------------------------------------------*/ @@ -321,7 +276,6 @@ int main(int argc, char **argv) int tx_coeffs_per_filter; int opt; int transmit_modem; - int fixed_point; double carrier; double baud_rate; double rx_excess_bandwidth; @@ -330,16 +284,12 @@ int main(int argc, char **argv) const char *tx_tag; const char *modem; - fixed_point = FALSE; transmit_modem = FALSE; modem = ""; - while ((opt = getopt(argc, argv, "im:rt")) != -1) + while ((opt = getopt(argc, argv, "m:rt")) != -1) { switch (opt) { - case 'i': - fixed_point = TRUE; - break; case 'm': modem = optarg; break; @@ -607,7 +557,6 @@ int main(int argc, char **argv) carrier, baud_rate, tx_excess_bandwidth, - fixed_point, tx_tag); } else @@ -617,7 +566,6 @@ int main(int argc, char **argv) carrier, baud_rate, rx_excess_bandwidth, - fixed_point, rx_tag); } return 0; diff --git a/libs/spandsp/src/spandsp/private/async.h b/libs/spandsp/src/spandsp/private/async.h index 7354aaf967..39bb1d4a44 100644 --- a/libs/spandsp/src/spandsp/private/async.h +++ b/libs/spandsp/src/spandsp/private/async.h @@ -39,6 +39,8 @@ struct async_tx_state_s int parity; /*! \brief The number of stop bits per character. */ int stop_bits; + /*! \brief Total number of bits per character, including the parity and stop bits. */ + int total_bits; /*! \brief A pointer to the callback routine used to get characters to be transmitted. */ get_byte_func_t get_byte; /*! \brief An opaque pointer passed when calling get_byte. */ diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 7e9e4c333f..a8ed266f94 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -1538,7 +1538,7 @@ static int build_dcs(t30_state_t *s) || ((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200))) { - span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 0x%x 0x%x\n", s->image_width, s->x_resolution); + span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4\n"); /* No width related bits need to be set. */ } else if (((s->image_width == T4_WIDTH_R8_B4) && (s->x_resolution == T4_X_RESOLUTION_R8)) diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index 495ba6f9b1..e6d157c21e 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -653,6 +653,8 @@ SPAN_DECLARE(int) t30_set_rx_encoding(t30_state_t *s, int encoding) case T4_COMPRESSION_ITU_T4_1D: case T4_COMPRESSION_ITU_T4_2D: case T4_COMPRESSION_ITU_T6: + //case T4_COMPRESSION_ITU_T85: + //case T4_COMPRESSION_ITU_T85_L0: s->output_encoding = encoding; return 0; } diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index eae361941b..0d6950e278 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -146,9 +146,16 @@ static int set_tiff_directory_info(t4_rx_state_t *s) t4_rx_tiff_state_t *t; int32_t output_compression; int32_t output_t4_options; + int bits_per_sample; + int samples_per_pixel; + int photometric; + int image_length; t = &s->tiff; /* Prepare the directory entry fully before writing the image, or libtiff complains */ + bits_per_sample = 1; + samples_per_pixel = 1; + photometric = PHOTOMETRIC_MINISWHITE; switch (t->output_encoding) { case T4_COMPRESSION_ITU_T4_1D: @@ -163,7 +170,24 @@ static int set_tiff_directory_info(t4_rx_state_t *s) case T4_COMPRESSION_ITU_T6: output_compression = COMPRESSION_CCITT_T6; break; +#if defined(SPANDSP_SUPPORT_T42) + case T4_COMPRESSION_ITU_T42: + output_compression = COMPRESSION_JPEG; + bits_per_sample = 8; + samples_per_pixel = 3; + photometric = PHOTOMETRIC_ITULAB; + break; +#endif +#if defined(SPANDSP_SUPPORT_T43) + case T4_COMPRESSION_ITU_T43: + output_compression = COMPRESSION_T43; + bits_per_sample = 8; + samples_per_pixel = 3; + photometric = PHOTOMETRIC_ITULAB; + break; +#endif case T4_COMPRESSION_ITU_T85: + case T4_COMPRESSION_ITU_T85_L0: output_compression = COMPRESSION_T85; break; } @@ -179,28 +203,23 @@ static int set_tiff_directory_info(t4_rx_state_t *s) TIFFSetField(t->tiff_file, TIFFTAG_T6OPTIONS, 0); TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); break; + case COMPRESSION_JPEG: + TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); + break; +#if defined(SPANDSP_SUPPORT_T43) + case COMPRESSION_T43: + TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); + break; +#endif case COMPRESSION_T85: TIFFSetField(t->tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF); - TIFFSetField(t->tiff_file, TIFFTAG_ROWSPERSTRIP, -1L); - break; - default: - TIFFSetField(t->tiff_file, - TIFFTAG_ROWSPERSTRIP, - TIFFDefaultStripSize(t->tiff_file, 0)); break; } -#if defined(SPANDSP_SUPPORT_TIFF_FX) - TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, PROFILETYPE_G3_FAX); - TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, FAXPROFILE_F); - TIFFSetField(t->tiff_file, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6); - TIFFSetField(t->tiff_file, TIFFTAG_VERSIONYEAR, "1998"); - /* TIFFSetField(t->tiff_file, TIFFTAG_MODENUMBER, 0); */ -#endif - TIFFSetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, 1); TIFFSetField(t->tiff_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); - TIFFSetField(t->tiff_file, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, bits_per_sample); + TIFFSetField(t->tiff_file, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel); TIFFSetField(t->tiff_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); + TIFFSetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, photometric); TIFFSetField(t->tiff_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); /* TIFFTAG_STRIPBYTECOUNTS and TIFFTAG_STRIPOFFSETS are added automatically */ @@ -257,6 +276,7 @@ static int set_tiff_directory_info(t4_rx_state_t *s) /* TIFF page numbers start from zero, so the number of pages in the file is always one greater than the highest page number in the file. */ s->tiff.pages_in_file = s->current_page + 1; + image_length = 0; switch (s->line_encoding) { case T4_COMPRESSION_ITU_T4_1D: @@ -277,22 +297,28 @@ static int set_tiff_directory_info(t4_rx_state_t *s) } /* Fall through */ case T4_COMPRESSION_ITU_T6: - TIFFSetField(t->tiff_file, TIFFTAG_IMAGELENGTH, t4_t6_decode_get_image_length(&s->decoder.t4_t6)); + image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6); break; case T4_COMPRESSION_ITU_T42: - TIFFSetField(t->tiff_file, TIFFTAG_IMAGELENGTH, t42_decode_get_image_length(&s->decoder.t42)); + image_length = t42_decode_get_image_length(&s->decoder.t42); break; #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_ITU_T43: - TIFFSetField(t->tiff_file, TIFFTAG_IMAGELENGTH, t43_decode_get_image_length(&s->decoder.t43)); + image_length = t43_decode_get_image_length(&s->decoder.t43); break; #endif case T4_COMPRESSION_ITU_T85: case T4_COMPRESSION_ITU_T85_L0: - TIFFSetField(t->tiff_file, TIFFTAG_IMAGELENGTH, t85_decode_get_image_length(&s->decoder.t85)); + image_length = t85_decode_get_image_length(&s->decoder.t85); break; } + TIFFSetField(t->tiff_file, TIFFTAG_IMAGELENGTH, image_length); + TIFFSetField(t->tiff_file, TIFFTAG_ROWSPERSTRIP, image_length); #if defined(SPANDSP_SUPPORT_TIFF_FX) + TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, PROFILETYPE_G3_FAX); + TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, FAXPROFILE_S); + TIFFSetField(t->tiff_file, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6); + TIFFSetField(t->tiff_file, TIFFTAG_VERSIONYEAR, "1998"); if (s->current_page == 0) { /* Create a placeholder for the global parameters IFD, to be filled in later */ diff --git a/libs/spandsp/src/v17_v32bis_tx_constellation_maps.h b/libs/spandsp/src/v17_v32bis_tx_constellation_maps.h index 8044ad1e32..5ce8db44c8 100644 --- a/libs/spandsp/src/v17_v32bis_tx_constellation_maps.h +++ b/libs/spandsp/src/v17_v32bis_tx_constellation_maps.h @@ -2,12 +2,11 @@ * SpanDSP - a series of DSP components for telephony * * v17_v32bis_tx_constellation_maps.h - ITU V.17 and V.32bis modems - * transmit part. - * Constellation mapping. + * transmit part. Constellation mapping. * * Written by Steve Underwood * - * Copyright (C) 2004 Steve Underwood + * Copyright (C) 2004, 2012 Steve Underwood * * All rights reserved. * @@ -31,134 +30,134 @@ static const complexi16_t v17_v32bis_14400_constellation[128] = static const complexf_t v17_v32bis_14400_constellation[128] = #endif { - {FP_SCALE(-8.0f), FP_SCALE(-3.0f)}, /* 0x00 */ - {FP_SCALE( 9.0f), FP_SCALE( 2.0f)}, /* 0x01 */ - {FP_SCALE( 2.0f), FP_SCALE(-9.0f)}, /* 0x02 */ - {FP_SCALE(-3.0f), FP_SCALE( 8.0f)}, /* 0x03 */ - {FP_SCALE( 8.0f), FP_SCALE( 3.0f)}, /* 0x04 */ - {FP_SCALE(-9.0f), FP_SCALE(-2.0f)}, /* 0x05 */ - {FP_SCALE(-2.0f), FP_SCALE( 9.0f)}, /* 0x06 */ - {FP_SCALE( 3.0f), FP_SCALE(-8.0f)}, /* 0x07 */ - {FP_SCALE(-8.0f), FP_SCALE( 1.0f)}, /* 0x08 */ - {FP_SCALE( 9.0f), FP_SCALE(-2.0f)}, /* 0x09 */ - {FP_SCALE(-2.0f), FP_SCALE(-9.0f)}, /* 0x0A */ - {FP_SCALE( 1.0f), FP_SCALE( 8.0f)}, /* 0x0B */ - {FP_SCALE( 8.0f), FP_SCALE(-1.0f)}, /* 0x0C */ - {FP_SCALE(-9.0f), FP_SCALE( 2.0f)}, /* 0x0D */ - {FP_SCALE( 2.0f), FP_SCALE( 9.0f)}, /* 0x0E */ - {FP_SCALE(-1.0f), FP_SCALE(-8.0f)}, /* 0x0F */ - {FP_SCALE(-4.0f), FP_SCALE(-3.0f)}, /* 0x10 */ - {FP_SCALE( 5.0f), FP_SCALE( 2.0f)}, /* 0x11 */ - {FP_SCALE( 2.0f), FP_SCALE(-5.0f)}, /* 0x12 */ - {FP_SCALE(-3.0f), FP_SCALE( 4.0f)}, /* 0x13 */ - {FP_SCALE( 4.0f), FP_SCALE( 3.0f)}, /* 0x14 */ - {FP_SCALE(-5.0f), FP_SCALE(-2.0f)}, /* 0x15 */ - {FP_SCALE(-2.0f), FP_SCALE( 5.0f)}, /* 0x16 */ - {FP_SCALE( 3.0f), FP_SCALE(-4.0f)}, /* 0x17 */ - {FP_SCALE(-4.0f), FP_SCALE( 1.0f)}, /* 0x18 */ - {FP_SCALE( 5.0f), FP_SCALE(-2.0f)}, /* 0x19 */ - {FP_SCALE(-2.0f), FP_SCALE(-5.0f)}, /* 0x1A */ - {FP_SCALE( 1.0f), FP_SCALE( 4.0f)}, /* 0x1B */ - {FP_SCALE( 4.0f), FP_SCALE(-1.0f)}, /* 0x1C */ - {FP_SCALE(-5.0f), FP_SCALE( 2.0f)}, /* 0x1D */ - {FP_SCALE( 2.0f), FP_SCALE( 5.0f)}, /* 0x1E */ - {FP_SCALE(-1.0f), FP_SCALE(-4.0f)}, /* 0x1F */ - {FP_SCALE( 4.0f), FP_SCALE(-3.0f)}, /* 0x20 */ - {FP_SCALE(-3.0f), FP_SCALE( 2.0f)}, /* 0x21 */ - {FP_SCALE( 2.0f), FP_SCALE( 3.0f)}, /* 0x22 */ - {FP_SCALE(-3.0f), FP_SCALE(-4.0f)}, /* 0x23 */ - {FP_SCALE(-4.0f), FP_SCALE( 3.0f)}, /* 0x24 */ - {FP_SCALE( 3.0f), FP_SCALE(-2.0f)}, /* 0x25 */ - {FP_SCALE(-2.0f), FP_SCALE(-3.0f)}, /* 0x26 */ - {FP_SCALE( 3.0f), FP_SCALE( 4.0f)}, /* 0x27 */ - {FP_SCALE( 4.0f), FP_SCALE( 1.0f)}, /* 0x28 */ - {FP_SCALE(-3.0f), FP_SCALE(-2.0f)}, /* 0x29 */ - {FP_SCALE(-2.0f), FP_SCALE( 3.0f)}, /* 0x2A */ - {FP_SCALE( 1.0f), FP_SCALE(-4.0f)}, /* 0x2B */ - {FP_SCALE(-4.0f), FP_SCALE(-1.0f)}, /* 0x2C */ - {FP_SCALE( 3.0f), FP_SCALE( 2.0f)}, /* 0x2D */ - {FP_SCALE( 2.0f), FP_SCALE(-3.0f)}, /* 0x2E */ - {FP_SCALE(-1.0f), FP_SCALE( 4.0f)}, /* 0x2F */ - {FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 0x30 */ - {FP_SCALE( 1.0f), FP_SCALE( 2.0f)}, /* 0x31 */ - {FP_SCALE( 2.0f), FP_SCALE(-1.0f)}, /* 0x32 */ - {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 0x33 */ - {FP_SCALE( 0.0f), FP_SCALE( 3.0f)}, /* 0x34 */ - {FP_SCALE(-1.0f), FP_SCALE(-2.0f)}, /* 0x35 */ - {FP_SCALE(-2.0f), FP_SCALE( 1.0f)}, /* 0x36 */ - {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0x37 */ - {FP_SCALE( 0.0f), FP_SCALE( 1.0f)}, /* 0x38 */ - {FP_SCALE( 1.0f), FP_SCALE(-2.0f)}, /* 0x39 */ - {FP_SCALE(-2.0f), FP_SCALE(-1.0f)}, /* 0x3A */ - {FP_SCALE( 1.0f), FP_SCALE( 0.0f)}, /* 0x3B */ - {FP_SCALE( 0.0f), FP_SCALE(-1.0f)}, /* 0x3C */ - {FP_SCALE(-1.0f), FP_SCALE( 2.0f)}, /* 0x3D */ - {FP_SCALE( 2.0f), FP_SCALE( 1.0f)}, /* 0x3E */ - {FP_SCALE(-1.0f), FP_SCALE( 0.0f)}, /* 0x3F */ - {FP_SCALE( 8.0f), FP_SCALE(-3.0f)}, /* 0x40 */ - {FP_SCALE(-7.0f), FP_SCALE( 2.0f)}, /* 0x41 */ - {FP_SCALE( 2.0f), FP_SCALE( 7.0f)}, /* 0x42 */ - {FP_SCALE(-3.0f), FP_SCALE(-8.0f)}, /* 0x43 */ - {FP_SCALE(-8.0f), FP_SCALE( 3.0f)}, /* 0x44 */ - {FP_SCALE( 7.0f), FP_SCALE(-2.0f)}, /* 0x45 */ - {FP_SCALE(-2.0f), FP_SCALE(-7.0f)}, /* 0x46 */ - {FP_SCALE( 3.0f), FP_SCALE( 8.0f)}, /* 0x47 */ - {FP_SCALE( 8.0f), FP_SCALE( 1.0f)}, /* 0x48 */ - {FP_SCALE(-7.0f), FP_SCALE(-2.0f)}, /* 0x49 */ - {FP_SCALE(-2.0f), FP_SCALE( 7.0f)}, /* 0x4A */ - {FP_SCALE( 1.0f), FP_SCALE(-8.0f)}, /* 0x4B */ - {FP_SCALE(-8.0f), FP_SCALE(-1.0f)}, /* 0x4C */ - {FP_SCALE( 7.0f), FP_SCALE( 2.0f)}, /* 0x4D */ - {FP_SCALE( 2.0f), FP_SCALE(-7.0f)}, /* 0x4E */ - {FP_SCALE(-1.0f), FP_SCALE( 8.0f)}, /* 0x4F */ - {FP_SCALE(-4.0f), FP_SCALE(-7.0f)}, /* 0x50 */ - {FP_SCALE( 5.0f), FP_SCALE( 6.0f)}, /* 0x51 */ - {FP_SCALE( 6.0f), FP_SCALE(-5.0f)}, /* 0x52 */ - {FP_SCALE(-7.0f), FP_SCALE( 4.0f)}, /* 0x53 */ - {FP_SCALE( 4.0f), FP_SCALE( 7.0f)}, /* 0x54 */ - {FP_SCALE(-5.0f), FP_SCALE(-6.0f)}, /* 0x55 */ - {FP_SCALE(-6.0f), FP_SCALE( 5.0f)}, /* 0x56 */ - {FP_SCALE( 7.0f), FP_SCALE(-4.0f)}, /* 0x57 */ - {FP_SCALE(-4.0f), FP_SCALE( 5.0f)}, /* 0x58 */ - {FP_SCALE( 5.0f), FP_SCALE(-6.0f)}, /* 0x59 */ - {FP_SCALE(-6.0f), FP_SCALE(-5.0f)}, /* 0x5A */ - {FP_SCALE( 5.0f), FP_SCALE( 4.0f)}, /* 0x5B */ - {FP_SCALE( 4.0f), FP_SCALE(-5.0f)}, /* 0x5C */ - {FP_SCALE(-5.0f), FP_SCALE( 6.0f)}, /* 0x5D */ - {FP_SCALE( 6.0f), FP_SCALE( 5.0f)}, /* 0x5E */ - {FP_SCALE(-5.0f), FP_SCALE(-4.0f)}, /* 0x5F */ - {FP_SCALE( 4.0f), FP_SCALE(-7.0f)}, /* 0x60 */ - {FP_SCALE(-3.0f), FP_SCALE( 6.0f)}, /* 0x61 */ - {FP_SCALE( 6.0f), FP_SCALE( 3.0f)}, /* 0x62 */ - {FP_SCALE(-7.0f), FP_SCALE(-4.0f)}, /* 0x63 */ - {FP_SCALE(-4.0f), FP_SCALE( 7.0f)}, /* 0x64 */ - {FP_SCALE( 3.0f), FP_SCALE(-6.0f)}, /* 0x65 */ - {FP_SCALE(-6.0f), FP_SCALE(-3.0f)}, /* 0x66 */ - {FP_SCALE( 7.0f), FP_SCALE( 4.0f)}, /* 0x67 */ - {FP_SCALE( 4.0f), FP_SCALE( 5.0f)}, /* 0x68 */ - {FP_SCALE(-3.0f), FP_SCALE(-6.0f)}, /* 0x69 */ - {FP_SCALE(-6.0f), FP_SCALE( 3.0f)}, /* 0x6A */ - {FP_SCALE( 5.0f), FP_SCALE(-4.0f)}, /* 0x6B */ - {FP_SCALE(-4.0f), FP_SCALE(-5.0f)}, /* 0x6C */ - {FP_SCALE( 3.0f), FP_SCALE( 6.0f)}, /* 0x6D */ - {FP_SCALE( 6.0f), FP_SCALE(-3.0f)}, /* 0x6E */ - {FP_SCALE(-5.0f), FP_SCALE( 4.0f)}, /* 0x6F */ - {FP_SCALE( 0.0f), FP_SCALE(-7.0f)}, /* 0x70 */ - {FP_SCALE( 1.0f), FP_SCALE( 6.0f)}, /* 0x71 */ - {FP_SCALE( 6.0f), FP_SCALE(-1.0f)}, /* 0x72 */ - {FP_SCALE(-7.0f), FP_SCALE( 0.0f)}, /* 0x73 */ - {FP_SCALE( 0.0f), FP_SCALE( 7.0f)}, /* 0x74 */ - {FP_SCALE(-1.0f), FP_SCALE(-6.0f)}, /* 0x75 */ - {FP_SCALE(-6.0f), FP_SCALE( 1.0f)}, /* 0x76 */ - {FP_SCALE( 7.0f), FP_SCALE( 0.0f)}, /* 0x77 */ - {FP_SCALE( 0.0f), FP_SCALE( 5.0f)}, /* 0x78 */ - {FP_SCALE( 1.0f), FP_SCALE(-6.0f)}, /* 0x79 */ - {FP_SCALE(-6.0f), FP_SCALE(-1.0f)}, /* 0x7A */ - {FP_SCALE( 5.0f), FP_SCALE( 0.0f)}, /* 0x7B */ - {FP_SCALE( 0.0f), FP_SCALE(-5.0f)}, /* 0x7C */ - {FP_SCALE(-1.0f), FP_SCALE( 6.0f)}, /* 0x7D */ - {FP_SCALE( 6.0f), FP_SCALE( 1.0f)}, /* 0x7E */ - {FP_SCALE(-5.0f), FP_SCALE( 0.0f)} /* 0x7F */ + {FP_CONSTELLATION_SCALE(-8.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x00 */ + {FP_CONSTELLATION_SCALE( 9.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x01 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-9.0f)}, /* 0x02 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 8.0f)}, /* 0x03 */ + {FP_CONSTELLATION_SCALE( 8.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x04 */ + {FP_CONSTELLATION_SCALE(-9.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x05 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 9.0f)}, /* 0x06 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-8.0f)}, /* 0x07 */ + {FP_CONSTELLATION_SCALE(-8.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x08 */ + {FP_CONSTELLATION_SCALE( 9.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x09 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-9.0f)}, /* 0x0A */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 8.0f)}, /* 0x0B */ + {FP_CONSTELLATION_SCALE( 8.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x0C */ + {FP_CONSTELLATION_SCALE(-9.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x0D */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 9.0f)}, /* 0x0E */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-8.0f)}, /* 0x0F */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x10 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x11 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x12 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x13 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x14 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x15 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x16 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x17 */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x18 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x19 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x1A */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x1B */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x1C */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x1D */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x1E */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x1F */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x20 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x21 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x22 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x23 */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x24 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x25 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x26 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x27 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x28 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x29 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x2A */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x2B */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x2C */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x2D */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x2E */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x2F */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x30 */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x31 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x32 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x33 */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x34 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x35 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x36 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x37 */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x38 */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x39 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x3A */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x3B */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x3C */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x3D */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x3E */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x3F */ + {FP_CONSTELLATION_SCALE( 8.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x40 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x41 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x42 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-8.0f)}, /* 0x43 */ + {FP_CONSTELLATION_SCALE(-8.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x44 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x45 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x46 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 8.0f)}, /* 0x47 */ + {FP_CONSTELLATION_SCALE( 8.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x48 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x49 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x4A */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-8.0f)}, /* 0x4B */ + {FP_CONSTELLATION_SCALE(-8.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x4C */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x4D */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x4E */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 8.0f)}, /* 0x4F */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x50 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x51 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x52 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x53 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x54 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x55 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x56 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x57 */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x58 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x59 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x5A */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x5B */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x5C */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x5D */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x5E */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x5F */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x60 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x61 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x62 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x63 */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x64 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x65 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x66 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x67 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x68 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x69 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x6A */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x6B */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x6C */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x6D */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x6E */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x6F */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x70 */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x71 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x72 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x73 */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x74 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x75 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x76 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x77 */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x78 */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x79 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x7A */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x7B */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x7C */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x7D */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x7E */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 0.0f)} /* 0x7F */ }; #if defined(SPANDSP_USE_FIXED_POINTx) @@ -167,70 +166,70 @@ static const complexi16_t v17_v32bis_12000_constellation[64] = static const complexf_t v17_v32bis_12000_constellation[64] = #endif { - {FP_SCALE( 7.0f), FP_SCALE( 1.0f)}, /* 0x00 */ - {FP_SCALE(-5.0f), FP_SCALE(-1.0f)}, /* 0x01 */ - {FP_SCALE(-1.0f), FP_SCALE( 5.0f)}, /* 0x02 */ - {FP_SCALE( 1.0f), FP_SCALE(-7.0f)}, /* 0x03 */ - {FP_SCALE(-7.0f), FP_SCALE(-1.0f)}, /* 0x04 */ - {FP_SCALE( 5.0f), FP_SCALE( 1.0f)}, /* 0x05 */ - {FP_SCALE( 1.0f), FP_SCALE(-5.0f)}, /* 0x06 */ - {FP_SCALE(-1.0f), FP_SCALE( 7.0f)}, /* 0x07 */ - {FP_SCALE( 3.0f), FP_SCALE(-3.0f)}, /* 0x08 */ - {FP_SCALE(-1.0f), FP_SCALE( 3.0f)}, /* 0x09 */ - {FP_SCALE( 3.0f), FP_SCALE( 1.0f)}, /* 0x0A */ - {FP_SCALE(-3.0f), FP_SCALE(-3.0f)}, /* 0x0B */ - {FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 0x0C */ - {FP_SCALE( 1.0f), FP_SCALE(-3.0f)}, /* 0x0D */ - {FP_SCALE(-3.0f), FP_SCALE(-1.0f)}, /* 0x0E */ - {FP_SCALE( 3.0f), FP_SCALE( 3.0f)}, /* 0x0F */ - {FP_SCALE( 7.0f), FP_SCALE(-7.0f)}, /* 0x10 */ - {FP_SCALE(-5.0f), FP_SCALE( 7.0f)}, /* 0x11 */ - {FP_SCALE( 7.0f), FP_SCALE( 5.0f)}, /* 0x12 */ - {FP_SCALE(-7.0f), FP_SCALE(-7.0f)}, /* 0x13 */ - {FP_SCALE(-7.0f), FP_SCALE( 7.0f)}, /* 0x14 */ - {FP_SCALE( 5.0f), FP_SCALE(-7.0f)}, /* 0x15 */ - {FP_SCALE(-7.0f), FP_SCALE(-5.0f)}, /* 0x16 */ - {FP_SCALE( 7.0f), FP_SCALE( 7.0f)}, /* 0x17 */ - {FP_SCALE(-1.0f), FP_SCALE(-7.0f)}, /* 0x18 */ - {FP_SCALE( 3.0f), FP_SCALE( 7.0f)}, /* 0x19 */ - {FP_SCALE( 7.0f), FP_SCALE(-3.0f)}, /* 0x1A */ - {FP_SCALE(-7.0f), FP_SCALE( 1.0f)}, /* 0x1B */ - {FP_SCALE( 1.0f), FP_SCALE( 7.0f)}, /* 0x1C */ - {FP_SCALE(-3.0f), FP_SCALE(-7.0f)}, /* 0x1D */ - {FP_SCALE(-7.0f), FP_SCALE( 3.0f)}, /* 0x1E */ - {FP_SCALE( 7.0f), FP_SCALE(-1.0f)}, /* 0x1F */ - {FP_SCALE( 3.0f), FP_SCALE( 5.0f)}, /* 0x20 */ - {FP_SCALE(-1.0f), FP_SCALE(-5.0f)}, /* 0x21 */ - {FP_SCALE(-5.0f), FP_SCALE( 1.0f)}, /* 0x22 */ - {FP_SCALE( 5.0f), FP_SCALE(-3.0f)}, /* 0x23 */ - {FP_SCALE(-3.0f), FP_SCALE(-5.0f)}, /* 0x24 */ - {FP_SCALE( 1.0f), FP_SCALE( 5.0f)}, /* 0x25 */ - {FP_SCALE( 5.0f), FP_SCALE(-1.0f)}, /* 0x26 */ - {FP_SCALE(-5.0f), FP_SCALE( 3.0f)}, /* 0x27 */ - {FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 0x28 */ - {FP_SCALE( 3.0f), FP_SCALE(-1.0f)}, /* 0x29 */ - {FP_SCALE(-1.0f), FP_SCALE(-3.0f)}, /* 0x2A */ - {FP_SCALE( 1.0f), FP_SCALE( 1.0f)}, /* 0x2B */ - {FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 0x2C */ - {FP_SCALE(-3.0f), FP_SCALE( 1.0f)}, /* 0x2D */ - {FP_SCALE( 1.0f), FP_SCALE( 3.0f)}, /* 0x2E */ - {FP_SCALE(-1.0f), FP_SCALE(-1.0f)}, /* 0x2F */ - {FP_SCALE(-5.0f), FP_SCALE( 5.0f)}, /* 0x30 */ - {FP_SCALE( 7.0f), FP_SCALE(-5.0f)}, /* 0x31 */ - {FP_SCALE(-5.0f), FP_SCALE(-7.0f)}, /* 0x32 */ - {FP_SCALE( 5.0f), FP_SCALE( 5.0f)}, /* 0x33 */ - {FP_SCALE( 5.0f), FP_SCALE(-5.0f)}, /* 0x34 */ - {FP_SCALE(-7.0f), FP_SCALE( 5.0f)}, /* 0x35 */ - {FP_SCALE( 5.0f), FP_SCALE( 7.0f)}, /* 0x36 */ - {FP_SCALE(-5.0f), FP_SCALE(-5.0f)}, /* 0x37 */ - {FP_SCALE(-5.0f), FP_SCALE(-3.0f)}, /* 0x38 */ - {FP_SCALE( 7.0f), FP_SCALE( 3.0f)}, /* 0x39 */ - {FP_SCALE( 3.0f), FP_SCALE(-7.0f)}, /* 0x3A */ - {FP_SCALE(-3.0f), FP_SCALE( 5.0f)}, /* 0x3B */ - {FP_SCALE( 5.0f), FP_SCALE( 3.0f)}, /* 0x3C */ - {FP_SCALE(-7.0f), FP_SCALE(-3.0f)}, /* 0x3D */ - {FP_SCALE(-3.0f), FP_SCALE( 7.0f)}, /* 0x3E */ - {FP_SCALE( 3.0f), FP_SCALE(-5.0f)} /* 0x3F */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x00 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x01 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x02 */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x03 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x04 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x05 */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x06 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x07 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x08 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x09 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x0A */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x0B */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x0C */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x0D */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x0E */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x0F */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x10 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x11 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x12 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x13 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x14 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x15 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x16 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x17 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x18 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x19 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x1A */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x1B */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x1C */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x1D */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x1E */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x1F */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x20 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x21 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x22 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x23 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x24 */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x25 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x26 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x27 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x28 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x29 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x2A */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x2B */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x2C */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 0x2D */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x2E */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 0x2F */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x30 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x31 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x32 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x33 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x34 */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x35 */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x36 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 0x37 */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x38 */ + {FP_CONSTELLATION_SCALE( 7.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x39 */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-7.0f)}, /* 0x3A */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 0x3B */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 0x3C */ + {FP_CONSTELLATION_SCALE(-7.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 0x3D */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 7.0f)}, /* 0x3E */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-5.0f)} /* 0x3F */ }; #if defined(SPANDSP_USE_FIXED_POINTx) @@ -239,38 +238,38 @@ static const complexi16_t v17_v32bis_9600_constellation[32] = static const complexf_t v17_v32bis_9600_constellation[32] = #endif { - {FP_SCALE(-8.0f), FP_SCALE( 2.0f)}, /* 0x00 */ - {FP_SCALE(-6.0f), FP_SCALE(-4.0f)}, /* 0x01 */ - {FP_SCALE(-4.0f), FP_SCALE( 6.0f)}, /* 0x02 */ - {FP_SCALE( 2.0f), FP_SCALE( 8.0f)}, /* 0x03 */ - {FP_SCALE( 8.0f), FP_SCALE(-2.0f)}, /* 0x04 */ - {FP_SCALE( 6.0f), FP_SCALE( 4.0f)}, /* 0x05 */ - {FP_SCALE( 4.0f), FP_SCALE(-6.0f)}, /* 0x06 */ - {FP_SCALE(-2.0f), FP_SCALE(-8.0f)}, /* 0x07 */ - {FP_SCALE( 0.0f), FP_SCALE( 2.0f)}, /* 0x08 */ - {FP_SCALE(-6.0f), FP_SCALE( 4.0f)}, /* 0x09 */ - {FP_SCALE( 4.0f), FP_SCALE( 6.0f)}, /* 0x0A */ - {FP_SCALE( 2.0f), FP_SCALE( 0.0f)}, /* 0x0B */ - {FP_SCALE( 0.0f), FP_SCALE(-2.0f)}, /* 0x0C */ - {FP_SCALE( 6.0f), FP_SCALE(-4.0f)}, /* 0x0D */ - {FP_SCALE(-4.0f), FP_SCALE(-6.0f)}, /* 0x0E */ - {FP_SCALE(-2.0f), FP_SCALE( 0.0f)}, /* 0x0F */ - {FP_SCALE( 0.0f), FP_SCALE(-6.0f)}, /* 0x10 */ - {FP_SCALE( 2.0f), FP_SCALE(-4.0f)}, /* 0x11 */ - {FP_SCALE(-4.0f), FP_SCALE(-2.0f)}, /* 0x12 */ - {FP_SCALE(-6.0f), FP_SCALE( 0.0f)}, /* 0x13 */ - {FP_SCALE( 0.0f), FP_SCALE( 6.0f)}, /* 0x14 */ - {FP_SCALE(-2.0f), FP_SCALE( 4.0f)}, /* 0x15 */ - {FP_SCALE( 4.0f), FP_SCALE( 2.0f)}, /* 0x16 */ - {FP_SCALE( 6.0f), FP_SCALE( 0.0f)}, /* 0x17 */ - {FP_SCALE( 8.0f), FP_SCALE( 2.0f)}, /* 0x18 */ - {FP_SCALE( 2.0f), FP_SCALE( 4.0f)}, /* 0x19 */ - {FP_SCALE( 4.0f), FP_SCALE(-2.0f)}, /* 0x1A */ - {FP_SCALE( 2.0f), FP_SCALE(-8.0f)}, /* 0x1B */ - {FP_SCALE(-8.0f), FP_SCALE(-2.0f)}, /* 0x1C */ - {FP_SCALE(-2.0f), FP_SCALE(-4.0f)}, /* 0x1D */ - {FP_SCALE(-4.0f), FP_SCALE( 2.0f)}, /* 0x1E */ - {FP_SCALE(-2.0f), FP_SCALE( 8.0f)} /* 0x1F */ + {FP_CONSTELLATION_SCALE(-8.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x00 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x01 */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x02 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 8.0f)}, /* 0x03 */ + {FP_CONSTELLATION_SCALE( 8.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x04 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x05 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x06 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-8.0f)}, /* 0x07 */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x08 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x09 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x0A */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x0B */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x0C */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x0D */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x0E */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x0F */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x10 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x11 */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x12 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x13 */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x14 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x15 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x16 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0x17 */ + {FP_CONSTELLATION_SCALE( 8.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x18 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 4.0f)}, /* 0x19 */ + {FP_CONSTELLATION_SCALE( 4.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x1A */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-8.0f)}, /* 0x1B */ + {FP_CONSTELLATION_SCALE(-8.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x1C */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-4.0f)}, /* 0x1D */ + {FP_CONSTELLATION_SCALE(-4.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x1E */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 8.0f)} /* 0x1F */ }; #if defined(SPANDSP_USE_FIXED_POINTx) @@ -279,22 +278,22 @@ static const complexi16_t v17_v32bis_7200_constellation[16] = static const complexf_t v17_v32bis_7200_constellation[16] = #endif { - {FP_SCALE( 6.0f), FP_SCALE(-6.0f)}, /* 0x00 */ - {FP_SCALE(-2.0f), FP_SCALE( 6.0f)}, /* 0x01 */ - {FP_SCALE( 6.0f), FP_SCALE( 2.0f)}, /* 0x02 */ - {FP_SCALE(-6.0f), FP_SCALE(-6.0f)}, /* 0x03 */ - {FP_SCALE(-6.0f), FP_SCALE( 6.0f)}, /* 0x04 */ - {FP_SCALE( 2.0f), FP_SCALE(-6.0f)}, /* 0x05 */ - {FP_SCALE(-6.0f), FP_SCALE(-2.0f)}, /* 0x06 */ - {FP_SCALE( 6.0f), FP_SCALE( 6.0f)}, /* 0x07 */ - {FP_SCALE(-2.0f), FP_SCALE( 2.0f)}, /* 0x08 */ - {FP_SCALE( 6.0f), FP_SCALE(-2.0f)}, /* 0x09 */ - {FP_SCALE(-2.0f), FP_SCALE(-6.0f)}, /* 0x0A */ - {FP_SCALE( 2.0f), FP_SCALE( 2.0f)}, /* 0x0B */ - {FP_SCALE( 2.0f), FP_SCALE(-2.0f)}, /* 0x0C */ - {FP_SCALE(-6.0f), FP_SCALE( 2.0f)}, /* 0x0D */ - {FP_SCALE( 2.0f), FP_SCALE( 6.0f)}, /* 0x0E */ - {FP_SCALE(-2.0f), FP_SCALE(-2.0f)} /* 0x0F */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x00 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x01 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x02 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x03 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x04 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x05 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x06 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x07 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x08 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x09 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x0A */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x0B */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x0C */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* 0x0D */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x0E */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE(-2.0f)} /* 0x0F */ }; /* This one does not exist in V.17 as a data constellation. It is only @@ -305,10 +304,10 @@ static const complexi16_t v17_v32bis_4800_constellation[4] = static const complexf_t v17_v32bis_4800_constellation[4] = #endif { - {FP_SCALE(-6.0f), FP_SCALE(-2.0f)}, /* 0x00 */ - {FP_SCALE(-2.0f), FP_SCALE( 6.0f)}, /* 0x01 */ - {FP_SCALE( 2.0f), FP_SCALE(-6.0f)}, /* 0x02 */ - {FP_SCALE( 6.0f), FP_SCALE( 2.0f)} /* 0x03 */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* 0x00 */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 6.0f)}, /* 0x01 */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* 0x02 */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 2.0f)} /* 0x03 */ }; #if defined(SPANDSP_USE_FIXED_POINTx) @@ -317,10 +316,10 @@ static const complexi16_t v17_v32bis_abcd_constellation[4] = static const complexf_t v17_v32bis_abcd_constellation[4] = #endif { - {FP_SCALE(-6.0f), FP_SCALE(-2.0f)}, /* A */ - {FP_SCALE( 2.0f), FP_SCALE(-6.0f)}, /* B */ - {FP_SCALE( 6.0f), FP_SCALE( 2.0f)}, /* C */ - {FP_SCALE(-2.0f), FP_SCALE( 6.0f)} /* D */ + {FP_CONSTELLATION_SCALE(-6.0f), FP_CONSTELLATION_SCALE(-2.0f)}, /* A */ + {FP_CONSTELLATION_SCALE( 2.0f), FP_CONSTELLATION_SCALE(-6.0f)}, /* B */ + {FP_CONSTELLATION_SCALE( 6.0f), FP_CONSTELLATION_SCALE( 2.0f)}, /* C */ + {FP_CONSTELLATION_SCALE(-2.0f), FP_CONSTELLATION_SCALE( 6.0f)} /* D */ }; /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/v17rx.c b/libs/spandsp/src/v17rx.c index 46480ee19b..9aae8bfbf1 100644 --- a/libs/spandsp/src/v17rx.c +++ b/libs/spandsp/src/v17rx.c @@ -69,11 +69,14 @@ #define FP_SCALE(x) FP_Q_6_10(x) #define FP_FACTOR 1024 #define FP_SHIFT_FACTOR 12 -#include "v17_v32bis_rx_fixed_rrc.h" #else #define FP_SCALE(x) (x) -#include "v17_v32bis_rx_floating_rrc.h" #endif + +#include "v17_v32bis_rx_rrc.h" + +#define FP_CONSTELLATION_SCALE(x) FP_SCALE(x) + #include "v17_v32bis_tx_constellation_maps.h" #include "v17_v32bis_rx_constellation_maps.h" diff --git a/libs/spandsp/src/v17tx.c b/libs/spandsp/src/v17tx.c index 56d3fa13a0..fe361d7744 100644 --- a/libs/spandsp/src/v17tx.c +++ b/libs/spandsp/src/v17tx.c @@ -63,44 +63,42 @@ #include "spandsp/private/v17tx.h" #if defined(SPANDSP_USE_FIXED_POINT) -#define FP_SCALE(x) ((int16_t) x) +#define FP_SCALE(x) ((int16_t) x) #else -#define FP_SCALE(x) (x) +#define FP_SCALE(x) (x) #endif +#define FP_CONSTELLATION_SCALE(x) FP_SCALE(x) + #include "v17_v32bis_tx_constellation_maps.h" -#if defined(SPANDSP_USE_FIXED_POINT) -#include "v17_v32bis_tx_fixed_rrc.h" -#else -#include "v17_v32bis_tx_floating_rrc.h" -#endif +#include "v17_v32bis_tx_rrc.h" /*! The nominal frequency of the carrier, in Hertz */ -#define CARRIER_NOMINAL_FREQ 1800.0f +#define CARRIER_NOMINAL_FREQ 1800.0f /* Segments of the training sequence */ /*! The start of the optional TEP, that may preceed the actual training, in symbols */ -#define V17_TRAINING_SEG_TEP_A 0 +#define V17_TRAINING_SEG_TEP_A 0 /*! The mid point of the optional TEP, that may preceed the actual training, in symbols */ -#define V17_TRAINING_SEG_TEP_B (V17_TRAINING_SEG_TEP_A + 480) +#define V17_TRAINING_SEG_TEP_B (V17_TRAINING_SEG_TEP_A + 480) /*! The start of training segment 1, in symbols */ -#define V17_TRAINING_SEG_1 (V17_TRAINING_SEG_TEP_B + 48) +#define V17_TRAINING_SEG_1 (V17_TRAINING_SEG_TEP_B + 48) /*! The start of training segment 2, in symbols */ -#define V17_TRAINING_SEG_2 (V17_TRAINING_SEG_1 + 256) +#define V17_TRAINING_SEG_2 (V17_TRAINING_SEG_1 + 256) /*! The start of training segment 3, in symbols */ -#define V17_TRAINING_SEG_3 (V17_TRAINING_SEG_2 + 2976) +#define V17_TRAINING_SEG_3 (V17_TRAINING_SEG_2 + 2976) /*! The start of training segment 4, in symbols */ -#define V17_TRAINING_SEG_4 (V17_TRAINING_SEG_3 + 64) +#define V17_TRAINING_SEG_4 (V17_TRAINING_SEG_3 + 64) /*! The start of training segment 4 in short training mode, in symbols */ -#define V17_TRAINING_SHORT_SEG_4 (V17_TRAINING_SEG_2 + 38) +#define V17_TRAINING_SHORT_SEG_4 (V17_TRAINING_SEG_2 + 38) /*! The end of the training, in symbols */ -#define V17_TRAINING_END (V17_TRAINING_SEG_4 + 48) -#define V17_TRAINING_SHUTDOWN_A (V17_TRAINING_END + 32) +#define V17_TRAINING_END (V17_TRAINING_SEG_4 + 48) +#define V17_TRAINING_SHUTDOWN_A (V17_TRAINING_END + 32) /*! The end of the shutdown sequence, in symbols */ -#define V17_TRAINING_SHUTDOWN_END (V17_TRAINING_SHUTDOWN_A + 48) +#define V17_TRAINING_SHUTDOWN_END (V17_TRAINING_SHUTDOWN_A + 48) /*! The 16 bit pattern used in the bridge section of the training sequence */ -#define V17_BRIDGE_WORD 0x8880 +#define V17_BRIDGE_WORD 0x8880 static __inline__ int scramble(v17_tx_state_t *s, int in_bit) { diff --git a/libs/spandsp/src/v22bis_rx.c b/libs/spandsp/src/v22bis_rx.c index c4898cf1cd..c00c62b47c 100644 --- a/libs/spandsp/src/v22bis_rx.c +++ b/libs/spandsp/src/v22bis_rx.c @@ -75,14 +75,13 @@ #if defined(SPANDSP_USE_FIXED_POINT) #define FP_SHIFT_FACTOR 10 #define FP_SCALE FP_Q_6_10 -#include "v22bis_rx_1200_fixed_rrc.h" -#include "v22bis_rx_2400_fixed_rrc.h" #else #define FP_SCALE(x) (x) -#include "v22bis_rx_1200_floating_rrc.h" -#include "v22bis_rx_2400_floating_rrc.h" #endif +#include "v22bis_rx_1200_rrc.h" +#include "v22bis_rx_2400_rrc.h" + #define ms_to_symbols(t) (((t)*600)/1000) /*! The adaption rate coefficient for the equalizer */ diff --git a/libs/spandsp/src/v22bis_tx.c b/libs/spandsp/src/v22bis_tx.c index 8b5068803e..0c43b95a07 100644 --- a/libs/spandsp/src/v22bis_tx.c +++ b/libs/spandsp/src/v22bis_tx.c @@ -64,12 +64,12 @@ #if defined(SPANDSP_USE_FIXED_POINT) #define FP_SCALE FP_Q_6_10 -#include "v22bis_tx_fixed_rrc.h" #else #define FP_SCALE(x) (x) -#include "v22bis_tx_floating_rrc.h" #endif +#include "v22bis_tx_rrc.h" + /* Quoting from the V.22bis spec. 6.3.1.1 Interworking at 2400 bit/s diff --git a/libs/spandsp/src/v27ter_rx.c b/libs/spandsp/src/v27ter_rx.c index ce0537b560..7e1fb9929b 100644 --- a/libs/spandsp/src/v27ter_rx.c +++ b/libs/spandsp/src/v27ter_rx.c @@ -68,14 +68,13 @@ #define FP_SCALE FP_Q_6_10 #define FP_FACTOR 4096 #define FP_SHIFT_FACTOR 12 -#include "v27ter_rx_4800_fixed_rrc.h" -#include "v27ter_rx_2400_fixed_rrc.h" #else #define FP_SCALE(x) (x) -#include "v27ter_rx_4800_floating_rrc.h" -#include "v27ter_rx_2400_floating_rrc.h" #endif +#include "v27ter_rx_4800_rrc.h" +#include "v27ter_rx_2400_rrc.h" + /* V.27ter is a DPSK modem, but this code treats it like QAM. It nails down the signal to a static constellation, even though dealing with differences is all that is necessary. */ @@ -272,6 +271,34 @@ static void tune_equalizer(v27ter_rx_state_t *s, const complexf_t *z, const comp #endif /*- End of function --------------------------------------------------------*/ +#if defined(SPANDSP_USE_FIXED_POINT) +static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexi16_t *z, const complexi16_t *target) +#else +static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexf_t *z, const complexf_t *target) +#endif +{ +#if defined(SPANDSP_USE_FIXED_POINT) + int32_t error; +#else + float error; +#endif + + /* For small errors the imaginary part of the difference between the actual and the target + positions is proportional to the phase error, for any particular target. However, the + different amplitudes of the various target positions scale things. */ +#if defined(SPANDSP_USE_FIXED_POINT) + error = ((int32_t) z->im*target->re - (int32_t) z->re*target->im) >> 10; + s->carrier_phase_rate += ((s->carrier_track_i*error) >> FP_SHIFT_FACTOR); + s->carrier_phase += ((s->carrier_track_p*error) >> FP_SHIFT_FACTOR); +#else + error = z->im*target->re - z->re*target->im; + s->carrier_phase_rate += (int32_t) (s->carrier_track_i*error); + s->carrier_phase += (int32_t) (s->carrier_track_p*error); + //span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate)); +#endif +} +/*- End of function --------------------------------------------------------*/ + #if defined(SPANDSP_USE_FIXED_POINT) static __inline__ int find_quadrant(const complexi16_t *z) #else @@ -337,38 +364,11 @@ static __inline__ int find_octant(complexf_t *z) } /*- End of function --------------------------------------------------------*/ -#if defined(SPANDSP_USE_FIXED_POINT) -static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexi16_t *z, const complexi16_t *target) -#else -static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexf_t *z, const complexf_t *target) -#endif -{ -#if defined(SPANDSP_USE_FIXED_POINT) - int32_t error; -#else - float error; -#endif - - /* For small errors the imaginary part of the difference between the actual and the target - positions is proportional to the phase error, for any particular target. However, the - different amplitudes of the various target positions scale things. */ -#if defined(SPANDSP_USE_FIXED_POINT) - error = ((int32_t) z->im*target->re - (int32_t) z->re*target->im) >> 10; - s->carrier_phase_rate += ((s->carrier_track_i*error) >> FP_SHIFT_FACTOR); - s->carrier_phase += ((s->carrier_track_p*error) >> FP_SHIFT_FACTOR); -#else - error = z->im*target->re - z->re*target->im; - s->carrier_phase_rate += (int32_t) (s->carrier_track_i*error); - s->carrier_phase += (int32_t) (s->carrier_track_p*error); - //span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate)); -#endif -} -/*- End of function --------------------------------------------------------*/ - static __inline__ int descramble(v27ter_rx_state_t *s, int in_bit) { int out_bit; + in_bit &= 1; out_bit = (in_bit ^ (s->scramble_reg >> 5) ^ (s->scramble_reg >> 6)) & 1; if (s->scrambler_pattern_count >= 33) { diff --git a/libs/spandsp/src/v27ter_tx.c b/libs/spandsp/src/v27ter_tx.c index a877915271..f1d7ce263d 100644 --- a/libs/spandsp/src/v27ter_tx.c +++ b/libs/spandsp/src/v27ter_tx.c @@ -60,14 +60,13 @@ #if defined(SPANDSP_USE_FIXED_POINT) #define FP_SCALE FP_Q_6_10 -#include "v27ter_tx_4800_fixed_rrc.h" -#include "v27ter_tx_2400_fixed_rrc.h" #else #define FP_SCALE(x) (x) -#include "v27ter_tx_4800_floating_rrc.h" -#include "v27ter_tx_2400_floating_rrc.h" #endif +#include "v27ter_tx_4800_rrc.h" +#include "v27ter_tx_2400_rrc.h" + /*! The nominal frequency of the carrier, in Hertz */ #define CARRIER_NOMINAL_FREQ 1800.0f diff --git a/libs/spandsp/src/v29rx.c b/libs/spandsp/src/v29rx.c index 33e4d0b161..525532a392 100644 --- a/libs/spandsp/src/v29rx.c +++ b/libs/spandsp/src/v29rx.c @@ -67,14 +67,16 @@ #define FP_SCALE FP_Q_4_12 #define FP_FACTOR 4096 #define FP_SHIFT_FACTOR 12 -#include "v29tx_constellation_maps.h" -#include "v29rx_fixed_rrc.h" #else #define FP_SCALE(x) (x) -#include "v29tx_constellation_maps.h" -#include "v29rx_floating_rrc.h" #endif +#include "v29rx_rrc.h" + +#define FP_CONSTELLATION_SCALE(x) FP_SCALE(x) + +#include "v29tx_constellation_maps.h" + /*! The nominal frequency of the carrier, in Hertz */ #define CARRIER_NOMINAL_FREQ 1700.0f /*! The nominal baud or symbol rate */ @@ -104,6 +106,7 @@ enum static const uint8_t space_map_9600[20][20] = { + /* Middle V Middle */ {13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11}, {13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11}, {13, 13, 13, 13, 13, 13, 13, 4, 4, 4, 4, 4, 4, 11, 11, 11, 11, 11, 11, 11}, @@ -113,8 +116,8 @@ static const uint8_t space_map_9600[20][20] = {14, 13, 13, 13, 13, 13, 5, 5, 5, 5, 3, 3, 3, 3, 11, 11, 11, 11, 11, 10}, {14, 14, 6, 6, 6, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 2, 2, 2, 10, 10}, {14, 14, 6, 6, 6, 6, 5, 5, 5, 5, 3, 3, 3, 3, 2, 2, 2, 2, 10, 10}, - {14, 14, 6, 6, 6, 6, 5, 5, 5, 5, 3, 3, 3, 3, 2, 2, 2, 2, 10, 10}, - {14, 14, 6, 6, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 10, 10}, + {14, 14, 6, 6, 6, 6, 5, 5, 5, 5, 3, 3, 3, 3, 2, 2, 2, 2, 10, 10}, /* << Middle */ + {14, 14, 6, 6, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 10, 10}, /* << Middle */ {14, 14, 6, 6, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 10, 10}, {14, 14, 6, 6, 6, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 2, 2, 2, 10, 10}, {14, 15, 15, 15, 15, 15, 7, 7, 7, 7, 1, 1, 1, 1, 9, 9, 9, 9, 9, 10}, @@ -124,6 +127,7 @@ static const uint8_t space_map_9600[20][20] = {15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9}, {15, 15, 15, 15, 15, 15, 15, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9}, {15, 15, 15, 15, 15, 15, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9} + /* Middle ^ Middle */ }; /* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */ diff --git a/libs/spandsp/src/v29tx.c b/libs/spandsp/src/v29tx.c index 7604ae4ac1..868b9ac341 100644 --- a/libs/spandsp/src/v29tx.c +++ b/libs/spandsp/src/v29tx.c @@ -58,13 +58,18 @@ #include "spandsp/private/logging.h" #include "spandsp/private/v29tx.h" -#include "v29tx_constellation_maps.h" #if defined(SPANDSP_USE_FIXED_POINT) -#include "v29tx_fixed_rrc.h" +#define FP_SCALE(x) ((int16_t) x) #else -#include "v29tx_floating_rrc.h" +#define FP_SCALE(x) (x) #endif +#define FP_CONSTELLATION_SCALE(x) FP_SCALE(x) + +#include "v29tx_constellation_maps.h" + +#include "v29tx_rrc.h" + /*! The nominal frequency of the carrier, in Hertz */ #define CARRIER_NOMINAL_FREQ 1700.0f diff --git a/libs/spandsp/src/v29tx_constellation_maps.h b/libs/spandsp/src/v29tx_constellation_maps.h index f141b336bb..2178ad2ace 100644 --- a/libs/spandsp/src/v29tx_constellation_maps.h +++ b/libs/spandsp/src/v29tx_constellation_maps.h @@ -6,7 +6,7 @@ * * Written by Steve Underwood * - * Copyright (C) 2008 Steve Underwood + * Copyright (C) 2008, 2012 Steve Underwood * * All rights reserved. * @@ -24,26 +24,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if !defined(FP_SCALE) -#if defined(SPANDSP_USE_FIXED_POINT) -#define FP_SCALE(x) ((int16_t) x) -#else -#define FP_SCALE(x) (x) -#endif -#endif - #if defined(SPANDSP_USE_FIXED_POINT) static const complexi16_t v29_abab_constellation[6] = #else static const complexf_t v29_abab_constellation[6] = #endif { - {FP_SCALE( 3.0f), FP_SCALE(-3.0f)}, /* 315deg high 9600 */ - {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */ - {FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low 7200 */ - {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */ - {FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low 4800 */ - {FP_SCALE(-3.0f), FP_SCALE( 0.0f)} /* 180deg low */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 315deg high 9600 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 180deg low */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 315deg low 7200 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 180deg low */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 270deg low 4800 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 0.0f)} /* 180deg low */ }; #if defined(SPANDSP_USE_FIXED_POINT) @@ -52,12 +44,12 @@ static const complexi16_t v29_cdcd_constellation[6] = static const complexf_t v29_cdcd_constellation[6] = #endif { - {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 9600 */ - {FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */ - {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 7200 */ - {FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */ - {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 4800 */ - {FP_SCALE( 0.0f), FP_SCALE( 3.0f)} /* 90deg low */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0deg low 9600 */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 135deg high */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0deg low 7200 */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 135deg low */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0deg low 4800 */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 3.0f)} /* 90deg low */ }; #if defined(SPANDSP_USE_FIXED_POINT) @@ -66,22 +58,22 @@ static const complexi16_t v29_9600_constellation[16] = static const complexf_t v29_9600_constellation[16] = #endif { - {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low */ - {FP_SCALE( 1.0f), FP_SCALE( 1.0f)}, /* 45deg low */ - {FP_SCALE( 0.0f), FP_SCALE( 3.0f)}, /* 90deg low */ - {FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */ - {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */ - {FP_SCALE(-1.0f), FP_SCALE(-1.0f)}, /* 225deg low */ - {FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low */ - {FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low */ - {FP_SCALE( 5.0f), FP_SCALE( 0.0f)}, /* 0deg high */ - {FP_SCALE( 3.0f), FP_SCALE( 3.0f)}, /* 45deg high */ - {FP_SCALE( 0.0f), FP_SCALE( 5.0f)}, /* 90deg high */ - {FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */ - {FP_SCALE(-5.0f), FP_SCALE( 0.0f)}, /* 180deg high */ - {FP_SCALE(-3.0f), FP_SCALE(-3.0f)}, /* 225deg high */ - {FP_SCALE( 0.0f), FP_SCALE(-5.0f)}, /* 270deg high */ - {FP_SCALE( 3.0f), FP_SCALE(-3.0f)} /* 315deg high */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0deg low */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 45deg low */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 90deg low */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE( 1.0f)}, /* 135deg low */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 180deg low */ + {FP_CONSTELLATION_SCALE(-1.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 225deg low */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 270deg low */ + {FP_CONSTELLATION_SCALE( 1.0f), FP_CONSTELLATION_SCALE(-1.0f)}, /* 315deg low */ + {FP_CONSTELLATION_SCALE( 5.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 0deg high */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 45deg high */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE( 5.0f)}, /* 90deg high */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE( 3.0f)}, /* 135deg high */ + {FP_CONSTELLATION_SCALE(-5.0f), FP_CONSTELLATION_SCALE( 0.0f)}, /* 180deg high */ + {FP_CONSTELLATION_SCALE(-3.0f), FP_CONSTELLATION_SCALE(-3.0f)}, /* 225deg high */ + {FP_CONSTELLATION_SCALE( 0.0f), FP_CONSTELLATION_SCALE(-5.0f)}, /* 270deg high */ + {FP_CONSTELLATION_SCALE( 3.0f), FP_CONSTELLATION_SCALE(-3.0f)} /* 315deg high */ }; /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/tests/regression_tests.sh b/libs/spandsp/tests/regression_tests.sh index 224fb5fd62..31aeb5a952 100755 --- a/libs/spandsp/tests/regression_tests.sh +++ b/libs/spandsp/tests/regression_tests.sh @@ -25,6 +25,15 @@ STDERR_DEST=xyzzy2 echo Performing basic spandsp regression tests echo +./ademco_contactid_tests >$STDOUT_DEST 2>$STDERR_DEST +RETVAL=$? +if [ $RETVAL != 0 ] +then + echo ademco_contactid_tests failed! + exit $RETVAL +fi +echo ademco_contactid_tests completed OK + ./adsi_tests >$STDOUT_DEST 2>$STDERR_DEST RETVAL=$? if [ $RETVAL != 0 ] From e40ba88fbeebcc9e45a100336d93c6df80f3945d Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sat, 16 Mar 2013 15:21:38 -0500 Subject: [PATCH 043/113] fix windows build for last spandsp commit for vs2010-2012 --- .../src/msvc/make_modem_filter.2010.vcxproj | 22 +++++++++---------- .../src/msvc/make_modem_filter.2012.vcxproj | 22 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libs/spandsp/src/msvc/make_modem_filter.2010.vcxproj b/libs/spandsp/src/msvc/make_modem_filter.2010.vcxproj index f06c64692f..84543d77b0 100644 --- a/libs/spandsp/src/msvc/make_modem_filter.2010.vcxproj +++ b/libs/spandsp/src/msvc/make_modem_filter.2010.vcxproj @@ -53,31 +53,31 @@ MachineX86 - "$(TargetPath)" -m V.17 -i -r >"$(ProjectDir)..\v17_v32bis_rx_fixed_rrc.h" + "$(TargetPath)" -m V.17 -r >"$(ProjectDir)..\v17_v32bis_rx_rrc.h" "$(TargetPath)" -m V.17 -r >"$(ProjectDir)..\v17_v32bis_rx_floating_rrc.h" -"$(TargetPath)" -m V.17 -i -t >"$(ProjectDir)..\v17_v32bis_tx_fixed_rrc.h" +"$(TargetPath)" -m V.17 -t >"$(ProjectDir)..\v17_v32bis_tx_rrc.h" "$(TargetPath)" -m V.17 -t >"$(ProjectDir)..\v17_v32bis_tx_floating_rrc.h" -"$(TargetPath)" -m V.22bis1200 -i -r >"$(ProjectDir)..\v22bis_rx_1200_fixed_rrc.h" -"$(TargetPath)" -m V.22bis2400 -i -r >"$(ProjectDir)..\v22bis_rx_2400_fixed_rrc.h" +"$(TargetPath)" -m V.22bis1200 -r >"$(ProjectDir)..\v22bis_rx_1200_rrc.h" +"$(TargetPath)" -m V.22bis2400 -r >"$(ProjectDir)..\v22bis_rx_2400_rrc.h" "$(TargetPath)" -m V.22bis1200 -r >"$(ProjectDir)..\v22bis_rx_1200_floating_rrc.h" "$(TargetPath)" -m V.22bis2400 -r >"$(ProjectDir)..\v22bis_rx_2400_floating_rrc.h" -"$(TargetPath)" -m V.22bis -i -t >"$(ProjectDir)..\v22bis_tx_fixed_rrc.h" +"$(TargetPath)" -m V.22bis -t >"$(ProjectDir)..\v22bis_tx_rrc.h" "$(TargetPath)" -m V.22bis -t >"$(ProjectDir)..\v22bis_tx_floating_rrc.h" -"$(TargetPath)" -m V.27ter2400 -i -r >"$(ProjectDir)..\v27ter_rx_2400_fixed_rrc.h" -"$(TargetPath)" -m V.27ter4800 -i -r >"$(ProjectDir)..\v27ter_rx_4800_fixed_rrc.h" +"$(TargetPath)" -m V.27ter2400 -r >"$(ProjectDir)..\v27ter_rx_2400_rrc.h" +"$(TargetPath)" -m V.27ter4800 -r >"$(ProjectDir)..\v27ter_rx_4800_rrc.h" "$(TargetPath)" -m V.27ter2400 -r >"$(ProjectDir)..\v27ter_rx_2400_floating_rrc.h" "$(TargetPath)" -m V.27ter4800 -r >"$(ProjectDir)..\v27ter_rx_4800_floating_rrc.h" -"$(TargetPath)" -m V.27ter2400 -i -t >"$(ProjectDir)..\v27ter_tx_2400_fixed_rrc.h" -"$(TargetPath)" -m V.27ter4800 -i -t >"$(ProjectDir)..\v27ter_tx_4800_fixed_rrc.h" +"$(TargetPath)" -m V.27ter2400 -t >"$(ProjectDir)..\v27ter_tx_2400_rrc.h" +"$(TargetPath)" -m V.27ter4800 -t >"$(ProjectDir)..\v27ter_tx_4800_rrc.h" "$(TargetPath)" -m V.27ter2400 -t >"$(ProjectDir)..\v27ter_tx_2400_floating_rrc.h" "$(TargetPath)" -m V.27ter4800 -t >"$(ProjectDir)..\v27ter_tx_4800_floating_rrc.h" -"$(TargetPath)" -m V.29 -i -r >"$(ProjectDir)..\v29rx_fixed_rrc.h" +"$(TargetPath)" -m V.29 -r >"$(ProjectDir)..\v29rx_rrc.h" "$(TargetPath)" -m V.29 -r >"$(ProjectDir)..\v29rx_floating_rrc.h" -"$(TargetPath)" -m V.29 -i -t >"$(ProjectDir)..\v29tx_fixed_rrc.h" +"$(TargetPath)" -m V.29 -t >"$(ProjectDir)..\v29tx_rrc.h" "$(TargetPath)" -m V.29 -t >"$(ProjectDir)..\v29tx_floating_rrc.h" diff --git a/libs/spandsp/src/msvc/make_modem_filter.2012.vcxproj b/libs/spandsp/src/msvc/make_modem_filter.2012.vcxproj index f4e6017866..1218f8183d 100644 --- a/libs/spandsp/src/msvc/make_modem_filter.2012.vcxproj +++ b/libs/spandsp/src/msvc/make_modem_filter.2012.vcxproj @@ -54,31 +54,31 @@ MachineX86 - "$(TargetPath)" -m V.17 -i -r >"$(ProjectDir)..\v17_v32bis_rx_fixed_rrc.h" + "$(TargetPath)" -m V.17 -r >"$(ProjectDir)..\v17_v32bis_rx_rrc.h" "$(TargetPath)" -m V.17 -r >"$(ProjectDir)..\v17_v32bis_rx_floating_rrc.h" -"$(TargetPath)" -m V.17 -i -t >"$(ProjectDir)..\v17_v32bis_tx_fixed_rrc.h" +"$(TargetPath)" -m V.17 -t >"$(ProjectDir)..\v17_v32bis_tx_rrc.h" "$(TargetPath)" -m V.17 -t >"$(ProjectDir)..\v17_v32bis_tx_floating_rrc.h" -"$(TargetPath)" -m V.22bis1200 -i -r >"$(ProjectDir)..\v22bis_rx_1200_fixed_rrc.h" -"$(TargetPath)" -m V.22bis2400 -i -r >"$(ProjectDir)..\v22bis_rx_2400_fixed_rrc.h" +"$(TargetPath)" -m V.22bis1200 -r >"$(ProjectDir)..\v22bis_rx_1200_rrc.h" +"$(TargetPath)" -m V.22bis2400 -r >"$(ProjectDir)..\v22bis_rx_2400_rrc.h" "$(TargetPath)" -m V.22bis1200 -r >"$(ProjectDir)..\v22bis_rx_1200_floating_rrc.h" "$(TargetPath)" -m V.22bis2400 -r >"$(ProjectDir)..\v22bis_rx_2400_floating_rrc.h" -"$(TargetPath)" -m V.22bis -i -t >"$(ProjectDir)..\v22bis_tx_fixed_rrc.h" +"$(TargetPath)" -m V.22bis -t >"$(ProjectDir)..\v22bis_tx_rrc.h" "$(TargetPath)" -m V.22bis -t >"$(ProjectDir)..\v22bis_tx_floating_rrc.h" -"$(TargetPath)" -m V.27ter2400 -i -r >"$(ProjectDir)..\v27ter_rx_2400_fixed_rrc.h" -"$(TargetPath)" -m V.27ter4800 -i -r >"$(ProjectDir)..\v27ter_rx_4800_fixed_rrc.h" +"$(TargetPath)" -m V.27ter2400 -r >"$(ProjectDir)..\v27ter_rx_2400_rrc.h" +"$(TargetPath)" -m V.27ter4800 -r >"$(ProjectDir)..\v27ter_rx_4800_rrc.h" "$(TargetPath)" -m V.27ter2400 -r >"$(ProjectDir)..\v27ter_rx_2400_floating_rrc.h" "$(TargetPath)" -m V.27ter4800 -r >"$(ProjectDir)..\v27ter_rx_4800_floating_rrc.h" -"$(TargetPath)" -m V.27ter2400 -i -t >"$(ProjectDir)..\v27ter_tx_2400_fixed_rrc.h" -"$(TargetPath)" -m V.27ter4800 -i -t >"$(ProjectDir)..\v27ter_tx_4800_fixed_rrc.h" +"$(TargetPath)" -m V.27ter2400 -t >"$(ProjectDir)..\v27ter_tx_2400_rrc.h" +"$(TargetPath)" -m V.27ter4800 -t >"$(ProjectDir)..\v27ter_tx_4800_rrc.h" "$(TargetPath)" -m V.27ter2400 -t >"$(ProjectDir)..\v27ter_tx_2400_floating_rrc.h" "$(TargetPath)" -m V.27ter4800 -t >"$(ProjectDir)..\v27ter_tx_4800_floating_rrc.h" -"$(TargetPath)" -m V.29 -i -r >"$(ProjectDir)..\v29rx_fixed_rrc.h" +"$(TargetPath)" -m V.29 -r >"$(ProjectDir)..\v29rx_rrc.h" "$(TargetPath)" -m V.29 -r >"$(ProjectDir)..\v29rx_floating_rrc.h" -"$(TargetPath)" -m V.29 -i -t >"$(ProjectDir)..\v29tx_fixed_rrc.h" +"$(TargetPath)" -m V.29 -t >"$(ProjectDir)..\v29tx_rrc.h" "$(TargetPath)" -m V.29 -t >"$(ProjectDir)..\v29tx_floating_rrc.h" From 6afa0fd5429781b5c754c677ced9bc401408ff09 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Sat, 16 Mar 2013 22:14:02 +0100 Subject: [PATCH 044/113] FS-5148: noise at beginning of call, probably from uncleaned buffer --- src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index 1474f77908..bae1906fe3 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -509,6 +509,8 @@ static switch_status_t channel_on_init(switch_core_session_t *session) tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); + memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); + channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); //ERRORA("%s CHANNEL INIT\n", GSMOPEN_P_LOG, tech_pvt->name); @@ -559,6 +561,7 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) if (tech_pvt->phone_callflow == CALLFLOW_STATUS_FINISHED) { tech_pvt->phone_callflow = CALLFLOW_CALL_IDLE; } + memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); switch_core_session_set_private(session, NULL); } else { DEBUGA_GSMOPEN("!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(session)); @@ -757,6 +760,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch if (tech_pvt->no_sound) { goto cng; } + memset(buffer2, 0, sizeof(buffer2)); samples = tech_pvt->serialPort_serial_audio->Read(buffer2, 640); if (samples >= 320) { @@ -778,6 +782,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch tech_pvt->buffer2_full = 0; samples = 320; DEBUGA_GSMOPEN("samples=%d FROM BUFFER\n", GSMOPEN_P_LOG, samples); + memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); } } @@ -793,6 +798,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch switch_mutex_unlock(tech_pvt->flag_mutex); if (samples != 320) { + memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); if (samples != 0) { DEBUGA_GSMOPEN("samples=%d, goto cng\n", GSMOPEN_P_LOG, samples); } From a4b8a73989c6c3401d85634be74428972b890202 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 17 Mar 2013 18:28:54 +0000 Subject: [PATCH 045/113] Refactor doxygen check code --- libs/libzrtp/configure.in | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/libzrtp/configure.in b/libs/libzrtp/configure.in index 963a95dd71..1de413c389 100644 --- a/libs/libzrtp/configure.in +++ b/libs/libzrtp/configure.in @@ -85,11 +85,9 @@ AC_DEFINE(INLINE,[static inline],[Define inline construction for your platform]) # Documentation # AC_CHECK_PROGS([DOXYGEN], [doxygen]) -if test -z "$DOXYGEN"; - then AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]) -fi - -if test -n "$DOXYGEN"; then +if test -z "$DOXYGEN"; then + AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]) +else AM_CONDITIONAL([HAVE_DOXYGEN], [true]) AC_CONFIG_FILES([doc/Doxyfile]) fi From 950a7b7a9a4db0c5a4aa23a48a001a45e98c095e Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 17 Mar 2013 18:32:24 +0000 Subject: [PATCH 046/113] Make sure HAVE_DOXYGEN is defined Thanks-to: --- libs/libzrtp/configure.in | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/libzrtp/configure.in b/libs/libzrtp/configure.in index 1de413c389..f908ea69a1 100644 --- a/libs/libzrtp/configure.in +++ b/libs/libzrtp/configure.in @@ -84,6 +84,7 @@ AC_DEFINE(INLINE,[static inline],[Define inline construction for your platform]) # # Documentation # +AM_CONDITIONAL([HAVE_DOXYGEN], [false]) AC_CHECK_PROGS([DOXYGEN], [doxygen]) if test -z "$DOXYGEN"; then AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]) From e9e5f00de7b694d4eb235020918109b3dd2ba172 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 17 Mar 2013 18:35:45 +0000 Subject: [PATCH 047/113] Enable automatic build support on FreeBSD Thanks-to: --- libs/libzrtp/configure.in | 1 - libs/libzrtp/include/zrtp_config.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/libzrtp/configure.in b/libs/libzrtp/configure.in index f908ea69a1..2d10359a08 100644 --- a/libs/libzrtp/configure.in +++ b/libs/libzrtp/configure.in @@ -24,7 +24,6 @@ case $target_os in ;; *freebsd2* | *freebsd* | *netbsd* | *openbsd* | *osf[12]*) echo "------- START libzrtp configuration for BSD platform ------------" - AC_DEFINE(PLATFORM,ZP_BSD,BSD platform) ;; hpux* | irix* | linuxaout* | linux* | osf* | solaris2* | sunos4*) echo "------- START libzrtp configuration for Linux platform ------------" diff --git a/libs/libzrtp/include/zrtp_config.h b/libs/libzrtp/include/zrtp_config.h index d781043fde..3f954fc836 100644 --- a/libs/libzrtp/include/zrtp_config.h +++ b/libs/libzrtp/include/zrtp_config.h @@ -19,6 +19,8 @@ #if !defined(ZRTP_PLATFORM) # if defined(ANDROID_NDK) # define ZRTP_PLATFORM ZP_ANDROID +# elif defined(__FreeBSD__) +# define ZRTP_PLATFORM ZP_BSD # elif defined(linux) || defined(__linux) # include # define ZRTP_PLATFORM ZP_LINUX From f05b493367b0f9aa884c725aa10912f5b414fa0b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 18 Mar 2013 12:41:07 -0500 Subject: [PATCH 048/113] Revert "FS-3996 --resolve stop conference recording when only 1 person left" This reverts commit 05895faa770d227953346ec3f573e724073d2cdf. --- src/mod/applications/mod_conference/mod_conference.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index c5b3049a38..7fc6311fa1 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -3932,7 +3932,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_event_fire(&event); } - while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count > 1) { + while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) { len = 0; From f45fa08e152c6d09e0d526797ec47659670886de Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Mon, 18 Mar 2013 17:58:51 -0400 Subject: [PATCH 049/113] mod_http_cache: add support for http/https formats if enable-file-formats is set to true in http_cache.conf. Don't load mod_httapi if you use this option --- .../autoload_configs/http_cache.conf.xml | 9 +- .../conf/autoload_configs/http_cache.conf.xml | 3 +- .../mod_http_cache/mod_http_cache.c | 170 ++++++++++++++++-- 3 files changed, 161 insertions(+), 21 deletions(-) diff --git a/conf/vanilla/autoload_configs/http_cache.conf.xml b/conf/vanilla/autoload_configs/http_cache.conf.xml index 4f05269658..5d0294c662 100644 --- a/conf/vanilla/autoload_configs/http_cache.conf.xml +++ b/conf/vanilla/autoload_configs/http_cache.conf.xml @@ -1,10 +1,17 @@ + + + + + + + + - diff --git a/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml b/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml index d4b5475ec9..1fe886227d 100644 --- a/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml +++ b/src/mod/applications/mod_http_cache/conf/autoload_configs/http_cache.conf.xml @@ -1,5 +1,7 @@ + + @@ -8,4 +10,3 @@ - diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c index 4bb6376393..77f93a0d25 100644 --- a/src/mod/applications/mod_http_cache/mod_http_cache.c +++ b/src/mod/applications/mod_http_cache/mod_http_cache.c @@ -168,6 +168,8 @@ struct url_cache { int ssl_verifypeer; /** Verify that hostname matches certificate */ int ssl_verifyhost; + /** True if http/https file formats should be loaded */ + int enable_file_formats; }; static url_cache_t gcache; @@ -234,7 +236,7 @@ static switch_status_t http_put(url_cache_t *cache, switch_core_session_t *sessi status = SWITCH_STATUS_FALSE; goto done; } - + curl_handle = switch_curl_easy_init(); if (!curl_handle) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_curl_easy_init() failure\n"); @@ -254,7 +256,7 @@ static switch_status_t http_put(url_cache_t *cache, switch_core_session_t *sessi if (!cache->ssl_verifypeer) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); } else { - /* this is the file with all the trusted certificate authorities */ + /* this is the file with all the trusted certificate authorities */ if (!zstr(cache->ssl_cacert)) { switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, cache->ssl_cacert); } @@ -273,7 +275,7 @@ static switch_status_t http_put(url_cache_t *cache, switch_core_session_t *sessi switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Received HTTP error %ld trying to save %s to %s\n", httpRes, filename, url); status = SWITCH_STATUS_GENERR; } - + done: if (file_to_put) { fclose(file_to_put); @@ -311,7 +313,7 @@ static size_t get_file_callback(void *ptr, size_t size, size_t nmemb, void *get) get_data->url->size += bytes_written; result = bytes_written; } - + return result; } /** @@ -340,7 +342,7 @@ static char *trim(char *str) if (zstr(str)) { return str; } - + /* strip whitespace from end */ for (i = len - 1; i >= 0; i--) { if (!isspace(str[i])) { @@ -423,7 +425,7 @@ static size_t get_header_callback(void *ptr, size_t size, size_t nmemb, void *ge switch_zmalloc(header, realsize + 1); strncpy(header, (char *)ptr, realsize); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s", header); - + /* check which header this is and process it */ if (!strncasecmp(CACHE_CONTROL_HEADER, header, CACHE_CONTROL_HEADER_LEN)) { process_cache_control_header(url, header + CACHE_CONTROL_HEADER_LEN); @@ -603,7 +605,7 @@ static switch_status_t url_cache_add(url_cache_t *cache, switch_core_session_t * * great, but is better than least recently used and is simple to implement. * * @param cache the cache - * @param session the (optional) session + * @param session the (optional) session * @return SWITCH_STATUS_SUCCESS if successful */ static switch_status_t url_cache_replace(url_cache_t *cache, switch_core_session_t *session) @@ -611,7 +613,7 @@ static switch_status_t url_cache_replace(url_cache_t *cache, switch_core_session switch_status_t status = SWITCH_STATUS_FALSE; int i = 0; simple_queue_t *queue = &cache->queue; - + if (queue->size < queue->max_size || queue->size == 0) { return SWITCH_STATUS_FALSE; } @@ -674,7 +676,7 @@ static void url_cache_remove(url_cache_t *cache, switch_core_session_t *session, if (url == to_remove) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Removing %s(%s) from cache index %d\n", url->url, url->filename, queue->pos); queue->data[queue->pos] = NULL; - queue->size--; + queue->size--; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "URL entry, %s, not in cache queue!!!\n", url->url); } @@ -703,7 +705,7 @@ static cached_url_t *cached_url_create(url_cache_t *cache, const char *url) if (zstr(url)) { return NULL; } - + switch_zmalloc(u, sizeof(cached_url_t)); /* filename is constructed from UUID and is stored in cache dir (first 2 characters of UUID) */ @@ -715,7 +717,7 @@ static cached_url_t *cached_url_create(url_cache_t *cache, const char *url) /* create sub-directory if it doesn't exist */ switch_dir_make_recursive(dirname, SWITCH_DEFAULT_DIR_PERMS, cache->pool); - + /* find extension on the end of URL */ for (ext = &url[strlen(url) - 1]; ext != url; ext--) { if (*ext == '/' || *ext == '\\') { @@ -775,7 +777,7 @@ static switch_status_t http_get(url_cache_t *cache, cached_url_t *url, switch_co /* set up HTTP GET */ get_data.fd = 0; get_data.url = url; - + curl_handle = switch_curl_easy_init(); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "opening %s for URL cache\n", get_data.url->filename); if ((get_data.fd = open(get_data.url->filename, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { @@ -786,11 +788,11 @@ static switch_status_t http_get(url_cache_t *cache, cached_url_t *url, switch_co switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &get_data); switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback); switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) url); - switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-http-cache/1.0"); + switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-http-cache/1.0"); if (!cache->ssl_verifypeer) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); } else { - /* this is the file with all the trusted certificate authorities */ + /* this is the file with all the trusted certificate authorities */ if (!zstr(cache->ssl_cacert)) { switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, cache->ssl_cacert); } @@ -820,7 +822,7 @@ static switch_status_t http_get(url_cache_t *cache, cached_url_t *url, switch_co switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Received HTTP error %ld trying to fetch %s\n", httpRes, url->url); return SWITCH_STATUS_GENERR; } - + return status; } @@ -910,7 +912,7 @@ SWITCH_STANDARD_API(http_cache_get) filename = url_cache_get(&gcache, session, cmd, 1, pool); if (filename) { stream->write_function(stream, "%s", filename); - + } else { stream->write_function(stream, "-ERR\n"); status = SWITCH_STATUS_FALSE; @@ -1082,6 +1084,7 @@ static switch_status_t do_config(url_cache_t *cache) cache->ssl_cacert = SWITCH_PREFIX_DIR "/conf/cacert.pem"; cache->ssl_verifyhost = 1; cache->ssl_verifypeer = 1; + cache->enable_file_formats = 0; /* get params */ settings = switch_xml_child(cfg, "settings"); @@ -1089,7 +1092,12 @@ static switch_status_t do_config(url_cache_t *cache) for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); - if (!strcasecmp(var, "max-urls")) { + if (!strcasecmp(var, "enable-file-formats")) { + cache->enable_file_formats = switch_true(val); + if (cache->enable_file_formats) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabling http:// and https:// formats. This is unstable if mod_httapi is also loaded\n"); + } + } else if (!strcasecmp(var, "max-urls")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting max-urls to %s\n", val); max_urls = atoi(val); } else if (!strcasecmp(var, "location")) { @@ -1123,7 +1131,7 @@ static switch_status_t do_config(url_cache_t *cache) if (max_urls <= 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-urls must be > 0\n"); status = SWITCH_STATUS_TERM; - goto done; + goto done; } if (zstr(cache->location)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "location must not be empty\n"); @@ -1154,6 +1162,114 @@ done: return status; } +/** + * HTTP file playback state + */ +struct http_context { + switch_file_handle_t fh; +}; + +/** + * Open URL + * @param handle + * @param prefix URL prefix + * @param path the URL + * @return SWITCH_STATUS_SUCCESS if opened + */ +static switch_status_t file_open(switch_file_handle_t *handle, const char *prefix, const char *path) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + struct http_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); + const char *url = switch_core_sprintf(handle->memory_pool, "%s%s", prefix, path); + const char *local_path; + + if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { + /* WRITE not supported */ + return SWITCH_STATUS_FALSE; + } + + local_path = url_cache_get(&gcache, NULL, url, 1, handle->memory_pool); + if (!local_path) { + return SWITCH_STATUS_FALSE; + } + + if ((status = switch_core_file_open(&context->fh, + local_path, + handle->channels, + handle->samplerate, + SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open HTTP cache file: %s, %s\n", local_path, url); + return status; + } + + handle->private_info = context; + handle->samples = context->fh.samples; + handle->format = context->fh.format; + handle->sections = context->fh.sections; + handle->seekable = context->fh.seekable; + handle->speed = context->fh.speed; + handle->interval = context->fh.interval; + handle->channels = context->fh.channels; + handle->flags |= SWITCH_FILE_NOMUX; + + if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) { + switch_set_flag(handle, SWITCH_FILE_NATIVE); + } else { + switch_clear_flag(handle, SWITCH_FILE_NATIVE); + } + + return status; +} + +/** + * Open HTTP URL + * @param handle + * @param path the URL + * @return SWITCH_STATUS_SUCCESS if opened + */ +static switch_status_t http_file_open(switch_file_handle_t *handle, const char *path) +{ + return file_open(handle, "http://", path); +} + +/** + * Open HTTPS URL + * @param handle + * @param path the URL + * @return SWITCH_STATUS_SUCCESS if opened + */ +static switch_status_t https_file_open(switch_file_handle_t *handle, const char *path) +{ + return file_open(handle, "https://", path); +} + +/** + * Read from HTTP file + * @param handle + * @param data + * @param len + * @return + */ +static switch_status_t http_file_read(switch_file_handle_t *handle, void *data, size_t *len) +{ + struct http_context *context = (struct http_context *)handle->private_info; + return switch_core_file_read(&context->fh, data, len); +} + +/** + * Close HTTP file + * @param handle + * @return SWITCH_STATUS_SUCCESS + */ +static switch_status_t http_file_close(switch_file_handle_t *handle) +{ + struct http_context *context = (struct http_context *)handle->private_info; + return switch_core_file_close(&context->fh); +} + +static char *http_supported_formats[] = { "http", NULL }; +static char *https_supported_formats[] = { "https", NULL }; + /** * Called when FreeSWITCH loads the module */ @@ -1169,7 +1285,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load) SWITCH_ADD_API(api, "http_put", "HTTP PUT", http_cache_put, HTTP_PUT_SYNTAX); SWITCH_ADD_API(api, "http_clear_cache", "Clear the cache", http_cache_clear, HTTP_CACHE_CLEAR_SYNTAX); SWITCH_ADD_API(api, "http_prefetch", "Prefetch document in a background thread. Use http_get to get the prefetched document", http_cache_prefetch, HTTP_PREFETCH_SYNTAX); - + memset(&gcache, 0, sizeof(url_cache_t)); gcache.pool = pool; @@ -1177,6 +1293,22 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load) return SWITCH_STATUS_TERM; } + if (gcache.enable_file_formats) { + switch_file_interface_t *file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); + file_interface->interface_name = modname; + file_interface->extens = http_supported_formats; + file_interface->file_open = http_file_open; + file_interface->file_close = http_file_close; + file_interface->file_read = http_file_read; + + file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); + file_interface->interface_name = modname; + file_interface->extens = https_supported_formats; + file_interface->file_open = https_file_open; + file_interface->file_close = http_file_close; + file_interface->file_read = http_file_read; + } + switch_core_hash_init(&gcache.map, gcache.pool); switch_mutex_init(&gcache.mutex, SWITCH_MUTEX_UNNESTED, gcache.pool); switch_thread_rwlock_create(&gcache.shutdown_lock, gcache.pool); From e7f6ea72004b487f04e410f5b8ebdf8aa9c87700 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 18 Mar 2013 16:08:46 -0500 Subject: [PATCH 050/113] FS-5197 --resolve --- src/mod/applications/mod_httapi/mod_httapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 9026333004..7c56f60517 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -2602,9 +2602,9 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char if ((!context->url_params || !switch_event_get_header(context->url_params, "ext")) && headers && (ct = switch_event_get_header(headers, "content-type"))) { if (switch_strcasecmp_any(ct, "audio/mpeg", "audio/x-mpeg", "audio/mp3", "audio/x-mp3", "audio/mpeg3", - "audio/x-mpeg3", "audio/mpg", "audio/x-mpg", "audio/x-mpegaudio")) { + "audio/x-mpeg3", "audio/mpg", "audio/x-mpg", "audio/x-mpegaudio", NULL)) { newext = "mp3"; - } else if (switch_strcasecmp_any(ct, "audio/wav", "audio/x-wave", "audio/wav")) { + } else if (switch_strcasecmp_any(ct, "audio/wav", "audio/x-wave", "audio/wav", NULL)) { newext = "wav"; } } From 2dc3b47db1401298fab98dede26defda9011add2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 18 Mar 2013 16:12:11 -0500 Subject: [PATCH 051/113] FS-5196 --resolve --- src/mod/applications/mod_httapi/mod_httapi.c | 22 ++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 7c56f60517..5c782fe090 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -2694,12 +2694,23 @@ static switch_status_t http_file_file_open(switch_file_handle_t *handle, const c { http_file_context_t *context; char *parsed = NULL, *pdup = NULL; + const char *pa = NULL; + int is_https = 0; switch_status_t status; + if (!strncmp(path, "http://", 7)) { + pa = path + 7; + } else if (!strncmp(path, "https://", 8)) { + pa = path + 8; + is_https = 1; + } else { + pa = path; + } + context = switch_core_alloc(handle->memory_pool, sizeof(*context)); context->pool = handle->memory_pool; - pdup = switch_core_strdup(context->pool, path); + pdup = switch_core_strdup(context->pool, pa); switch_event_create_brackets(pdup, '(', ')', ',', &context->url_params, &parsed, SWITCH_FALSE); @@ -2710,12 +2721,15 @@ static switch_status_t http_file_file_open(switch_file_handle_t *handle, const c if ((var = switch_event_get_header(context->url_params, "cache")) && !switch_true(var)) { context->expires = 1; } - } - if (parsed) path = parsed; + if (parsed) pa = parsed; - context->dest_url = switch_core_sprintf(context->pool, "http://%s", path); + if (is_https) { + context->dest_url = switch_core_sprintf(context->pool, "https://%s", pa); + } else { + context->dest_url = switch_core_sprintf(context->pool, "http://%s", pa); + } if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { char *ext; From a8cb98c7f98055c7d05bf500bb49f88f8e370441 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Tue, 19 Mar 2013 08:59:39 -0400 Subject: [PATCH 052/113] mod_http_cache: added http_cache file format that won't conflict with mod_httapi. --- .../mod_http_cache/mod_http_cache.c | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c index 77f93a0d25..6dbb55b1fb 100644 --- a/src/mod/applications/mod_http_cache/mod_http_cache.c +++ b/src/mod/applications/mod_http_cache/mod_http_cache.c @@ -1172,15 +1172,13 @@ struct http_context { /** * Open URL * @param handle - * @param prefix URL prefix * @param path the URL * @return SWITCH_STATUS_SUCCESS if opened */ -static switch_status_t file_open(switch_file_handle_t *handle, const char *prefix, const char *path) +static switch_status_t http_cache_file_open(switch_file_handle_t *handle, const char *path) { switch_status_t status = SWITCH_STATUS_SUCCESS; struct http_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); - const char *url = switch_core_sprintf(handle->memory_pool, "%s%s", prefix, path); const char *local_path; if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { @@ -1188,7 +1186,7 @@ static switch_status_t file_open(switch_file_handle_t *handle, const char *prefi return SWITCH_STATUS_FALSE; } - local_path = url_cache_get(&gcache, NULL, url, 1, handle->memory_pool); + local_path = url_cache_get(&gcache, NULL, path, 1, handle->memory_pool); if (!local_path) { return SWITCH_STATUS_FALSE; } @@ -1198,7 +1196,7 @@ static switch_status_t file_open(switch_file_handle_t *handle, const char *prefi handle->channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open HTTP cache file: %s, %s\n", local_path, url); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open HTTP cache file: %s, %s\n", local_path, path); return status; } @@ -1229,7 +1227,7 @@ static switch_status_t file_open(switch_file_handle_t *handle, const char *prefi */ static switch_status_t http_file_open(switch_file_handle_t *handle, const char *path) { - return file_open(handle, "http://", path); + return http_cache_file_open(handle, switch_core_sprintf(handle->memory_pool, "http://%s", path)); } /** @@ -1240,7 +1238,7 @@ static switch_status_t http_file_open(switch_file_handle_t *handle, const char * */ static switch_status_t https_file_open(switch_file_handle_t *handle, const char *path) { - return file_open(handle, "https://", path); + return http_cache_file_open(handle, switch_core_sprintf(handle->memory_pool, "https://%s", path)); } /** @@ -1269,6 +1267,7 @@ static switch_status_t http_file_close(switch_file_handle_t *handle) static char *http_supported_formats[] = { "http", NULL }; static char *https_supported_formats[] = { "https", NULL }; +static char *http_cache_supported_formats[] = { "http_cache", NULL }; /** * Called when FreeSWITCH loads the module @@ -1277,6 +1276,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load) { switch_api_interface_t *api; int i; + switch_file_interface_t *file_interface; *module_interface = switch_loadable_module_create_module_interface(pool, modname); @@ -1293,8 +1293,15 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load) return SWITCH_STATUS_TERM; } + file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); + file_interface->interface_name = modname; + file_interface->extens = http_cache_supported_formats; + file_interface->file_open = http_cache_file_open; + file_interface->file_close = http_file_close; + file_interface->file_read = http_file_read; + if (gcache.enable_file_formats) { - switch_file_interface_t *file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); + file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); file_interface->interface_name = modname; file_interface->extens = http_supported_formats; file_interface->file_open = http_file_open; From 8afe9f3c3fd3bef6d75d3c0d27384ae0aa093132 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 19 Mar 2013 08:31:52 -0500 Subject: [PATCH 053/113] FS-5196 --resolve --- src/mod/applications/mod_httapi/mod_httapi.c | 42 +++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 5c782fe090..75d896db45 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -2690,12 +2690,11 @@ static switch_status_t http_file_file_seek(switch_file_handle_t *handle, unsigne return switch_core_file_seek(&context->fh, cur_sample, samples, whence); } -static switch_status_t http_file_file_open(switch_file_handle_t *handle, const char *path) +static switch_status_t file_open(switch_file_handle_t *handle, const char *path, int is_https) { http_file_context_t *context; char *parsed = NULL, *pdup = NULL; const char *pa = NULL; - int is_https = 0; switch_status_t status; if (!strncmp(path, "http://", 7)) { @@ -2818,6 +2817,14 @@ static switch_status_t http_file_file_open(switch_file_handle_t *handle, const c return SWITCH_STATUS_SUCCESS; } +static switch_status_t http_file_file_open(switch_file_handle_t *handle, const char *path) { + return file_open(handle, path, 0); +} + +static switch_status_t https_file_file_open(switch_file_handle_t *handle, const char *path) { + return file_open(handle, path, 1); +} + static switch_status_t http_file_file_close(switch_file_handle_t *handle) { http_file_context_t *context = handle->private_info; @@ -2904,6 +2911,7 @@ static switch_status_t http_file_file_read(switch_file_handle_t *handle, void *d /* Registration */ static char *http_file_supported_formats[SWITCH_MAX_CODECS] = { 0 }; +static char *https_file_supported_formats[SWITCH_MAX_CODECS] = { 0 }; /* /HTTP FILE INTERFACE */ @@ -2912,7 +2920,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load) { switch_api_interface_t *httapi_api_interface; switch_application_interface_t *app_interface; - switch_file_interface_t *file_interface; + switch_file_interface_t *http_file_interface; + switch_file_interface_t *https_file_interface; /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); @@ -2927,14 +2936,25 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load) http_file_supported_formats[0] = "http"; - file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); - file_interface->interface_name = modname; - file_interface->extens = http_file_supported_formats; - file_interface->file_open = http_file_file_open; - file_interface->file_close = http_file_file_close; - file_interface->file_read = http_file_file_read; - file_interface->file_write = http_file_write; - file_interface->file_seek = http_file_file_seek; + http_file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); + http_file_interface->interface_name = modname; + http_file_interface->extens = http_file_supported_formats; + http_file_interface->file_open = http_file_file_open; + http_file_interface->file_close = http_file_file_close; + http_file_interface->file_read = http_file_file_read; + http_file_interface->file_write = http_file_write; + http_file_interface->file_seek = http_file_file_seek; + + https_file_supported_formats[0] = "https"; + + https_file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); + https_file_interface->interface_name = modname; + https_file_interface->extens = https_file_supported_formats; + https_file_interface->file_open = https_file_file_open; + https_file_interface->file_close = http_file_file_close; + https_file_interface->file_read = http_file_file_read; + https_file_interface->file_write = http_file_write; + https_file_interface->file_seek = http_file_file_seek; switch_snprintf(globals.cache_path, sizeof(globals.cache_path), "%s%shttp_file_cache", SWITCH_GLOBAL_dirs.storage_dir, SWITCH_PATH_SEPARATOR); switch_dir_make_recursive(globals.cache_path, SWITCH_DEFAULT_DIR_PERMS, pool); From c7fcf8c3c694d39719390f10109d625166ac7a86 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 19 Mar 2013 08:39:19 -0500 Subject: [PATCH 054/113] FS-5200 --resolve this patch did not apply please be up to date with latest HEAD when generating patches --- src/mod/applications/mod_httapi/mod_httapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 75d896db45..9a329e7cfc 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -2604,7 +2604,7 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char if (switch_strcasecmp_any(ct, "audio/mpeg", "audio/x-mpeg", "audio/mp3", "audio/x-mp3", "audio/mpeg3", "audio/x-mpeg3", "audio/mpg", "audio/x-mpg", "audio/x-mpegaudio", NULL)) { newext = "mp3"; - } else if (switch_strcasecmp_any(ct, "audio/wav", "audio/x-wave", "audio/wav", NULL)) { + } else if (switch_strcasecmp_any(ct, "audio/wav", "audio/x-wave", "audio/wav", "audio/wave", NULL)) { newext = "wav"; } } From 43b3a98b09c6092b8b5b245cbaa6b48be978c4f8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 19 Mar 2013 08:51:20 -0500 Subject: [PATCH 055/113] FS-5011 please update and retest with new logs --- src/switch_core_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 4298942eb6..f936985737 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -339,6 +339,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi if (tap_only) { need_codec = 0; + do_resample = 0; + do_bugs = 0; } From de9714d7721b185f21c53c6df41b6cb63467d332 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 19 Mar 2013 09:16:36 -0500 Subject: [PATCH 056/113] FS-5194 --resolve --- src/switch_ivr_originate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index e273e76ed6..d1e3c37649 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2372,7 +2372,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess or_argc = 1; } - for (r = 0; r < or_argc; r++) { + for (r = 0; r < or_argc && (!cancel_cause || *cancel_cause == 0); r++) { char *p, *end = NULL; int q = 0, alt = 0; From 20110f456930425e309f7f8c9367547665b58b05 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 19 Mar 2013 14:32:03 -0400 Subject: [PATCH 057/113] Freetdm - ISDN:Fix for race condition where we receive a new call, and did not finish clearing existing call internally. --- .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index c2d18f01a9..b414d4dfb1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -210,7 +210,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) } break; case FTDM_CHANNEL_STATE_TERMINATING: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in TERMINATING state, saving SETUP info for later processing\n"); + case FTDM_CHANNEL_STATE_HANGUP: + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in %s state, saving SETUP info for later processing\n", ftdm_channel_state2str(ftdmchan->state)); ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare\n"); sngisdn_set_flag(sngisdn_info, FLAG_GLARE); From 4ecba7fea86ad1ffb76fa92f8d92616e96737ac4 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 19 Mar 2013 20:54:27 -0500 Subject: [PATCH 058/113] FS-5011 please retest with this patch --- src/switch_core_io.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/switch_core_io.c b/src/switch_core_io.c index f936985737..178ae02ce3 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -271,6 +271,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi if (bp->ready) { if (!switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) { + printf("FUCKER\n\n\n"); tap_only = 0; } @@ -341,6 +342,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi need_codec = 0; do_resample = 0; do_bugs = 0; + goto done; } @@ -657,7 +659,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi } } - if (do_bugs) { + if (do_bugs || tap_only) { goto done; } @@ -985,8 +987,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess } if (session->bugs && !need_codec) { - do_bugs = TRUE; - need_codec = TRUE; + switch_media_bug_t *bp; + int tap_only = 1; + + switch_thread_rwlock_rdlock(session->bug_rwlock); + for (bp = session->bugs; bp; bp = bp->next) { + if (bp->ready) { + if (!switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) { + tap_only = 0; + break; + } + } + } + switch_thread_rwlock_unlock(session->bug_rwlock); + + if (!tap_only) { + do_bugs = TRUE; + need_codec = TRUE; + } } if (frame->codec->implementation->actual_samples_per_second != session->write_impl.actual_samples_per_second) { From d60317c153b8bc72b4e22cf3fba2f6c3d9a668a3 Mon Sep 17 00:00:00 2001 From: Raymond Chandler Date: Tue, 19 Mar 2013 22:32:40 -0400 Subject: [PATCH 059/113] FS-5091 --resolve avoid division by 0 --- src/mod/formats/mod_shout/mod_shout.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c index 6d00f7ab38..e3fda4bef9 100644 --- a/src/mod/formats/mod_shout/mod_shout.c +++ b/src/mod/formats/mod_shout/mod_shout.c @@ -208,6 +208,7 @@ static inline void free_context(shout_context_t *context) unsigned char mp3buffer[8192]; int len; int16_t blank[2048] = { 0 }, *r = NULL; + int framesize; if (context->channels == 2) { r = blank; @@ -222,13 +223,16 @@ static inline void free_context(shout_context_t *context) } } - while ((len = lame_encode_flush(context->gfp, mp3buffer, sizeof(mp3buffer))) > 0) { - ret = shout_send(context->shout, mp3buffer, len); + framesize = lame_get_framesize(context->gfp); + if ( framesize ) { + while ((len = lame_encode_flush(context->gfp, mp3buffer, sizeof(mp3buffer))) > 0) { + ret = shout_send(context->shout, mp3buffer, len); - if (ret != SHOUTERR_SUCCESS) { - break; - } else { - shout_sync(context->shout); + if (ret != SHOUTERR_SUCCESS) { + break; + } else { + shout_sync(context->shout); + } } } } From 39902893422ab4287a78344391f1016d035bea9b Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 20 Mar 2013 18:43:50 +0000 Subject: [PATCH 060/113] Build-depend on libasound2-dev for mod_portaudio Ken thinks this may have been needed to get mod_portaudio to work for him. --- debian/control-modules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control-modules b/debian/control-modules index 1787a81389..f50a76793c 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -405,6 +405,7 @@ Description: mod_opal Module: endpoints/mod_portaudio Description: mod_portaudio Adds mod_portaudio. +Build-Depends: libasound2-dev Module: endpoints/mod_reference Description: mod_reference From 09a3e63b151ea1ff2bb77d470acc86989a4b95fe Mon Sep 17 00:00:00 2001 From: Raymond Chandler Date: Wed, 20 Mar 2013 15:10:19 -0400 Subject: [PATCH 061/113] add param to not fail module load on device fail --- .../conf/autoload_configs/portaudio.conf.xml | 3 +++ src/mod/endpoints/mod_portaudio/mod_portaudio.c | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_portaudio/conf/autoload_configs/portaudio.conf.xml b/src/mod/endpoints/mod_portaudio/conf/autoload_configs/portaudio.conf.xml index 02c21ef449..1a69eeb43b 100644 --- a/src/mod/endpoints/mod_portaudio/conf/autoload_configs/portaudio.conf.xml +++ b/src/mod/endpoints/mod_portaudio/conf/autoload_configs/portaudio.conf.xml @@ -31,6 +31,9 @@ + + + + +
+ A span: + + Hello. + +
+ + ``` + + ### `parentView` setting + + The `parentView` property of the new `Ember.View` instance created through + `{{view}}` will be set to the `Ember.View` instance of the template where + `{{view}}` was called. + + ```javascript + aView = Ember.View.create({ + template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}") + }); + + aView.appendTo('body'); + ``` + + Will result in HTML structure: + + ```html +
+
+ my parent: ember1 +
+
+ ``` + + ### Setting CSS id and class attributes + + The HTML `id` attribute can be set on the `{{view}}`'s resulting element with + the `id` option. This option will _not_ be passed to `Ember.View.create`. + + ```handlebars + {{#view tagName="span" id="a-custom-id"}} + hello. + {{/view}} + ``` + + Results in the following HTML structure: + + ```html +
+ + hello. + +
+ ``` + + The HTML `class` attribute can be set on the `{{view}}`'s resulting element + with the `class` or `classNameBindings` options. The `class` option will + directly set the CSS `class` attribute and will not be passed to + `Ember.View.create`. `classNameBindings` will be passed to `create` and use + `Ember.View`'s class name binding functionality: + + ```handlebars + {{#view tagName="span" class="a-custom-class"}} + hello. + {{/view}} + ``` + + Results in the following HTML structure: + + ```html +
+ + hello. + +
+ ``` + + ### Supplying a different view class + + `{{view}}` can take an optional first argument before its supplied options to + specify a path to a custom view class. + + ```handlebars + {{#view "MyApp.CustomView"}} + hello. + {{/view}} + ``` + + The first argument can also be a relative path. Ember will search for the + view class starting at the `Ember.View` of the template where `{{view}}` was + used as the root object: + + ```javascript + MyApp = Ember.Application.create({}); + MyApp.OuterView = Ember.View.extend({ + innerViewClass: Ember.View.extend({ + classNames: ['a-custom-view-class-as-property'] + }), + template: Ember.Handlebars.compile('{{#view "innerViewClass"}} hi {{/view}}') + }); + + MyApp.OuterView.create().appendTo('body'); + ``` + + Will result in the following HTML: + + ```html +
+
+ hi +
+
+ ``` + + ### Blockless use + + If you supply a custom `Ember.View` subclass that specifies its own template + or provide a `templateName` option to `{{view}}` it can be used without + supplying a block. Attempts to use both a `templateName` option and supply a + block will throw an error. + + ```handlebars + {{view "MyApp.ViewWithATemplateDefined"}} + ``` + + ### `viewName` property + + You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance + will be referenced as a property of its parent view by this name. + + ```javascript + aView = Ember.View.create({ + template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}') + }); + + aView.appendTo('body'); + aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper + ``` + + @method view + @for Ember.Handlebars.helpers + @param {String} path + @param {Hash} options + @return {String} HTML string +*/ +EmberHandlebars.registerHelper('view', function(path, options) { + Ember.assert("The view helper only takes a single argument", arguments.length <= 2); + + // If no path is provided, treat path param as options. + if (path && path.data && path.data.isRenderData) { + options = path; + path = "Ember.View"; + } + + return EmberHandlebars.ViewHelper.helper(this, path, options); +}); + + +})(); + + + +(function() { +/*globals Handlebars */ + +// TODO: Don't require all of this module +/** +@module ember +@submodule ember-handlebars +*/ + +var get = Ember.get, handlebarsGet = Ember.Handlebars.get, fmt = Ember.String.fmt; + +/** + `{{collection}}` is a `Ember.Handlebars` helper for adding instances of + `Ember.CollectionView` to a template. See `Ember.CollectionView` for + additional information on how a `CollectionView` functions. + + `{{collection}}`'s primary use is as a block helper with a `contentBinding` + option pointing towards an `Ember.Array`-compatible object. An `Ember.View` + instance will be created for each item in its `content` property. Each view + will have its own `content` property set to the appropriate item in the + collection. + + The provided block will be applied as the template for each item's view. + + Given an empty `` the following template: + + ```handlebars + {{#collection contentBinding="App.items"}} + Hi {{view.content.name}} + {{/collection}} + ``` + + And the following application code + + ```javascript + App = Ember.Application.create() + App.items = [ + Ember.Object.create({name: 'Dave'}), + Ember.Object.create({name: 'Mary'}), + Ember.Object.create({name: 'Sara'}) + ] + ``` + + Will result in the HTML structure below + + ```html +
+
Hi Dave
+
Hi Mary
+
Hi Sara
+
+ ``` + + ### Blockless Use + + If you provide an `itemViewClass` option that has its own `template` you can + omit the block. + + The following template: + + ```handlebars + {{collection contentBinding="App.items" itemViewClass="App.AnItemView"}} + ``` + + And application code + + ```javascript + App = Ember.Application.create(); + App.items = [ + Ember.Object.create({name: 'Dave'}), + Ember.Object.create({name: 'Mary'}), + Ember.Object.create({name: 'Sara'}) + ]; + + App.AnItemView = Ember.View.extend({ + template: Ember.Handlebars.compile("Greetings {{view.content.name}}") + }); + ``` + + Will result in the HTML structure below + + ```html +
+
Greetings Dave
+
Greetings Mary
+
Greetings Sara
+
+ ``` + + ### Specifying a CollectionView subclass + + By default the `{{collection}}` helper will create an instance of + `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to + the helper by passing it as the first argument: + + ```handlebars + {{#collection App.MyCustomCollectionClass contentBinding="App.items"}} + Hi {{view.content.name}} + {{/collection}} + ``` + + ### Forwarded `item.*`-named Options + + As with the `{{view}}`, helper options passed to the `{{collection}}` will be + set on the resulting `Ember.CollectionView` as properties. Additionally, + options prefixed with `item` will be applied to the views rendered for each + item (note the camelcasing): + + ```handlebars + {{#collection contentBinding="App.items" + itemTagName="p" + itemClassNames="greeting"}} + Howdy {{view.content.name}} + {{/collection}} + ``` + + Will result in the following HTML structure: + + ```html +
+

Howdy Dave

+

Howdy Mary

+

Howdy Sara

+
+ ``` + + @method collection + @for Ember.Handlebars.helpers + @param {String} path + @param {Hash} options + @return {String} HTML string + @deprecated Use `{{each}}` helper instead. +*/ +Ember.Handlebars.registerHelper('collection', function(path, options) { + Ember.deprecate("Using the {{collection}} helper without specifying a class has been deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection'); + + // If no path is provided, treat path param as options. + if (path && path.data && path.data.isRenderData) { + options = path; + path = undefined; + Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1); + } else { + Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2); + } + + var fn = options.fn; + var data = options.data; + var inverse = options.inverse; + var view = options.data.view; + + // If passed a path string, convert that into an object. + // Otherwise, just default to the standard class. + var collectionClass; + collectionClass = path ? handlebarsGet(this, path, options) : Ember.CollectionView; + Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass); + + var hash = options.hash, itemHash = {}, match; + + // Extract item view class if provided else default to the standard class + var itemViewClass, itemViewPath = hash.itemViewClass; + var collectionPrototype = collectionClass.proto(); + delete hash.itemViewClass; + itemViewClass = itemViewPath ? handlebarsGet(collectionPrototype, itemViewPath, options) : collectionPrototype.itemViewClass; + Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewPath]), !!itemViewClass); + + // Go through options passed to the {{collection}} helper and extract options + // that configure item views instead of the collection itself. + for (var prop in hash) { + if (hash.hasOwnProperty(prop)) { + match = prop.match(/^item(.)(.*)$/); + + if(match && prop !== 'itemController') { + // Convert itemShouldFoo -> shouldFoo + itemHash[match[1].toLowerCase() + match[2]] = hash[prop]; + // Delete from hash as this will end up getting passed to the + // {{view}} helper method. + delete hash[prop]; + } + } + } + + var tagName = hash.tagName || collectionPrototype.tagName; + + if (fn) { + itemHash.template = fn; + delete options.fn; + } + + var emptyViewClass; + if (inverse && inverse !== Handlebars.VM.noop) { + emptyViewClass = get(collectionPrototype, 'emptyViewClass'); + emptyViewClass = emptyViewClass.extend({ + template: inverse, + tagName: itemHash.tagName + }); + } else if (hash.emptyViewClass) { + emptyViewClass = handlebarsGet(this, hash.emptyViewClass, options); + } + if (emptyViewClass) { hash.emptyView = emptyViewClass; } + + if(!hash.keyword){ + itemHash._context = Ember.computed.alias('content'); + } + + var viewString = view.toString(); + + var viewOptions = Ember.Handlebars.ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this); + hash.itemViewClass = itemViewClass.extend(viewOptions); + + return Ember.Handlebars.helpers.view.call(this, collectionClass, options); +}); + + +})(); + + + +(function() { +/*globals Handlebars */ +/** +@module ember +@submodule ember-handlebars +*/ + +var handlebarsGet = Ember.Handlebars.get; + +/** + `unbound` allows you to output a property without binding. *Important:* The + output will not be updated if the property changes. Use with caution. + + ```handlebars +
{{unbound somePropertyThatDoesntChange}}
+ ``` + + `unbound` can also be used in conjunction with a bound helper to + render it in its unbound form: + + ```handlebars +
{{unbound helperName somePropertyThatDoesntChange}}
+ ``` + + @method unbound + @for Ember.Handlebars.helpers + @param {String} property + @return {String} HTML string +*/ +Ember.Handlebars.registerHelper('unbound', function(property, fn) { + var options = arguments[arguments.length - 1], helper, context, out; + + if(arguments.length > 2) { + // Unbound helper call. + options.data.isUnbound = true; + helper = Ember.Handlebars.helpers[arguments[0]] || Ember.Handlebars.helperMissing; + out = helper.apply(this, Array.prototype.slice.call(arguments, 1)); + delete options.data.isUnbound; + return out; + } + + context = (fn.contexts && fn.contexts[0]) || this; + return handlebarsGet(context, property, fn); +}); + +})(); + + + +(function() { +/*jshint debug:true*/ +/** +@module ember +@submodule ember-handlebars +*/ + +var handlebarsGet = Ember.Handlebars.get, normalizePath = Ember.Handlebars.normalizePath; + +/** + `log` allows you to output the value of a value in the current rendering + context. + + ```handlebars + {{log myVariable}} + ``` + + @method log + @for Ember.Handlebars.helpers + @param {String} property +*/ +Ember.Handlebars.registerHelper('log', function(property, options) { + var context = (options.contexts && options.contexts[0]) || this, + normalized = normalizePath(context, property, options.data), + pathRoot = normalized.root, + path = normalized.path, + value = (path === 'this') ? pathRoot : handlebarsGet(pathRoot, path, options); + Ember.Logger.log(value); +}); + +/** + Execute the `debugger` statement in the current context. + + ```handlebars + {{debugger}} + ``` + + @method debugger + @for Ember.Handlebars.helpers + @param {String} property +*/ +Ember.Handlebars.registerHelper('debugger', function() { + debugger; +}); + +})(); + + + +(function() { +/** +@module ember +@submodule ember-handlebars +*/ + +var get = Ember.get, set = Ember.set; + +Ember.Handlebars.EachView = Ember.CollectionView.extend(Ember._Metamorph, { + init: function() { + var itemController = get(this, 'itemController'); + var binding; + + if (itemController) { + var controller = Ember.ArrayController.create(); + set(controller, 'itemController', itemController); + set(controller, 'container', get(this, 'controller.container')); + set(controller, '_eachView', this); + set(controller, 'target', get(this, 'controller')); + + this.disableContentObservers(function() { + set(this, 'content', controller); + binding = new Ember.Binding('content', '_eachView.dataSource').oneWay(); + binding.connect(controller); + }); + + set(this, '_arrayController', controller); + } else { + this.disableContentObservers(function() { + binding = new Ember.Binding('content', 'dataSource').oneWay(); + binding.connect(this); + }); + } + + return this._super(); + }, + + disableContentObservers: function(callback) { + Ember.removeBeforeObserver(this, 'content', null, '_contentWillChange'); + Ember.removeObserver(this, 'content', null, '_contentDidChange'); + + callback.apply(this); + + Ember.addBeforeObserver(this, 'content', null, '_contentWillChange'); + Ember.addObserver(this, 'content', null, '_contentDidChange'); + }, + + itemViewClass: Ember._MetamorphView, + emptyViewClass: Ember._MetamorphView, + + createChildView: function(view, attrs) { + view = this._super(view, attrs); + + // At the moment, if a container view subclass wants + // to insert keywords, it is responsible for cloning + // the keywords hash. This will be fixed momentarily. + var keyword = get(this, 'keyword'); + var content = get(view, 'content'); + + if (keyword) { + var data = get(view, 'templateData'); + + data = Ember.copy(data); + data.keywords = view.cloneKeywords(); + set(view, 'templateData', data); + + // In this case, we do not bind, because the `content` of + // a #each item cannot change. + data.keywords[keyword] = content; + } + + // If {{#each}} is looping over an array of controllers, + // point each child view at their respective controller. + if (content && get(content, 'isController')) { + set(view, 'controller', content); + } + + return view; + }, + + willDestroy: function() { + var arrayController = get(this, '_arrayController'); + + if (arrayController) { + arrayController.destroy(); + } + + return this._super(); + } +}); + +var GroupedEach = Ember.Handlebars.GroupedEach = function(context, path, options) { + var self = this, + normalized = Ember.Handlebars.normalizePath(context, path, options.data); + + this.context = context; + this.path = path; + this.options = options; + this.template = options.fn; + this.containingView = options.data.view; + this.normalizedRoot = normalized.root; + this.normalizedPath = normalized.path; + this.content = this.lookupContent(); + + this.addContentObservers(); + this.addArrayObservers(); + + this.containingView.on('willClearRender', function() { + self.destroy(); + }); +}; + +GroupedEach.prototype = { + contentWillChange: function() { + this.removeArrayObservers(); + }, + + contentDidChange: function() { + this.content = this.lookupContent(); + this.addArrayObservers(); + this.rerenderContainingView(); + }, + + contentArrayWillChange: Ember.K, + + contentArrayDidChange: function() { + this.rerenderContainingView(); + }, + + lookupContent: function() { + return Ember.Handlebars.get(this.normalizedRoot, this.normalizedPath, this.options); + }, + + addArrayObservers: function() { + this.content.addArrayObserver(this, { + willChange: 'contentArrayWillChange', + didChange: 'contentArrayDidChange' + }); + }, + + removeArrayObservers: function() { + this.content.removeArrayObserver(this, { + willChange: 'contentArrayWillChange', + didChange: 'contentArrayDidChange' + }); + }, + + addContentObservers: function() { + Ember.addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange); + Ember.addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange); + }, + + removeContentObservers: function() { + Ember.removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange); + Ember.removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange); + }, + + render: function() { + var content = this.content, + contentLength = get(content, 'length'), + data = this.options.data, + template = this.template; + + data.insideEach = true; + for (var i = 0; i < contentLength; i++) { + template(content.objectAt(i), { data: data }); + } + }, + + rerenderContainingView: function() { + Ember.run.scheduleOnce('render', this.containingView, 'rerender'); + }, + + destroy: function() { + this.removeContentObservers(); + this.removeArrayObservers(); + } +}; + +/** + The `{{#each}}` helper loops over elements in a collection, rendering its + block once for each item. It is an extension of the base Handlebars `{{#each}}` + helper: + + ```javascript + Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}]; + ``` + + ```handlebars + {{#each Developers}} + {{name}} + {{/each}} + ``` + + `{{each}}` supports an alternative syntax with element naming: + + ```handlebars + {{#each person in Developers}} + {{person.name}} + {{/each}} + ``` + + When looping over objects that do not have properties, `{{this}}` can be used + to render the object: + + ```javascript + DeveloperNames = ['Yehuda', 'Tom', 'Paul'] + ``` + + ```handlebars + {{#each DeveloperNames}} + {{this}} + {{/each}} + ``` + ### {{else}} condition + `{{#each}}` can have a matching `{{else}}`. The contents of this block will render + if the collection is empty. + + ``` + {{#each person in Developers}} + {{person.name}} + {{else}} +

Sorry, nobody is available for this task.

+ {{/each}} + ``` + ### Specifying a View class for items + If you provide an `itemViewClass` option that references a view class + with its own `template` you can omit the block. + + The following template: + + ```handlebars + {{#view App.MyView }} + {{each view.items itemViewClass="App.AnItemView"}} + {{/view}} + ``` + + And application code + + ```javascript + App = Ember.Application.create({ + MyView: Ember.View.extend({ + items: [ + Ember.Object.create({name: 'Dave'}), + Ember.Object.create({name: 'Mary'}), + Ember.Object.create({name: 'Sara'}) + ] + }) + }); + + App.AnItemView = Ember.View.extend({ + template: Ember.Handlebars.compile("Greetings {{name}}") + }); + ``` + + Will result in the HTML structure below + + ```html +
+
Greetings Dave
+
Greetings Mary
+
Greetings Sara
+
+ ``` + + ### Representing each item with a Controller. + By default the controller lookup within an `{{#each}}` block will be + the controller of the template where the `{{#each}}` was used. If each + item needs to be presented by a custom controller you can provide a + `itemController` option which references a controller by lookup name. + Each item in the loop will be wrapped in an instance of this controller + and the item itself will be set to the `content` property of that controller. + + This is useful in cases where properties of model objects need transformation + or synthesis for display: + + ```javascript + App.DeveloperController = Ember.ObjectController.extend({ + isAvailableForHire: function(){ + return !this.get('content.isEmployed') && this.get('content.isSeekingWork'); + }.property('isEmployed', 'isSeekingWork') + }) + ``` + + ```handlebars + {{#each person in Developers itemController="developer"}} + {{person.name}} {{#if person.isAvailableForHire}}Hire me!{{/if}} + {{/each}} + ``` + + @method each + @for Ember.Handlebars.helpers + @param [name] {String} name for item (used with `in`) + @param path {String} path + @param [options] {Object} Handlebars key/value pairs of options + @param [options.itemViewClass] {String} a path to a view class used for each item + @param [options.itemController] {String} name of a controller to be created for each item +*/ +Ember.Handlebars.registerHelper('each', function(path, options) { + if (arguments.length === 4) { + Ember.assert("If you pass more than one argument to the each helper, it must be in the form #each foo in bar", arguments[1] === "in"); + + var keywordName = arguments[0]; + + options = arguments[3]; + path = arguments[2]; + if (path === '') { path = "this"; } + + options.hash.keyword = keywordName; + } + + options.hash.dataSourceBinding = path; + // Set up emptyView as a metamorph with no tag + //options.hash.emptyViewClass = Ember._MetamorphView; + + if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) { + new Ember.Handlebars.GroupedEach(this, path, options).render(); + } else { + return Ember.Handlebars.helpers.collection.call(this, 'Ember.Handlebars.EachView', options); + } +}); + +})(); + + + +(function() { +/** +@module ember +@submodule ember-handlebars +*/ + +/** + `template` allows you to render a template from inside another template. + This allows you to re-use the same template in multiple places. For example: + + ```html + + ``` + + ```html + + ``` + + This helper looks for templates in the global `Ember.TEMPLATES` hash. If you + add ` + ``` + + And application code + + ```javascript + AController = Ember.Controller.extend({ + anActionName: function() {} + }); + + AView = Ember.View.extend({ + controller: AController.create(), + templateName: 'a-template' + }); + + aView = AView.create(); + aView.appendTo('body'); + ``` + + Will results in the following rendered HTML + + ```html +
+
+ click me +
+
+ ``` + + Clicking "click me" will trigger the `anActionName` method of the + `AController`. In this case, no additional parameters will be passed. + + If you provide additional parameters to the helper: + + ```handlebars + + ``` + + Those parameters will be passed along as arguments to the JavaScript + function implementing the action. + + ### Event Propagation + + Events triggered through the action helper will automatically have + `.preventDefault()` called on them. You do not need to do so in your event + handlers. + + To also disable bubbling, pass `bubbles=false` to the helper: + + ```handlebars + + ``` + + If you need the default handler to trigger you should either register your + own event handler, or use event methods on your view class. See `Ember.View` + 'Responding to Browser Events' for more information. + + ### Specifying DOM event type + + By default the `{{action}}` helper registers for DOM `click` events. You can + supply an `on` option to the helper to specify a different DOM event name: + + ```handlebars + + ``` + + See `Ember.View` 'Responding to Browser Events' for a list of + acceptable DOM event names. + + NOTE: Because `{{action}}` depends on Ember's event dispatch system it will + only function if an `Ember.EventDispatcher` instance is available. An + `Ember.EventDispatcher` instance will be created when a new `Ember.Application` + is created. Having an instance of `Ember.Application` will satisfy this + requirement. + + ### Specifying a Target + + There are several possible target objects for `{{action}}` helpers: + + In a typical Ember application, where views are managed through use of the + `{{outlet}}` helper, actions will bubble to the current controller, then + to the current route, and then up the route hierarchy. + + Alternatively, a `target` option can be provided to the helper to change + which object will receive the method call. This option must be a path + path to an object, accessible in the current context: + + ```handlebars + + ``` + + Clicking "click me" in the rendered HTML of the above template will trigger + the `anActionName` method of the object at `MyApplication.someObject`. + + If an action's target does not implement a method that matches the supplied + action name an error will be thrown. + + ```handlebars + + ``` + + With the following application code + + ```javascript + AView = Ember.View.extend({ + templateName; 'a-template', + // note: no method 'aMethodNameThatIsMissing' + anActionName: function(event) {} + }); + + aView = AView.create(); + aView.appendTo('body'); + ``` + + Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when + "click me" is clicked. + + ### Additional Parameters + + You may specify additional parameters to the `{{action}}` helper. These + parameters are passed along as the arguments to the JavaScript function + implementing the action. + + ```handlebars + + ``` + + Clicking "click me" will trigger the `edit` method on the current view's + controller with the current person as a parameter. + + @method action + @for Ember.Handlebars.helpers + @param {String} actionName + @param {Object} [context]* + @param {Hash} options + */ + EmberHandlebars.registerHelper('action', function(actionName) { + var options = arguments[arguments.length - 1], + contexts = a_slice.call(arguments, 1, -1); + + var hash = options.hash, + view = options.data.view, + controller, link; + + // create a hash to pass along to registerAction + var action = { + eventName: hash.on || "click" + }; + + action.parameters = { + context: this, + options: options, + params: contexts + }; + + action.view = view = get(view, 'concreteView'); + + var root, target; + + if (hash.target) { + root = this; + target = hash.target; + } else if (controller = options.data.keywords.controller) { + root = controller; + } + + action.target = { root: root, target: target, options: options }; + action.bubbles = hash.bubbles; + + var actionId = ActionHelper.registerAction(actionName, action); + return new SafeString('data-ember-action="' + actionId + '"'); + }); + +}); + +})(); + + + +(function() { +/** +@module ember +@submodule ember-routing +*/ + +if (Ember.ENV.EXPERIMENTAL_CONTROL_HELPER) { + var get = Ember.get, set = Ember.set; + + /** + The control helper is currently under development and is considered experimental. + To enable it, set `ENV.EXPERIMENTAL_CONTROL_HELPER = true` before requiring Ember. + + @method control + @for Ember.Handlebars.helpers + @param {String} path + @param {String} modelPath + @param {Hash} options + @return {String} HTML string + */ + Ember.Handlebars.registerHelper('control', function(path, modelPath, options) { + if (arguments.length === 2) { + options = modelPath; + modelPath = undefined; + } + + var model; + + if (modelPath) { + model = Ember.Handlebars.get(this, modelPath, options); + } + + var controller = options.data.keywords.controller, + view = options.data.keywords.view, + children = get(controller, '_childContainers'), + controlID = options.hash.controlID, + container, subContainer; + + if (children.hasOwnProperty(controlID)) { + subContainer = children[controlID]; + } else { + container = get(controller, 'container'), + subContainer = container.child(); + children[controlID] = subContainer; + } + + var normalizedPath = path.replace(/\//g, '.'); + + var childView = subContainer.lookup('view:' + normalizedPath) || subContainer.lookup('view:default'), + childController = subContainer.lookup('controller:' + normalizedPath), + childTemplate = subContainer.lookup('template:' + path); + + Ember.assert("Could not find controller for path: " + normalizedPath, childController); + Ember.assert("Could not find view for path: " + normalizedPath, childView); + + set(childController, 'target', controller); + set(childController, 'model', model); + + options.hash.template = childTemplate; + options.hash.controller = childController; + + function observer() { + var model = Ember.Handlebars.get(this, modelPath, options); + set(childController, 'model', model); + childView.rerender(); + } + + Ember.addObserver(this, modelPath, observer); + childView.one('willDestroyElement', this, function() { + Ember.removeObserver(this, modelPath, observer); + }); + + Ember.Handlebars.helpers.view.call(this, childView, options); + }); +} + +})(); + + + +(function() { + +})(); + + + +(function() { +/** +@module ember +@submodule ember-routing +*/ + +var get = Ember.get, set = Ember.set; + +Ember.ControllerMixin.reopen({ + transitionToRoute: function() { + // target may be either another controller or a router + var target = get(this, 'target'), + method = target.transitionToRoute || target.transitionTo; + return method.apply(target, arguments); + }, + + transitionTo: function() { + Ember.deprecate("transitionTo is deprecated. Please use transitionToRoute."); + return this.transitionToRoute.apply(this, arguments); + }, + + replaceRoute: function() { + // target may be either another controller or a router + var target = get(this, 'target'), + method = target.replaceRoute || target.replaceWith; + return method.apply(target, arguments); + }, + + replaceWith: function() { + Ember.deprecate("replaceWith is deprecated. Please use replaceRoute."); + return this.replaceRoute.apply(this, arguments); + } +}); + +})(); + + + +(function() { +/** +@module ember +@submodule ember-routing +*/ + +var get = Ember.get, set = Ember.set; + +Ember.View.reopen({ + init: function() { + set(this, '_outlets', {}); + this._super(); + }, + + connectOutlet: function(outletName, view) { + var outlets = get(this, '_outlets'), + container = get(this, 'container'), + router = container && container.lookup('router:main'), + renderedName = get(view, 'renderedName'); + + set(outlets, outletName, view); + + if (router && renderedName) { + router._connectActiveView(renderedName, view); + } + }, + + disconnectOutlet: function(outletName) { + var outlets = get(this, '_outlets'); + + set(outlets, outletName, null); + } +}); + +})(); + + + +(function() { + +})(); + + + +(function() { +/** +@module ember +@submodule ember-routing +*/ + +var get = Ember.get, set = Ember.set; + +/* + This file implements the `location` API used by Ember's router. + + That API is: + + getURL: returns the current URL + setURL(path): sets the current URL + replaceURL(path): replace the current URL (optional) + onUpdateURL(callback): triggers the callback when the URL changes + formatURL(url): formats `url` to be placed into `href` attribute + + Calling setURL or replaceURL will not trigger onUpdateURL callbacks. + + TODO: This should perhaps be moved so that it's visible in the doc output. +*/ + +/** + Ember.Location returns an instance of the correct implementation of + the `location` API. + + You can pass it a `implementation` ('hash', 'history', 'none') to force a + particular implementation. + + @class Location + @namespace Ember + @static +*/ +Ember.Location = { + create: function(options) { + var implementation = options && options.implementation; + Ember.assert("Ember.Location.create: you must specify a 'implementation' option", !!implementation); + + var implementationClass = this.implementations[implementation]; + Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass); + + return implementationClass.create.apply(implementationClass, arguments); + }, + + registerImplementation: function(name, implementation) { + this.implementations[name] = implementation; + }, + + implementations: {} +}; + +})(); + + + +(function() { +/** +@module ember +@submodule ember-routing +*/ + +var get = Ember.get, set = Ember.set; + +/** + Ember.NoneLocation does not interact with the browser. It is useful for + testing, or when you need to manage state with your Router, but temporarily + don't want it to muck with the URL (for example when you embed your + application in a larger page). + + @class NoneLocation + @namespace Ember + @extends Ember.Object +*/ +Ember.NoneLocation = Ember.Object.extend({ + path: '', + + getURL: function() { + return get(this, 'path'); + }, + + setURL: function(path) { + set(this, 'path', path); + }, + + onUpdateURL: function(callback) { + this.updateCallback = callback; + }, + + handleURL: function(url) { + set(this, 'path', url); + this.updateCallback(url); + }, + + formatURL: function(url) { + // The return value is not overly meaningful, but we do not want to throw + // errors when test code renders templates containing {{action href=true}} + // helpers. + return url; + } +}); + +Ember.Location.registerImplementation('none', Ember.NoneLocation); + +})(); + + + +(function() { +/** +@module ember +@submodule ember-routing +*/ + +var get = Ember.get, set = Ember.set; + +/** + Ember.HashLocation implements the location API using the browser's + hash. At present, it relies on a hashchange event existing in the + browser. + + @class HashLocation + @namespace Ember + @extends Ember.Object +*/ +Ember.HashLocation = Ember.Object.extend({ + + init: function() { + set(this, 'location', get(this, 'location') || window.location); + }, + + /** + @private + + Returns the current `location.hash`, minus the '#' at the front. + + @method getURL + */ + getURL: function() { + return get(this, 'location').hash.substr(1); + }, + + /** + @private + + Set the `location.hash` and remembers what was set. This prevents + `onUpdateURL` callbacks from triggering when the hash was set by + `HashLocation`. + + @method setURL + @param path {String} + */ + setURL: function(path) { + get(this, 'location').hash = path; + set(this, 'lastSetURL', path); + }, + + /** + @private + + Register a callback to be invoked when the hash changes. These + callbacks will execute when the user presses the back or forward + button, but not after `setURL` is invoked. + + @method onUpdateURL + @param callback {Function} + */ + onUpdateURL: function(callback) { + var self = this; + var guid = Ember.guidFor(this); + + Ember.$(window).bind('hashchange.ember-location-'+guid, function() { + Ember.run(function() { + var path = location.hash.substr(1); + if (get(self, 'lastSetURL') === path) { return; } + + set(self, 'lastSetURL', null); + + callback(location.hash.substr(1)); + }); + }); + }, + + /** + @private + + Given a URL, formats it to be placed into the page as part + of an element's `href` attribute. + + This is used, for example, when using the {{action}} helper + to generate a URL based on an event. + + @method formatURL + @param url {String} + */ + formatURL: function(url) { + return '#'+url; + }, + + willDestroy: function() { + var guid = Ember.guidFor(this); + + Ember.$(window).unbind('hashchange.ember-location-'+guid); + } +}); + +Ember.Location.registerImplementation('hash', Ember.HashLocation); + +})(); + + + +(function() { +/** +@module ember +@submodule ember-routing +*/ + +var get = Ember.get, set = Ember.set; +var popstateReady = false; + +/** + Ember.HistoryLocation implements the location API using the browser's + history.pushState API. + + @class HistoryLocation + @namespace Ember + @extends Ember.Object +*/ +Ember.HistoryLocation = Ember.Object.extend({ + + init: function() { + set(this, 'location', get(this, 'location') || window.location); + this.initState(); + }, + + /** + @private + + Used to set state on first call to setURL + + @method initState + */ + initState: function() { + this.replaceState(this.formatURL(this.getURL())); + set(this, 'history', window.history); + }, + + /** + Will be pre-pended to path upon state change + + @property rootURL + @default '/' + */ + rootURL: '/', + + /** + @private + + Returns the current `location.pathname` without rootURL + + @method getURL + */ + getURL: function() { + var rootURL = get(this, 'rootURL'), + url = get(this, 'location').pathname; + + rootURL = rootURL.replace(/\/$/, ''); + url = url.replace(rootURL, ''); + + return url; + }, + + /** + @private + + Uses `history.pushState` to update the url without a page reload. + + @method setURL + @param path {String} + */ + setURL: function(path) { + path = this.formatURL(path); + + if (this.getState() && this.getState().path !== path) { + popstateReady = true; + this.pushState(path); + } + }, + + /** + @private + + Uses `history.replaceState` to update the url without a page reload + or history modification. + + @method replaceURL + @param path {String} + */ + replaceURL: function(path) { + path = this.formatURL(path); + + if (this.getState() && this.getState().path !== path) { + popstateReady = true; + this.replaceState(path); + } + }, + + /** + @private + + Get the current `history.state` + + @method getState + */ + getState: function() { + return get(this, 'history').state; + }, + + /** + @private + + Pushes a new state + + @method pushState + @param path {String} + */ + pushState: function(path) { + window.history.pushState({ path: path }, null, path); + }, + + /** + @private + + Replaces the current state + + @method replaceState + @param path {String} + */ + replaceState: function(path) { + window.history.replaceState({ path: path }, null, path); + }, + + /** + @private + + Register a callback to be invoked whenever the browser + history changes, including using forward and back buttons. + + @method onUpdateURL + @param callback {Function} + */ + onUpdateURL: function(callback) { + var guid = Ember.guidFor(this), + self = this; + + Ember.$(window).bind('popstate.ember-location-'+guid, function(e) { + if(!popstateReady) { + return; + } + callback(self.getURL()); + }); + }, + + /** + @private + + Used when using `{{action}}` helper. The url is always appended to the rootURL. + + @method formatURL + @param url {String} + */ + formatURL: function(url) { + var rootURL = get(this, 'rootURL'); + + if (url !== '') { + rootURL = rootURL.replace(/\/$/, ''); + } + + return rootURL + url; + }, + + willDestroy: function() { + var guid = Ember.guidFor(this); + + Ember.$(window).unbind('popstate.ember-location-'+guid); + } +}); + +Ember.Location.registerImplementation('history', Ember.HistoryLocation); + +})(); + + + +(function() { + +})(); + + + +(function() { +/** +Ember Routing + +@module ember +@submodule ember-routing +@requires ember-states +@requires ember-views +*/ + +})(); + +(function() { +function visit(vertex, fn, visited, path) { + var name = vertex.name, + vertices = vertex.incoming, + names = vertex.incomingNames, + len = names.length, + i; + if (!visited) { + visited = {}; + } + if (!path) { + path = []; + } + if (visited.hasOwnProperty(name)) { + return; + } + path.push(name); + visited[name] = true; + for (i = 0; i < len; i++) { + visit(vertices[names[i]], fn, visited, path); + } + fn(vertex, path); + path.pop(); +} + +function DAG() { + this.names = []; + this.vertices = {}; +} + +DAG.prototype.add = function(name) { + if (!name) { return; } + if (this.vertices.hasOwnProperty(name)) { + return this.vertices[name]; + } + var vertex = { + name: name, incoming: {}, incomingNames: [], hasOutgoing: false, value: null + }; + this.vertices[name] = vertex; + this.names.push(name); + return vertex; +}; + +DAG.prototype.map = function(name, value) { + this.add(name).value = value; +}; + +DAG.prototype.addEdge = function(fromName, toName) { + if (!fromName || !toName || fromName === toName) { + return; + } + var from = this.add(fromName), to = this.add(toName); + if (to.incoming.hasOwnProperty(fromName)) { + return; + } + function checkCycle(vertex, path) { + if (vertex.name === toName) { + throw new Error("cycle detected: " + toName + " <- " + path.join(" <- ")); + } + } + visit(from, checkCycle); + from.hasOutgoing = true; + to.incoming[fromName] = from; + to.incomingNames.push(fromName); +}; + +DAG.prototype.topsort = function(fn) { + var visited = {}, + vertices = this.vertices, + names = this.names, + len = names.length, + i, vertex; + for (i = 0; i < len; i++) { + vertex = vertices[names[i]]; + if (!vertex.hasOutgoing) { + visit(vertex, fn, visited); + } + } +}; + +DAG.prototype.addEdges = function(name, value, before, after) { + var i; + this.map(name, value); + if (before) { + if (typeof before === 'string') { + this.addEdge(name, before); + } else { + for (i = 0; i < before.length; i++) { + this.addEdge(name, before[i]); + } + } + } + if (after) { + if (typeof after === 'string') { + this.addEdge(after, name); + } else { + for (i = 0; i < after.length; i++) { + this.addEdge(after[i], name); + } + } + } +}; + +Ember.DAG = DAG; + +})(); + + + +(function() { +/** +@module ember +@submodule ember-application +*/ + +var get = Ember.get, set = Ember.set, + classify = Ember.String.classify, + decamelize = Ember.String.decamelize; + +/** + An instance of `Ember.Application` is the starting point for every Ember + application. It helps to instantiate, initialize and coordinate the many + objects that make up your app. + + Each Ember app has one and only one `Ember.Application` object. In fact, the + very first thing you should do in your application is create the instance: + + ```javascript + window.App = Ember.Application.create(); + ``` + + Typically, the application object is the only global variable. All other + classes in your app should be properties on the `Ember.Application` instance, + which highlights its first role: a global namespace. + + For example, if you define a view class, it might look like this: + + ```javascript + App.MyView = Ember.View.extend(); + ``` + + By default, calling `Ember.Application.create()` will automatically initialize + your application by calling the `Ember.Application.initialize()` method. If + you need to delay initialization, you can call your app's `deferReadiness()` + method. When you are ready for your app to be initialized, call its + `advanceReadiness()` method. + + Because `Ember.Application` inherits from `Ember.Namespace`, any classes + you create will have useful string representations when calling `toString()`. + See the `Ember.Namespace` documentation for more information. + + While you can think of your `Ember.Application` as a container that holds the + other classes in your application, there are several other responsibilities + going on under-the-hood that you may want to understand. + + ### Event Delegation + + Ember uses a technique called _event delegation_. This allows the framework + to set up a global, shared event listener instead of requiring each view to + do it manually. For example, instead of each view registering its own + `mousedown` listener on its associated element, Ember sets up a `mousedown` + listener on the `body`. + + If a `mousedown` event occurs, Ember will look at the target of the event and + start walking up the DOM node tree, finding corresponding views and invoking + their `mouseDown` method as it goes. + + `Ember.Application` has a number of default events that it listens for, as + well as a mapping from lowercase events to camel-cased view method names. For + example, the `keypress` event causes the `keyPress` method on the view to be + called, the `dblclick` event causes `doubleClick` to be called, and so on. + + If there is a browser event that Ember does not listen for by default, you + can specify custom events and their corresponding view method names by + setting the application's `customEvents` property: + + ```javascript + App = Ember.Application.create({ + customEvents: { + // add support for the loadedmetadata media + // player event + 'loadedmetadata': "loadedMetadata" + } + }); + ``` + + By default, the application sets up these event listeners on the document + body. However, in cases where you are embedding an Ember application inside + an existing page, you may want it to set up the listeners on an element + inside the body. + + For example, if only events inside a DOM element with the ID of `ember-app` + should be delegated, set your application's `rootElement` property: + + ```javascript + window.App = Ember.Application.create({ + rootElement: '#ember-app' + }); + ``` + + The `rootElement` can be either a DOM element or a jQuery-compatible selector + string. Note that *views appended to the DOM outside the root element will + not receive events.* If you specify a custom root element, make sure you only + append views inside it! + + To learn more about the advantages of event delegation and the Ember view + layer, and a list of the event listeners that are setup by default, visit the + [Ember View Layer guide](http://emberjs.com/guides/view_layer#toc_event-delegation). + + ### Initializers + + Libraries on top of Ember can register additional initializers, like so: + + ```javascript + Ember.Application.initializer({ + name: "store", + + initialize: function(container, application) { + container.register('store', 'main', application.Store); + } + }); + ``` + + ### Routing + + In addition to creating your application's router, `Ember.Application` is + also responsible for telling the router when to start routing. Transitions + between routes can be logged with the LOG_TRANSITIONS flag: + + ```javascript + window.App = Ember.Application.create({ + LOG_TRANSITIONS: true + }); + ``` + + By default, the router will begin trying to translate the current URL into + application state once the browser emits the `DOMContentReady` event. If you + need to defer routing, you can call the application's `deferReadiness()` + method. Once routing can begin, call the `advanceReadiness()` method. + + If there is any setup required before routing begins, you can implement a + `ready()` method on your app that will be invoked immediately before routing + begins. + + To begin routing, you must have at a minimum a top-level controller and view. + You define these as `App.ApplicationController` and `App.ApplicationView`, + respectively. Your application will not work if you do not define these two + mandatory classes. For example: + + ```javascript + App.ApplicationView = Ember.View.extend({ + templateName: 'application' + }); + App.ApplicationController = Ember.Controller.extend(); + ``` + + @class Application + @namespace Ember + @extends Ember.Namespace +*/ +var Application = Ember.Application = Ember.Namespace.extend({ + + /** + The root DOM element of the Application. This can be specified as an + element or a + [jQuery-compatible selector string](http://api.jquery.com/category/selectors/). + + This is the element that will be passed to the Application's, + `eventDispatcher`, which sets up the listeners for event delegation. Every + view in your application should be a child of the element you specify here. + + @property rootElement + @type DOMElement + @default 'body' + */ + rootElement: 'body', + + /** + The `Ember.EventDispatcher` responsible for delegating events to this + application's views. + + The event dispatcher is created by the application at initialization time + and sets up event listeners on the DOM element described by the + application's `rootElement` property. + + See the documentation for `Ember.EventDispatcher` for more information. + + @property eventDispatcher + @type Ember.EventDispatcher + @default null + */ + eventDispatcher: null, + + /** + The DOM events for which the event dispatcher should listen. + + By default, the application's `Ember.EventDispatcher` listens + for a set of standard DOM events, such as `mousedown` and + `keyup`, and delegates them to your application's `Ember.View` + instances. + + If you would like additional events to be delegated to your + views, set your `Ember.Application`'s `customEvents` property + to a hash containing the DOM event name as the key and the + corresponding view method name as the value. For example: + + ```javascript + App = Ember.Application.create({ + customEvents: { + // add support for the loadedmetadata media + // player event + 'loadedmetadata': "loadedMetadata" + } + }); + ``` + + @property customEvents + @type Object + @default null + */ + customEvents: null, + + isInitialized: false, + + // Start off the number of deferrals at 1. This will be + // decremented by the Application's own `initialize` method. + _readinessDeferrals: 1, + + init: function() { + if (!this.$) { this.$ = Ember.$; } + this.__container__ = this.buildContainer(); + + this.Router = this.Router || this.defaultRouter(); + if (this.Router) { this.Router.namespace = this; } + + this._super(); + + this.deferUntilDOMReady(); + this.scheduleInitialize(); + + Ember.debug('-------------------------------'); + Ember.debug('Ember.VERSION : ' + Ember.VERSION); + Ember.debug('Handlebars.VERSION : ' + Ember.Handlebars.VERSION); + Ember.debug('jQuery.VERSION : ' + Ember.$().jquery); + Ember.debug('-------------------------------'); + }, + + /** + @private + + Build the container for the current application. + + Also register a default application view in case the application + itself does not. + + @method buildContainer + @return {Ember.Container} the configured container + */ + buildContainer: function() { + var container = this.__container__ = Application.buildContainer(this); + + return container; + }, + + /** + @private + + If the application has not opted out of routing and has not explicitly + defined a router, supply a default router for the application author + to configure. + + This allows application developers to do: + + ```javascript + App = Ember.Application.create(); + + App.Router.map(function(match) { + match("/").to("index"); + }); + ``` + + @method defaultRouter + @return {Ember.Router} the default router + */ + defaultRouter: function() { + // Create a default App.Router if one was not supplied to make + // it possible to do App.Router.map(...) without explicitly + // creating a router first. + if (this.router === undefined) { + return Ember.Router.extend(); + } + }, + + /** + @private + + Defer Ember readiness until DOM readiness. By default, Ember + will wait for both DOM readiness and application initialization, + as well as any deferrals registered by initializers. + + @method deferUntilDOMReady + */ + deferUntilDOMReady: function() { + this.deferReadiness(); + + var self = this; + this.$().ready(function() { + self.advanceReadiness(); + }); + }, + + /** + @private + + Automatically initialize the application once the DOM has + become ready. + + The initialization itself is deferred using Ember.run.once, + which ensures that application loading finishes before + booting. + + If you are asynchronously loading code, you should call + `deferReadiness()` to defer booting, and then call + `advanceReadiness()` once all of your code has finished + loading. + + @method scheduleInitialize + */ + scheduleInitialize: function() { + var self = this; + this.$().ready(function() { + if (self.isDestroyed || self.isInitialized) return; + Ember.run.once(self, 'initialize'); + }); + }, + + /** + Use this to defer readiness until some condition is true. + + Example: + + ```javascript + App = Ember.Application.create(); + App.deferReadiness(); + + jQuery.getJSON("/auth-token", function(token) { + App.token = token; + App.advanceReadiness(); + }); + ``` + + This allows you to perform asynchronous setup logic and defer + booting your application until the setup has finished. + + However, if the setup requires a loading UI, it might be better + to use the router for this purpose. + + @method deferReadiness + */ + deferReadiness: function() { + Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0); + this._readinessDeferrals++; + }, + + /** + @method advanceReadiness + @see {Ember.Application#deferReadiness} + */ + advanceReadiness: function() { + this._readinessDeferrals--; + + if (this._readinessDeferrals === 0) { + Ember.run.once(this, this.didBecomeReady); + } + }, + + /** + registers a factory for later injection + + Example: + + ```javascript + App = Ember.Application.create(); + + App.Person = Ember.Object.extend({}); + App.Orange = Ember.Object.extend({}); + App.Email = Ember.Object.extend({}); + + App.register('model:user', App.Person, {singleton: false }); + App.register('fruit:favorite', App.Orange); + App.register('communication:main', App.Email, {singleton: false}); + ``` + + @method register + @param type {String} + @param name {String} + @param factory {String} + @param options {String} (optional) + **/ + register: function() { + var container = this.__container__; + container.register.apply(container, arguments); + }, + /** + defines an injection or typeInjection + + Example: + + ```javascript + App.inject(, , ) + App.inject('model:user', 'email', 'model:email') + App.inject('model', 'source', 'source:main') + ``` + + @method inject + @param factoryNameOrType {String} + @param property {String} + @param injectionName {String} + **/ + inject: function(){ + var container = this.__container__; + container.injection.apply(container, arguments); + }, + + /** + @private + + Initialize the application. This happens automatically. + + Run any initializers and run the application load hook. These hooks may + choose to defer readiness. For example, an authentication hook might want + to defer readiness until the auth token has been retrieved. + + @method initialize + */ + initialize: function() { + Ember.assert("Application initialize may only be called once", !this.isInitialized); + Ember.assert("Cannot initialize a destroyed application", !this.isDestroyed); + this.isInitialized = true; + + // At this point, the App.Router must already be assigned + this.__container__.register('router', 'main', this.Router); + + this.runInitializers(); + Ember.runLoadHooks('application', this); + + // At this point, any initializers or load hooks that would have wanted + // to defer readiness have fired. In general, advancing readiness here + // will proceed to didBecomeReady. + this.advanceReadiness(); + + return this; + }, + + reset: function() { + get(this, '__container__').destroy(); + this.buildContainer(); + + this.isInitialized = false; + this.initialize(); + this.startRouting(); + }, + + /** + @private + @method runInitializers + */ + runInitializers: function() { + var initializers = get(this.constructor, 'initializers'), + container = this.__container__, + graph = new Ember.DAG(), + namespace = this, + properties, i, initializer; + + for (i=0; i` state will be added to the list of enter and exit + // states because its context has changed. + + while (contexts.length > 0) { + if (stateIdx >= 0) { + state = this.enterStates[stateIdx--]; + } else { + if (this.enterStates.length) { + state = get(this.enterStates[0], 'parentState'); + if (!state) { throw "Cannot match all contexts to states"; } + } else { + // If re-entering the current state with a context, the resolve + // state will be the current state. + state = this.resolveState; + } + + this.enterStates.unshift(state); + this.exitStates.unshift(state); + } + + // in routers, only states with dynamic segments have a context + if (get(state, 'hasContext')) { + context = contexts.pop(); + } else { + context = null; + } + + matchedContexts.unshift(context); + } + + this.contexts = matchedContexts; + }, + + /** + Add any `initialState`s to the list of enter states. + + @method addInitialStates + */ + addInitialStates: function() { + var finalState = this.finalState, initialState; + + while(true) { + initialState = get(finalState, 'initialState') || 'start'; + finalState = get(finalState, 'states.' + initialState); + + if (!finalState) { break; } + + this.finalState = finalState; + this.enterStates.push(finalState); + this.contexts.push(undefined); + } + }, + + /** + Remove any states that were added because the number of contexts + exceeded the number of explicit enter states, but the context has + not changed since the last time the state was entered. + + @method removeUnchangedContexts + @param {Ember.StateManager} manager passed in to look up the last + context for a states + */ + removeUnchangedContexts: function(manager) { + // Start from the beginning of the enter states. If the state was added + // to the list during the context matching phase, make sure the context + // has actually changed since the last time the state was entered. + while (this.enterStates.length > 0) { + if (this.enterStates[0] !== this.exitStates[0]) { break; } + + if (this.enterStates.length === this.contexts.length) { + if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; } + this.contexts.shift(); + } + + this.resolveState = this.enterStates.shift(); + this.exitStates.shift(); + } + } +}; + +var sendRecursively = function(event, currentState, isUnhandledPass) { + var log = this.enableLogging, + eventName = isUnhandledPass ? 'unhandledEvent' : event, + action = currentState[eventName], + contexts, sendRecursiveArguments, actionArguments; + + contexts = [].slice.call(arguments, 3); + + // Test to see if the action is a method that + // can be invoked. Don't blindly check just for + // existence, because it is possible the state + // manager has a child state of the given name, + // and we should still raise an exception in that + // case. + if (typeof action === 'function') { + if (log) { + if (isUnhandledPass) { + Ember.Logger.log(fmt("STATEMANAGER: Unhandled event '%@' being sent to state %@.", [event, get(currentState, 'path')])); + } else { + Ember.Logger.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, get(currentState, 'path')])); + } + } + + actionArguments = contexts; + if (isUnhandledPass) { + actionArguments.unshift(event); + } + actionArguments.unshift(this); + + return action.apply(currentState, actionArguments); + } else { + var parentState = get(currentState, 'parentState'); + if (parentState) { + + sendRecursiveArguments = contexts; + sendRecursiveArguments.unshift(event, parentState, isUnhandledPass); + + return sendRecursively.apply(this, sendRecursiveArguments); + } else if (!isUnhandledPass) { + return sendEvent.call(this, event, contexts, true); + } + } +}; + +var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) { + sendRecursiveArguments.unshift(eventName, get(this, 'currentState'), isUnhandledPass); + return sendRecursively.apply(this, sendRecursiveArguments); +}; + +/** + StateManager is part of Ember's implementation of a finite state machine. A + StateManager instance manages a number of properties that are instances of + `Ember.State`, + tracks the current active state, and triggers callbacks when states have changed. + + ## Defining States + + The states of StateManager can be declared in one of two ways. First, you can + define a `states` property that contains all the states: + + ```javascript + managerA = Ember.StateManager.create({ + states: { + stateOne: Ember.State.create(), + stateTwo: Ember.State.create() + } + }) + + managerA.get('states') + // { + // stateOne: Ember.State.create(), + // stateTwo: Ember.State.create() + // } + ``` + + You can also add instances of `Ember.State` (or an `Ember.State` subclass) + directly as properties of a StateManager. These states will be collected into + the `states` property for you. + + ```javascript + managerA = Ember.StateManager.create({ + stateOne: Ember.State.create(), + stateTwo: Ember.State.create() + }) + + managerA.get('states') + // { + // stateOne: Ember.State.create(), + // stateTwo: Ember.State.create() + // } + ``` + + ## The Initial State + + When created a StateManager instance will immediately enter into the state + defined as its `start` property or the state referenced by name in its + `initialState` property: + + ```javascript + managerA = Ember.StateManager.create({ + start: Ember.State.create({}) + }) + + managerA.get('currentState.name') // 'start' + + managerB = Ember.StateManager.create({ + initialState: 'beginHere', + beginHere: Ember.State.create({}) + }) + + managerB.get('currentState.name') // 'beginHere' + ``` + + Because it is a property you may also provide a computed function if you wish + to derive an `initialState` programmatically: + + ```javascript + managerC = Ember.StateManager.create({ + initialState: function(){ + if (someLogic) { + return 'active'; + } else { + return 'passive'; + } + }.property(), + active: Ember.State.create({}), + passive: Ember.State.create({}) + }) + ``` + + ## Moving Between States + + A StateManager can have any number of `Ember.State` objects as properties + and can have a single one of these states as its current state. + + Calling `transitionTo` transitions between states: + + ```javascript + robotManager = Ember.StateManager.create({ + initialState: 'poweredDown', + poweredDown: Ember.State.create({}), + poweredUp: Ember.State.create({}) + }) + + robotManager.get('currentState.name') // 'poweredDown' + robotManager.transitionTo('poweredUp') + robotManager.get('currentState.name') // 'poweredUp' + ``` + + Before transitioning into a new state the existing `currentState` will have + its `exit` method called with the StateManager instance as its first argument + and an object representing the transition as its second argument. + + After transitioning into a new state the new `currentState` will have its + `enter` method called with the StateManager instance as its first argument + and an object representing the transition as its second argument. + + ```javascript + robotManager = Ember.StateManager.create({ + initialState: 'poweredDown', + poweredDown: Ember.State.create({ + exit: function(stateManager){ + console.log("exiting the poweredDown state") + } + }), + poweredUp: Ember.State.create({ + enter: function(stateManager){ + console.log("entering the poweredUp state. Destroy all humans.") + } + }) + }) + + robotManager.get('currentState.name') // 'poweredDown' + robotManager.transitionTo('poweredUp') + + // will log + // 'exiting the poweredDown state' + // 'entering the poweredUp state. Destroy all humans.' + ``` + + Once a StateManager is already in a state, subsequent attempts to enter that + state will not trigger enter or exit method calls. Attempts to transition + into a state that the manager does not have will result in no changes in the + StateManager's current state: + + ```javascript + robotManager = Ember.StateManager.create({ + initialState: 'poweredDown', + poweredDown: Ember.State.create({ + exit: function(stateManager){ + console.log("exiting the poweredDown state") + } + }), + poweredUp: Ember.State.create({ + enter: function(stateManager){ + console.log("entering the poweredUp state. Destroy all humans.") + } + }) + }) + + robotManager.get('currentState.name') // 'poweredDown' + robotManager.transitionTo('poweredUp') + // will log + // 'exiting the poweredDown state' + // 'entering the poweredUp state. Destroy all humans.' + robotManager.transitionTo('poweredUp') // no logging, no state change + + robotManager.transitionTo('someUnknownState') // silently fails + robotManager.get('currentState.name') // 'poweredUp' + ``` + + Each state property may itself contain properties that are instances of + `Ember.State`. The StateManager can transition to specific sub-states in a + series of transitionTo method calls or via a single transitionTo with the + full path to the specific state. The StateManager will also keep track of the + full path to its currentState + + ```javascript + robotManager = Ember.StateManager.create({ + initialState: 'poweredDown', + poweredDown: Ember.State.create({ + charging: Ember.State.create(), + charged: Ember.State.create() + }), + poweredUp: Ember.State.create({ + mobile: Ember.State.create(), + stationary: Ember.State.create() + }) + }) + + robotManager.get('currentState.name') // 'poweredDown' + + robotManager.transitionTo('poweredUp') + robotManager.get('currentState.name') // 'poweredUp' + + robotManager.transitionTo('mobile') + robotManager.get('currentState.name') // 'mobile' + + // transition via a state path + robotManager.transitionTo('poweredDown.charging') + robotManager.get('currentState.name') // 'charging' + + robotManager.get('currentState.path') // 'poweredDown.charging' + ``` + + Enter transition methods will be called for each state and nested child state + in their hierarchical order. Exit methods will be called for each state and + its nested states in reverse hierarchical order. + + Exit transitions for a parent state are not called when entering into one of + its child states, only when transitioning to a new section of possible states + in the hierarchy. + + ```javascript + robotManager = Ember.StateManager.create({ + initialState: 'poweredDown', + poweredDown: Ember.State.create({ + enter: function(){}, + exit: function(){ + console.log("exited poweredDown state") + }, + charging: Ember.State.create({ + enter: function(){}, + exit: function(){} + }), + charged: Ember.State.create({ + enter: function(){ + console.log("entered charged state") + }, + exit: function(){ + console.log("exited charged state") + } + }) + }), + poweredUp: Ember.State.create({ + enter: function(){ + console.log("entered poweredUp state") + }, + exit: function(){}, + mobile: Ember.State.create({ + enter: function(){ + console.log("entered mobile state") + }, + exit: function(){} + }), + stationary: Ember.State.create({ + enter: function(){}, + exit: function(){} + }) + }) + }) + + + robotManager.get('currentState.path') // 'poweredDown' + robotManager.transitionTo('charged') + // logs 'entered charged state' + // but does *not* log 'exited poweredDown state' + robotManager.get('currentState.name') // 'charged + + robotManager.transitionTo('poweredUp.mobile') + // logs + // 'exited charged state' + // 'exited poweredDown state' + // 'entered poweredUp state' + // 'entered mobile state' + ``` + + During development you can set a StateManager's `enableLogging` property to + `true` to receive console messages of state transitions. + + ```javascript + robotManager = Ember.StateManager.create({ + enableLogging: true + }) + ``` + + ## Managing currentState with Actions + + To control which transitions are possible for a given state, and + appropriately handle external events, the StateManager can receive and + route action messages to its states via the `send` method. Calling to + `send` with an action name will begin searching for a method with the same + name starting at the current state and moving up through the parent states + in a state hierarchy until an appropriate method is found or the StateManager + instance itself is reached. + + If an appropriately named method is found it will be called with the state + manager as the first argument and an optional `context` object as the second + argument. + + ```javascript + managerA = Ember.StateManager.create({ + initialState: 'stateOne.substateOne.subsubstateOne', + stateOne: Ember.State.create({ + substateOne: Ember.State.create({ + anAction: function(manager, context){ + console.log("an action was called") + }, + subsubstateOne: Ember.State.create({}) + }) + }) + }) + + managerA.get('currentState.name') // 'subsubstateOne' + managerA.send('anAction') + // 'stateOne.substateOne.subsubstateOne' has no anAction method + // so the 'anAction' method of 'stateOne.substateOne' is called + // and logs "an action was called" + // with managerA as the first argument + // and no second argument + + someObject = {} + managerA.send('anAction', someObject) + // the 'anAction' method of 'stateOne.substateOne' is called again + // with managerA as the first argument and + // someObject as the second argument. + ``` + + If the StateManager attempts to send an action but does not find an appropriately named + method in the current state or while moving upwards through the state hierarchy, it will + repeat the process looking for a `unhandledEvent` method. If an `unhandledEvent` method is + found, it will be called with the original event name as the second argument. If an + `unhandledEvent` method is not found, the StateManager will throw a new Ember.Error. + + ```javascript + managerB = Ember.StateManager.create({ + initialState: 'stateOne.substateOne.subsubstateOne', + stateOne: Ember.State.create({ + substateOne: Ember.State.create({ + subsubstateOne: Ember.State.create({}), + unhandledEvent: function(manager, eventName, context) { + console.log("got an unhandledEvent with name " + eventName); + } + }) + }) + }) + + managerB.get('currentState.name') // 'subsubstateOne' + managerB.send('anAction') + // neither `stateOne.substateOne.subsubstateOne` nor any of it's + // parent states have a handler for `anAction`. `subsubstateOne` + // also does not have a `unhandledEvent` method, but its parent + // state, `substateOne`, does, and it gets fired. It will log + // "got an unhandledEvent with name anAction" + ``` + + Action detection only moves upwards through the state hierarchy from the current state. + It does not search in other portions of the hierarchy. + + ```javascript + managerC = Ember.StateManager.create({ + initialState: 'stateOne.substateOne.subsubstateOne', + stateOne: Ember.State.create({ + substateOne: Ember.State.create({ + subsubstateOne: Ember.State.create({}) + }) + }), + stateTwo: Ember.State.create({ + anAction: function(manager, context){ + // will not be called below because it is + // not a parent of the current state + } + }) + }) + + managerC.get('currentState.name') // 'subsubstateOne' + managerC.send('anAction') + // Error: could not + // respond to event anAction in state stateOne.substateOne.subsubstateOne. + ``` + + Inside of an action method the given state should delegate `transitionTo` calls on its + StateManager. + + ```javascript + robotManager = Ember.StateManager.create({ + initialState: 'poweredDown.charging', + poweredDown: Ember.State.create({ + charging: Ember.State.create({ + chargeComplete: function(manager, context){ + manager.transitionTo('charged') + } + }), + charged: Ember.State.create({ + boot: function(manager, context){ + manager.transitionTo('poweredUp') + } + }) + }), + poweredUp: Ember.State.create({ + beginExtermination: function(manager, context){ + manager.transitionTo('rampaging') + }, + rampaging: Ember.State.create() + }) + }) + + robotManager.get('currentState.name') // 'charging' + robotManager.send('boot') // throws error, no boot action + // in current hierarchy + robotManager.get('currentState.name') // remains 'charging' + + robotManager.send('beginExtermination') // throws error, no beginExtermination + // action in current hierarchy + robotManager.get('currentState.name') // remains 'charging' + + robotManager.send('chargeComplete') + robotManager.get('currentState.name') // 'charged' + + robotManager.send('boot') + robotManager.get('currentState.name') // 'poweredUp' + + robotManager.send('beginExtermination', allHumans) + robotManager.get('currentState.name') // 'rampaging' + ``` + + Transition actions can also be created using the `transitionTo` method of the `Ember.State` class. The + following example StateManagers are equivalent: + + ```javascript + aManager = Ember.StateManager.create({ + stateOne: Ember.State.create({ + changeToStateTwo: Ember.State.transitionTo('stateTwo') + }), + stateTwo: Ember.State.create({}) + }) + + bManager = Ember.StateManager.create({ + stateOne: Ember.State.create({ + changeToStateTwo: function(manager, context){ + manager.transitionTo('stateTwo', context) + } + }), + stateTwo: Ember.State.create({}) + }) + ``` + + @class StateManager + @namespace Ember + @extends Ember.State +**/ +Ember.StateManager = Ember.State.extend({ + /** + @private + + When creating a new statemanager, look for a default state to transition + into. This state can either be named `start`, or can be specified using the + `initialState` property. + + @method init + */ + init: function() { + this._super(); + + set(this, 'stateMeta', Ember.Map.create()); + + var initialState = get(this, 'initialState'); + + if (!initialState && get(this, 'states.start')) { + initialState = 'start'; + } + + if (initialState) { + this.transitionTo(initialState); + Ember.assert('Failed to transition to initial state "' + initialState + '"', !!get(this, 'currentState')); + } + }, + + stateMetaFor: function(state) { + var meta = get(this, 'stateMeta'), + stateMeta = meta.get(state); + + if (!stateMeta) { + stateMeta = {}; + meta.set(state, stateMeta); + } + + return stateMeta; + }, + + setStateMeta: function(state, key, value) { + return set(this.stateMetaFor(state), key, value); + }, + + getStateMeta: function(state, key) { + return get(this.stateMetaFor(state), key); + }, + + /** + The current state from among the manager's possible states. This property should + not be set directly. Use `transitionTo` to move between states by name. + + @property currentState + @type Ember.State + */ + currentState: null, + + /** + The path of the current state. Returns a string representation of the current + state. + + @property currentPath + @type String + */ + currentPath: Ember.computed.alias('currentState.path'), + + /** + The name of transitionEvent that this stateManager will dispatch + + @property transitionEvent + @type String + @default 'setup' + */ + transitionEvent: 'setup', + + /** + If set to true, `errorOnUnhandledEvents` will cause an exception to be + raised if you attempt to send an event to a state manager that is not + handled by the current state or any of its parent states. + + @property errorOnUnhandledEvents + @type Boolean + @default true + */ + errorOnUnhandledEvent: true, + + send: function(event) { + var contexts = [].slice.call(arguments, 1); + Ember.assert('Cannot send event "' + event + '" while currentState is ' + get(this, 'currentState'), get(this, 'currentState')); + return sendEvent.call(this, event, contexts, false); + }, + unhandledEvent: function(manager, event) { + if (get(this, 'errorOnUnhandledEvent')) { + throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + get(this, 'currentState.path') + "."); + } + }, + + /** + Finds a state by its state path. + + Example: + + ```javascript + manager = Ember.StateManager.create({ + root: Ember.State.create({ + dashboard: Ember.State.create() + }) + }); + + manager.getStateByPath(manager, "root.dashboard") + + // returns the dashboard state + ``` + + @method getStateByPath + @param {Ember.State} root the state to start searching from + @param {String} path the state path to follow + @return {Ember.State} the state at the end of the path + */ + getStateByPath: function(root, path) { + var parts = path.split('.'), + state = root; + + for (var i=0, len=parts.length; i`, an attempt to + // transition to `comments.show` will match ``. + // + // First, this code will look for root.posts.show.comments.show. + // Next, it will look for root.posts.comments.show. Finally, + // it will look for `root.comments.show`, and find the state. + // + // After this process, the following variables will exist: + // + // * resolveState: a common parent state between the current + // and target state. In the above example, `` is the + // `resolveState`. + // * enterStates: a list of all of the states represented + // by the path from the `resolveState`. For example, for + // the path `root.comments.show`, `enterStates` would have + // `[, ]` + // * exitStates: a list of all of the states from the + // `resolveState` to the `currentState`. In the above + // example, `exitStates` would have + // `[`, `]`. + while (resolveState && !enterStates) { + exitStates.unshift(resolveState); + + resolveState = get(resolveState, 'parentState'); + if (!resolveState) { + enterStates = this.getStatesInPath(this, path); + if (!enterStates) { + Ember.assert('Could not find state for path: "'+path+'"'); + return; + } + } + enterStates = this.getStatesInPath(resolveState, path); + } + + // If the path contains some states that are parents of both the + // current state and the target state, remove them. + // + // For example, in the following hierarchy: + // + // |- root + // | |- post + // | | |- index (* current) + // | | |- show + // + // If the `path` is `root.post.show`, the three variables will + // be: + // + // * resolveState: `` + // * enterStates: `[, , ]` + // * exitStates: `[, , ]` + // + // The goal of this code is to remove the common states, so we + // have: + // + // * resolveState: `` + // * enterStates: `[]` + // * exitStates: `[]` + // + // This avoid unnecessary calls to the enter and exit transitions. + while (enterStates.length > 0 && enterStates[0] === exitStates[0]) { + resolveState = enterStates.shift(); + exitStates.shift(); + } + + // Cache the enterStates, exitStates, and resolveState for the + // current state and the `path`. + var transitions = currentState.pathsCache[path] = { + exitStates: exitStates, + enterStates: enterStates, + resolveState: resolveState + }; + + return transitions; + }, + + triggerSetupContext: function(transitions) { + var contexts = transitions.contexts, + offset = transitions.enterStates.length - contexts.length, + enterStates = transitions.enterStates, + transitionEvent = get(this, 'transitionEvent'); + + Ember.assert("More contexts provided than states", offset >= 0); + + arrayForEach.call(enterStates, function(state, idx) { + state.trigger(transitionEvent, this, contexts[idx-offset]); + }, this); + }, + + getState: function(name) { + var state = get(this, name), + parentState = get(this, 'parentState'); + + if (state) { + return state; + } else if (parentState) { + return parentState.getState(name); + } + }, + + enterState: function(transition) { + var log = this.enableLogging; + + var exitStates = transition.exitStates.slice(0).reverse(); + arrayForEach.call(exitStates, function(state) { + state.trigger('exit', this); + }, this); + + arrayForEach.call(transition.enterStates, function(state) { + if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); } + state.trigger('enter', this); + }, this); + + set(this, 'currentState', transition.finalState); + } +}); + +})(); + + + +(function() { +/** +Ember States + +@module ember +@submodule ember-states +@requires ember-runtime +*/ + +})(); + + +})(); +// Version: v1.0.0-rc.1 +// Last commit: 8b061b4 (2013-02-15 12:10:22 -0800) + + +(function() { +/** +Ember + +@module ember +*/ + +})(); + diff --git a/htdocs/portal/assets/js/ember-1.0.0-rc.1.min.js b/htdocs/portal/assets/js/ember-1.0.0-rc.1.min.js new file mode 100644 index 0000000000..f26eda777e --- /dev/null +++ b/htdocs/portal/assets/js/ember-1.0.0-rc.1.min.js @@ -0,0 +1,20 @@ +// ========================================================================== +// Project: Ember - JavaScript Application Framework +// Copyright: ©2011-2013 Tilde Inc. and contributors +// Portions ©2006-2011 Strobe Inc. +// Portions ©2008-2011 Apple Inc. All rights reserved. +// License: Licensed under MIT license +// See https://raw.github.com/emberjs/ember.js/master/LICENSE +// ========================================================================== + + +// Version: v1.0.0-rc.1 +// Last commit: 8b061b4 (2013-02-15 12:10:22 -0800) + + +(function(){var e,t;(function(){var n={},r={};e=function(e,t,r){n[e]={deps:t,callback:r}},t=function(e){if(r[e])return r[e];r[e]={};var i=n[e],s=i.deps,o=i.callback,u=[],a;for(var f=0,l=s.length;f=0&&n.push(e)}),n}}}(),function(){var e=function(e){return e&&Function.prototype.toString.call(e).indexOf("[native code]")>-1},t=e(Array.prototype.map)?Array.prototype.map:function(e){if(this===void 0||this===null)throw new TypeError;var t=Object(this),n=t.length>>>0;if(typeof e!="function")throw new TypeError;var r=new Array(n),i=arguments[1];for(var s=0;s>>0;if(typeof e!="function")throw new TypeError;var r=arguments[1];for(var i=0;i-1&&s.splice(o,1)},isEmpty:function(){return this.list.length===0},has:function(t){var n=e(t),r=this.presenceSet;return n in r},forEach:function(e,t){var n=this.list.slice();for(var r=0,i=n.length;r0?u=s.values[i]:u=n[i],u!==undefined||"object"!=typeof n||i in n||"function"!=typeof n.unknownProperty?u:n.unknownProperty(i))},n=function(n,i,s,o){typeof n=="string"&&(s=i,i=n,n=null);if(!n||i.indexOf(".")!==-1)return c(n,i,s,o);var u=n[e],a=u&&u.descs[i],f,l;return a?a.set(n,i,s):(f="object"==typeof n&&!(i in n),f&&"function"==typeof n.setUnknownProperty?n.setUnknownProperty(i,s):u&&u.watching[i]>0?(r?l=u.values[i]:l=n[i],s!==l&&(Ember.propertyWillChange(n,i),r?l!==undefined||i in n?u.values[i]=s:Ember.defineProperty(n,i,null,s):n[i]=s,Ember.propertyDidChange(n,i))):n[i]=s),s},Ember.config.overrideAccessors&&(Ember.get=t,Ember.set=n,Ember.config.overrideAccessors(),t=Ember.get,n=Ember.set),Ember.normalizeTuple=function(e,t){return f(e,t)},Ember.getWithDefault=function(e,n,r){var i=t(e,n);return i===undefined?r:i},Ember.get=t,Ember.getPath=Ember.deprecateFunc("getPath is deprecated since get now supports paths",Ember.get),Ember.set=n,Ember.setPath=Ember.deprecateFunc("setPath is deprecated since set now supports paths",Ember.set),Ember.trySet=function(e,t,r){return n(e,t,r,!0)},Ember.trySetPath=Ember.deprecateFunc("trySetPath has been renamed to trySet",Ember.trySet),Ember.isGlobalPath=function(e){return i.test(e)}}(),function(){var e=Ember.GUID_KEY,t=Ember.META_KEY,n=Ember.EMPTY_META,r=Ember.meta,i=Ember.create,s=Ember.platform.defineProperty,o=Ember.ENV.MANDATORY_SETTER,u=Ember.Descriptor=function(){},a=Ember.MANDATORY_SETTER_FUNCTION=function(e){},f=Ember.DEFAULT_GETTER_FUNCTION=function(e){return function(){var n=this[t];return n&&n.values[e]}};Ember.defineProperty=function(e,t,n,i,u){var l,c,h,p;return u||(u=r(e)),l=u.descs,c=u.descs[t],h=u.watching[t]>0,c instanceof Ember.Descriptor&&c.teardown(e,t),n instanceof Ember.Descriptor?(p=n,l[t]=n,o&&h?s(e,t,{configurable:!0,enumerable:!0,writable:!0,value:undefined}):e[t]=undefined,n.setup(e,t)):(l[t]=undefined,n==null?(p=i,o&&h?(u.values[t]=i,s(e,t,{configurable:!0,enumerable:!0,set:a,get:f(t)})):e[t]=i):(p=n,s(e,t,n))),h&&Ember.overrideChains(e,t,u),e.didDefineProperty&&e.didDefineProperty(e,t,p),this}}(),function(){function i(){this.clear()}function u(t){return t+e}function a(e){return e+t}var e=":change",t=":before",n=Ember.guidFor,r=0;i.prototype.add=function(e,t,n){var r=this.observerSet,i=this.observers,s=Ember.guidFor(e),o=r[s],u;return o||(r[s]=o={}),u=o[t],u===undefined&&(u=i.push({sender:e,keyName:t,eventName:n,listeners:[]})-1,o[t]=u),i[u].listeners},i.prototype.flush=function(){var e=this.observers,t,n,r,i;this.clear();for(t=0,n=e.length;t=0;s--)i[s].didChange(r)}function O(e,n,r){var i=t(e,!1),s=i.watching[n]>0||n==="length",o=i.proto,u=i.descs[n];if(!s)return;if(o===e)return;u&&u.willChange&&u.willChange(e,n),y(e,n,i),L(e,n,i),Ember.notifyBeforeObservers(e,n)}function M(e,n){var r=t(e,!1),i=r.watching[n]>0||n==="length",s=r.proto,o=r.descs[n];if(s===e)return;o&&o.didChange&&o.didChange(e,n);if(!i&&n!=="length")return;b(e,n,r),A(e,n,r),Ember.notifyObservers(e,n)}var e=Ember.guidFor,t=Ember.meta,n=Ember.get,r=Ember.set,i=Ember.normalizeTuple,s=Ember.GUID_KEY,o=Ember.META_KEY,u=Ember.notifyObservers,a=Ember.ArrayPolyfills.forEach,f=/^([^\.\*]+)/,l=/[\.\*]/,c=Ember.ENV.MANDATORY_SETTER,h=Ember.platform.defineProperty,m,g,S=[],N=function(e,t,n){var r;this._parent=e,this._key=t,this._watching=n===undefined,this._value=n,this._paths={},this._watching&&(this._object=e.value(),this._object&&w(this._object,this._key,this)),this._parent&&this._parent._key==="@each"&&this.value()},C=N.prototype;C.value=function(){if(this._value===undefined&&this._watching){var e=this._parent.value();this._value=e&&!T(e)?n(e,this._key):undefined}return this._value},C.destroy=function(){if(this._watching){var e=this._object;e&&E(e,this._key,this),this._watching=!1}},C.copy=function(e){var t=new N(null,null,e),n=this._paths,r;for(r in n){if(n[r]<=0)continue;t.add(r)}return t},C.add=function(e){var t,n,r,s,o;o=this._paths,o[e]=(o[e]||0)+1,t=this.value(),n=i(t,e);if(n[0]&&n[0]===t)e=n[1],r=p(e),e=e.slice(r.length+1);else{if(!n[0]){S.push([this,e]),n.length=0;return}s=n[0],r=e.slice(0,0-(n[1].length+1)),e=n[1]}n.length=0,this.chain(r,e,s)},C.remove=function(e){var t,n,r,s,o;o=this._paths,o[e]>0&&o[e]--,t=this.value(),n=i(t,e),n[0]===t?(e=n[1],r=p(e),e=e.slice(r.length+1)):(s=n[0],r=e.slice(0,0-(n[1].length+1)),e=n[1]),n.length=0,this.unchain(r,e)},C.count=0,C.chain=function(e,t,n){var r=this._chains,i;r||(r=this._chains={}),i=r[e],i||(i=r[e]=new N(this,e,n)),i.count++,t&&t.length>0&&(e=p(t),t=t.slice(e.length+1),i.chain(e,t))},C.unchain=function(e,t){var n=this._chains,r=n[e];t&&t.length>1&&(e=p(t),t=t.slice(e.length+1),r.unchain(e,t)),r.count--,r.count<=0&&(delete n[r._key],r.destroy())},C.willChange=function(){var e=this._chains;if(e)for(var t in e){if(!e.hasOwnProperty(t))continue;e[t].willChange()}this._parent&&this._parent.chainWillChange(this,this._key,1)},C.chainWillChange=function(e,t,n){this._key&&(t=this._key+"."+t),this._parent?this._parent.chainWillChange(this,t,n+1):(n>1&&Ember.propertyWillChange(this.value(),t),t="this."+t,this._paths[t]>0&&Ember.propertyWillChange(this.value(),t))},C.chainDidChange=function(e,t,n){this._key&&(t=this._key+"."+t),this._parent?this._parent.chainDidChange(this,t,n+1):(n>1&&Ember.propertyDidChange(this.value(),t),t="this."+t,this._paths[t]>0&&Ember.propertyDidChange(this.value(),t))},C.didChange=function(e){if(this._watching){var t=this._parent.value();t!==this._object&&(E(this._object,this._key,this),this._object=t,w(t,this._key,this)),this._value=undefined,this._parent&&this._parent._key==="@each"&&this.value()}var n=this._chains;if(n)for(var r in n){if(!n.hasOwnProperty(r))continue;n[r].didChange(e)}if(e)return;this._parent&&this._parent.chainDidChange(this,this._key,1)},Ember.overrideChains=function(e,t,n){A(e,t,n,!0)},Ember.watch=function(e,n){if(n==="length"&&Ember.typeOf(e)==="array")return this;var r=t(e),i=r.watching,s;return i[n]?i[n]=(i[n]||0)+1:(i[n]=1,d(n)?(s=r.descs[n],s&&s.willWatch&&s.willWatch(e,n),"function"==typeof e.willWatchProperty&&e.willWatchProperty(n),c&&n in e&&(r.values[n]=e[n],h(e,n,{configurable:!0,enumerable:!0,set:Ember.MANDATORY_SETTER_FUNCTION,get:Ember.DEFAULT_GETTER_FUNCTION(n)}))):k(e).add(n)),this},Ember.isWatching=function(t,n){var r=t[o];return(r&&r.watching[n])>0},Ember.watch.flushPending=x,Ember.unwatch=function(e,n){if(n==="length"&&Ember.typeOf(e)==="array")return this;var r=t(e),i=r.watching,s;return i[n]===1?(i[n]=0,d(n)?(s=r.descs[n],s&&s.didUnwatch&&s.didUnwatch(e,n),"function"==typeof e.didUnwatchProperty&&e.didUnwatchProperty(n),c&&n in e&&(h(e,n,{configurable:!0,enumerable:!0,writable:!0,value:r.values[n]}),delete r.values[n])):k(e).remove(n)):i[n]>1&&i[n]--,this},Ember.rewatch=function(e){var n=t(e,!1),r=n.chains;return s in e&&!e.hasOwnProperty(s)&&Ember.generateGuid(e,"ember"),r&&r.value()!==e&&(n.chains=r.copy(e)),this},Ember.finishChains=function(e){var n=t(e,!1),r=n.chains;r&&(r.value()!==e&&(n.chains=r=r.copy(e)),r.didChange(!0))},Ember.propertyWillChange=O,Ember.propertyDidChange=M;var _=[];Ember.destroy=function(e){var t=e[o],n,r,i,s;if(t){e[o]=null,n=t.chains;if(n){_.push(n);while(_.length>0){n=_.pop(),r=n._chains;if(r)for(i in r)r.hasOwnProperty(i)&&_.push(r[i]);n._watching&&(s=n._object,s&&E(s,n._key,n))}}}}}(),function(){function f(e,t,n){var r=t[n];return r?t.hasOwnProperty(n)||(r=t[n]=s(r)):r=t[n]={},r}function l(e,t){var n=t.deps;return n?t.hasOwnProperty("deps")||(n=t.deps=s(n)):n=t.deps={},n}function c(e,t,n,r){var i=e._dependentKeys,s,o,a,c,h;if(!i)return;s=l(t,r);for(o=0,a=i.length;o1&&(t=i.call(arguments,0,-1),e=i.call(arguments,-1)[0]);var n=new p(e);return t&&n.property.apply(n,t),n},Ember.cacheFor=function(t,r){var i=n(t,!1).cache;if(i&&r in i)return i[r]},Ember.computed.not=function(t){return Ember.computed(t,function(n){return!e(this,t)})},Ember.computed.empty=function(t){return Ember.computed(t,function(n){var r=e(this,t);return r===undefined||r===null||r===""||Ember.isArray(r)&&e(r,"length")===0})},Ember.computed.bool=function(t){return Ember.computed(t,function(n){return!!e(this,t)})},Ember.computed.alias=function(n){return Ember.computed(n,function(r,i){return arguments.length===1?e(this,n):(t(this,n,i),i)})}}(),function(){function i(e,t,n){var r=-1;for(var i=0,s=e.length;i=0;u--){var a=o[u][0],f=o[u][1],l=o[u][2],c=o[u][3],h=i(n,a,f);h===-1&&n.push([a,f,l,c])}}function u(e,t,n){var s=e[r],o=s&&s.listeners&&s.listeners[t],u=[];if(!o)return;for(var a=o.length-1;a>=0;a--){var f=o[a][0],l=o[a][1],c=o[a][2],h=o[a][3],p=i(n,f,l);if(p!==-1)continue;n.push([f,l,c,h]),u.push([f,l,c,h])}return u}function a(e,t,n,r,o){!r&&"function"==typeof n&&(r=n,n=null);var u=s(e,t),a=i(u,n,r);if(a!==-1)return;u.push([n,r,o,undefined]),"function"==typeof e.didAddListener&&e.didAddListener(t,n,r)}function f(e,t,n,o){function u(n,r,o){var u=s(e,t),a=i(u,n,r);if(a===-1)return;u.splice(a,1),"function"==typeof e.didRemoveListener&&e.didRemoveListener(t,n,r)}!o&&"function"==typeof n&&(o=n,n=null);if(o)u(n,o);else{var a=e[r],f=a&&a.listeners&&a.listeners[t];if(!f)return;for(var l=f.length-1;l>=0;l--)u(f[l][0],f[l][1])}}function l(e,t,n,r,o){function l(){return o.call(n)}function c(){f&&(f[3]=undefined)}!r&&"function"==typeof n&&(r=n,n=null);var u=s(e,t),a=i(u,n,r),f;return a!==-1&&(f=u[a].slice(),f[3]=!0,u[a]=f),Ember.tryFinally(l,c)}function c(e,t,n,r,o){function d(){return o.call(n)}function v(){for(c=0,h=u.length;c=0;o--){if(!i[o]||i[o][3]===!0)continue;var u=i[o][0],a=i[o][1],l=i[o][2];l&&f(e,t,u,a),u||(u=e),"string"==typeof a&&(a=u[a]),n?a.apply(u,n):a.apply(u)}return!0}function d(e,t){var n=e[r],i=n&&n.listeners&&n.listeners[t];return!!i&&!!i.length}function v(e,t){var n=[],i=e[r],s=i&&i.listeners&&i.listeners[t];if(!s)return n;for(var o=0,u=s.length;o0&&(r=r.length>i?e.call(r,i):null),Ember.handleErrors(function(){return n.apply(t||this,r||[])},this)}function u(){o=null,s.currentRunLoop&&s.end()}function l(){f=null;var e=+(new Date),t=-1;for(var r in a){if(!a.hasOwnProperty(r))continue;var i=a[r];if(i&&i.expires)if(e>=i.expires)delete a[r],n(i.target,i.method,i.args,2);else if(t<0||i.expires0&&(f=setTimeout(l,t- +(new Date)))}function c(e,t){t[this.tguid]&&delete t[this.tguid][this.mguid],a[e]&&n(this.target,this.method,this.args),delete a[e]}function h(e,t,n,r){var i=Ember.guidFor(t),o=Ember.guidFor(n),u=s.autorun().onceTimers,f=u[i]&&u[i][o],l;return f&&a[f]?a[f].args=r:(l={target:t,method:n,args:r,tguid:i,mguid:o},f=Ember.guidFor(l),a[f]=l,u[i]||(u[i]={}),u[i][o]=f,s.schedule(e,l,c,f,u)),f}function d(){p=null;for(var e in a){if(!a.hasOwnProperty(e))continue;var t=a[e];t.next&&(delete a[e],n(t.target,t.method,t.args,2))}}var e=[].slice,t=Ember.ArrayPolyfills.forEach,r,i=function(e){this._prev=e||null,this.onceTimers={}};i.prototype={end:function(){this.flush()},prev:function(){return this._prev},schedule:function(t,n,r){var i=this._queues,s;i||(i=this._queues={}),s=i[t],s||(s=i[t]=[]);var o=arguments.length>3?e.call(arguments,3):null;return s.push({target:n,method:r,args:o}),this},flush:function(e){function f(e){n(e.target,e.method,e.args)}function l(){t.call(u,f)}var i,s,o,u,a;if(!this._queues)return this;Ember.watch.flushPending();if(e)while(this._queues&&(u=this._queues[e]))this._queues[e]=null,e==="sync"?(a=Ember.LOG_BINDINGS,a&&Ember.Logger.log("Begin: Flush Sync Queue"),Ember.beginPropertyChanges(),Ember.tryFinally(l,Ember.endPropertyChanges),a&&Ember.Logger.log("End: Flush Sync Queue")):t.call(u,f);else{i=Ember.run.queues,o=i.length,s=0;e:while(s("+this._from+" -> "+this._to+")"+e},connect:function(e){var t=this._from,n=this._to;return Ember.trySet(e,n,i(e,t)),Ember.addObserver(e,t,this,this.fromDidChange),this._oneWay||Ember.addObserver(e,n,this,this.toDidChange),this._readyToSync=!0,this},disconnect:function(e){var t=!this._oneWay;return Ember.removeObserver(e,this._from,this,this.fromDidChange),t&&Ember.removeObserver(e,this._to,this,this.toDidChange),this._readyToSync=!1,this},fromDidChange:function(e){this._scheduleSync(e,"fwd")},toDidChange:function(e){this._scheduleSync(e,"back")},_scheduleSync:function(e,t){var n=this._directionMap,r=n.get(e);r||(Ember.run.schedule("sync",this,this._sync,e),n.set(e,t)),r==="back"&&t==="fwd"&&n.set(e,"fwd")},_sync:function(t){var n=Ember.LOG_BINDINGS;if(t.isDestroyed||!this._readyToSync)return;var r=this._directionMap,s=r.get(t),o=this._from,u=this._to;r.remove(t);if(s==="fwd"){var a=i(t,this._from);n&&Ember.Logger.log(" ",this.toString(),"->",a,t),this._oneWay?Ember.trySet(t,u,a):Ember._suspendObserver(t,u,this,this.toDidChange,function(){Ember.trySet(t,u,a)})}else if(s==="back"){var f=e(t,this._to);n&&Ember.Logger.log(" ",this.toString(),"<-",f,t),Ember._suspendObserver(t,o,this,this.fromDidChange,function(){Ember.trySet(Ember.isGlobalPath(o)?Ember.lookup:t,o,f)})}}},o(s,{from:function(){var e=this,t=new e;return t.from.apply(t,arguments)},to:function(){var e=this,t=new e;return t.to.apply(t,arguments)},oneWay:function(e,t){var n=this,r=new n(null,e);return r.oneWay(t)}}),Ember.Binding=s,Ember.bind=function(e,t,n){return(new Ember.Binding(t,n)).connect(e)},Ember.oneWay=function(e,t,n){return(new Ember.Binding(t,n)).oneWay().connect(e)}}(),function(){function c(e){var t=Ember.meta(e,!0),n=t.mixins;return n?t.hasOwnProperty("mixins")||(n=t.mixins=a(n)):n=t.mixins={},n}function h(t,n){return n&&n.length>0&&(t.mixins=r.call(n,function(t){if(t instanceof e)return t;var n=new e;return n.properties=t,n})),t}function p(e){return"function"==typeof e&&e.isMethod!==!1&&e!==Boolean&&e!==Object&&e!==Number&&e!==Array&&e!==Date&&e!==String}function v(t,n){var r;return n instanceof e?(r=l(n),t[r]?d:(t[r]=n,n.properties)):n}function m(e,t,n){var r;return r=t.concatenatedProperties||n.concatenatedProperties,e.concatenatedProperties&&(r=r?r.concat(e.concatenatedProperties):e.concatenatedProperties),r}function g(e,t,n,r,i){var s;return r[t]===undefined&&(s=i[t]),s=s||e.descs[t],!!s&&s instanceof Ember.ComputedProperty?(n=a(n),n.func=Ember.wrap(n.func,s.func),n):n}function y(e,t,n,r,i){var s;return i[t]===undefined&&(s=r[t]),s=s||e[t],"function"!=typeof s?n:Ember.wrap(n,s)}function b(e,t,n,r){var i=r[t]||e[t];return i?"function"==typeof i.concat?i.concat(n):Ember.makeArray(i).concat(n):Ember.makeArray(n)}function w(e,n,r,s,o,u,a){if(r instanceof Ember.Descriptor){if(r===t&&o[n])return d;r.func&&(r=g(s,n,r,u,o)),o[n]=r,u[n]=undefined}else{if(p(r))r=y(e,n,r,u,o);else if(a&&i.call(a,n)>=0||n==="concatenatedProperties")r=b(e,n,r,u);o[n]=undefined,u[n]=r}}function E(e,t,n,r,i){function c(e){delete n[e],delete r[e]}var o,u,a,f,l;for(var h=0,p=e.length;h=0)if(_(i[s],t,n))return!0;return!1}function D(e,t,n){if(n[l(t)])return;n[l(t)]=!0;if(t.properties){var r=t.properties;for(var i in r)r.hasOwnProperty(i)&&(e[i]=!0)}else t.mixins&&s.call(t.mixins,function(t){D(e,t,n)})}var e,t,n,r=Ember.ArrayPolyfills.map,i=Ember.ArrayPolyfills.indexOf,s=Ember.ArrayPolyfills.forEach,o=[].slice,u={},a=Ember.create,f=Ember.defineProperty,l=Ember.guidFor,d={},x=Ember.IS_BINDING=/^.+Binding$/;Ember.mixin=function(e){var t=o.call(arguments,1);return O(e,t,!1),e},Ember.Mixin=function(){return h(this,arguments)},e=Ember.Mixin,e._apply=O,e.applyPartial=function(e){var t=o.call(arguments,1);return O(e,t,!0)},e.finishPartial=C,Ember.anyUnprocessedMixins=!1,e.create=function(){Ember.anyUnprocessedMixins=!0;var e=this;return h(new e,arguments)};var M=e.prototype;M.reopen=function(){var t,n;this.properties?(t=e.create(),t.properties=this.properties,delete this.properties,this.mixins=[t]):this.mixins||(this.mixins=[]);var r=arguments.length,i=this.mixins,s;for(s=0;s=0)return s[u];if(Ember.typeOf(t)==="array"){o=t.slice();if(n){u=o.length;while(--u>=0)o[u]=i(o[u],n,r,s)}}else if(Ember.Copyable&&Ember.Copyable.detect(t))o=t.copy(n,r,s);else{o={};for(a in t){if(!t.hasOwnProperty(a))continue;if(a.substring(0,2)==="__")continue;o[a]=n?i(t[a],n,r,s):t[a]}}return n&&(r.push(t),s.push(o)),o}var e=Ember.EnumerableUtils.indexOf,t={},n="Boolean Number String Function Array Date RegExp Object".split(" ");Ember.ArrayPolyfills.forEach.call(n,function(e){t["[object "+e+"]"]=e.toLowerCase()});var r=Object.prototype.toString;Ember.typeOf=function(e){var n;return n=e===null||e===undefined?String(e):t[r.call(e)]||"object",n==="function"?Ember.Object&&Ember.Object.detect(e)&&(n="class"):n==="object"&&(e instanceof Error?n="error":Ember.Object&&e instanceof Ember.Object?n="instance":n="object"),n},Ember.isNone=function(e){return e===null||e===undefined},Ember.none=Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.",Ember.isNone),Ember.isEmpty=function(e){return e===null||e===undefined||e.length===0&&typeof e!="function"||typeof e=="object"&&Ember.get(e,"length")===0},Ember.empty=Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.",Ember.isEmpty),Ember.compare=function o(e,t){if(e===t)return 0;var n=Ember.typeOf(e),r=Ember.typeOf(t),i=Ember.Comparable;if(i){if(n==="instance"&&i.detect(e.constructor))return e.constructor.compare(e,t);if(r==="instance"&&i.detect(t.constructor))return 1-t.constructor.compare(t,e)}var s=Ember.ORDER_DEFINITION_MAPPING;if(!s){var u=Ember.ORDER_DEFINITION;s=Ember.ORDER_DEFINITION_MAPPING={};var a,f;for(a=0,f=u.length;ac)return 1;switch(n){case"boolean":case"number":if(et)return 1;return 0;case"string":var h=e.localeCompare(t);if(h<0)return-1;if(h>0)return 1;return 0;case"array":var p=e.length,d=t.length,v=Math.min(p,d),m=0,g=0;while(m===0&&gd)return 1;return 0;case"instance":if(Ember.Comparable&&Ember.Comparable.detect(e))return e.compare(e,t);return 0;case"date":var y=e.getTime(),b=t.getTime();if(yb)return 1;return 0;default:return 0}},Ember.copy=function(e,t){return"object"!=typeof e||e===null?e:Ember.Copyable&&Ember.Copyable.detect(e)?e.copy(t):i(e,t,t?[]:null,t?[]:null)},Ember.inspect=function(e){if(typeof e!="object"||e===null)return e+"";var t,n=[];for(var r in e)if(e.hasOwnProperty(r)){t=e[r];if(t==="toString")continue;Ember.typeOf(t)==="function"&&(t="function() { ... }"),n.push(r+": "+t)}return"{"+n.join(", ")+"}"},Ember.isEqual=function(e,t){return e&&"function"==typeof e.isEqual?e.isEqual(t):e===t},Ember.ORDER_DEFINITION=Ember.ENV.ORDER_DEFINITION||["undefined","null","boolean","number","string","array","object","instance","function","class","date"],Ember.keys=Object.keys,Ember.keys||(Ember.keys=function(e){var t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(n);return t});var s=["description","fileName","lineNumber","message","name","number","stack"];Ember.Error=function(){var e=Error.prototype.constructor.apply(this,arguments);for(var t=0;t1&&(t=n.call(arguments,1)),this.forEach(function(n,i){var s=n&&n[e];"function"==typeof s&&(r[i]=t?s.apply(n,t):s.call(n))},this),r},toArray:function(){var e=[];return this.forEach(function(t,n){e[n]=t}),e},compact:function(){return this.without(null)},without:function(e){if(!this.contains(e))return this;var t=[];return this.forEach(function(n){n!==e&&(t[t.length]=n)}),t},uniq:function(){var e=[];return this.forEach(function(t){r(e,t)<0&&e.push(t)}),e},"[]":Ember.computed(function(e,t){return this}),addEnumerableObserver:function(t,n){var r=n&&n.willChange||"enumerableWillChange",i=n&&n.didChange||"enumerableDidChange",s=e(this,"hasEnumerableObservers");return s||Ember.propertyWillChange(this,"hasEnumerableObservers"),Ember.addListener(this,"@enumerable:before",t,r),Ember.addListener(this,"@enumerable:change",t,i),s||Ember.propertyDidChange(this,"hasEnumerableObservers"),this},removeEnumerableObserver:function(t,n){var r=n&&n.willChange||"enumerableWillChange",i=n&&n.didChange||"enumerableDidChange",s=e(this,"hasEnumerableObservers");return s&&Ember.propertyWillChange(this,"hasEnumerableObservers"),Ember.removeListener(this,"@enumerable:before",t,r),Ember.removeListener(this,"@enumerable:change",t,i),s&&Ember.propertyDidChange(this,"hasEnumerableObservers"),this},hasEnumerableObservers:Ember.computed(function(){return Ember.hasListeners(this,"@enumerable:change")||Ember.hasListeners(this,"@enumerable:before")}),enumerableContentWillChange:function(t,n){var r,i,s;return"number"==typeof t?r=t:t?r=e(t,"length"):r=t=-1,"number"==typeof n?i=n:n?i=e(n,"length"):i=n=-1,s=i<0||r<0||i-r!==0,t===-1&&(t=null),n===-1&&(n=null),Ember.propertyWillChange(this,"[]"),s&&Ember.propertyWillChange(this,"length"),Ember.sendEvent(this,"@enumerable:before",[this,t,n]),this},enumerableContentDidChange:function(t,n){var r=this.propertyDidChange,i,s,o;return"number"==typeof t?i=t:t?i=e(t,"length"):i=t=-1,"number"==typeof n?s=n:n?s=e(n,"length"):s=n=-1,o=s<0||i<0||s-i!==0,t===-1&&(t=null),n===-1&&(n=null),Ember.sendEvent(this,"@enumerable:change",[this,t,n]),o&&Ember.propertyDidChange(this,"length"),Ember.propertyDidChange(this,"[]"),this}})}(),function(){function s(e){return e===null||e===undefined}var e=Ember.get,t=Ember.set,n=Ember.meta,r=Ember.EnumerableUtils.map,i=Ember.cacheFor;Ember.Array=Ember.Mixin.create(Ember.Enumerable,{isSCArray:!0,length:Ember.required(),objectAt:function(t){return t<0||t>=e(this,"length")?undefined:e(this,t)},objectsAt:function(e){var t=this;return r(e,function(e){return t.objectAt(e)})},nextObject:function(e){return this.objectAt(e)},"[]":Ember.computed(function(t,n){return n!==undefined&&this.replace(0,e(this,"length"),n),this}),firstObject:Ember.computed(function(){return this.objectAt(0)}),lastObject:Ember.computed(function(){return this.objectAt(e(this,"length")-1)}),contains:function(e){return this.indexOf(e)>=0},slice:function(t,n){var r=[],i=e(this,"length");s(t)&&(t=0);if(s(n)||n>i)n=i;while(t=i)n=i-1;n<0&&(n+=i);for(r=n;r>=0;r--)if(this.objectAt(r)===t)return r;return-1},addArrayObserver:function(t,n){var r=n&&n.willChange||"arrayWillChange",i=n&&n.didChange||"arrayDidChange",s=e(this,"hasArrayObservers");return s||Ember.propertyWillChange(this,"hasArrayObservers"),Ember.addListener(this,"@array:before",t,r),Ember.addListener(this,"@array:change",t,i),s||Ember.propertyDidChange(this,"hasArrayObservers"),this},removeArrayObserver:function(t,n){var r=n&&n.willChange||"arrayWillChange",i=n&&n.didChange||"arrayDidChange",s=e(this,"hasArrayObservers");return s&&Ember.propertyWillChange(this,"hasArrayObservers"),Ember.removeListener(this,"@array:before",t,r),Ember.removeListener(this,"@array:change",t,i),s&&Ember.propertyDidChange(this,"hasArrayObservers"),this},hasArrayObservers:Ember.computed(function(){return Ember.hasListeners(this,"@array:change")||Ember.hasListeners(this,"@array:before")}),arrayContentWillChange:function(t,n,r){t===undefined?(t=0,n=r=-1):(n===undefined&&(n=-1),r===undefined&&(r=-1)),Ember.isWatching(this,"@each")&&e(this,"@each"),Ember.sendEvent(this,"@array:before",[this,t,n,r]);var i,s;if(t>=0&&n>=0&&e(this,"hasEnumerableObservers")){i=[],s=t+n;for(var o=t;o=0&&r>=0&&e(this,"hasEnumerableObservers")){s=[],o=t+r;for(var u=t;un(this,"length"))throw new Error(e);return this.replace(t,0,[r]),this},removeAt:function(r,i){if("number"==typeof r){if(r<0||r>=n(this,"length"))throw new Error(e);i===undefined&&(i=1),this.replace(r,i,t)}return this},pushObject:function(e){return this.insertAt(n(this,"length"),e),e},pushObjects:function(e){return this.replace(n(this,"length"),0,e),this},popObject:function(){var e=n(this,"length");if(e===0)return null;var t=this.objectAt(e-1);return this.removeAt(e-1,1),t},shiftObject:function(){if(n(this,"length")===0)return null;var e=this.objectAt(0);return this.removeAt(0),e},unshiftObject:function(e){return this.insertAt(0,e),e},unshiftObjects:function(e){return this.replace(0,0,e),this},reverseObjects:function(){var e=n(this,"length");if(e===0)return this;var t=this.toArray().reverse();return this.replace(0,e,t),this},setObjects:function(e){if(e.length===0)return this.clear();var t=n(this,"length");return this.replace(0,t,e),this},removeObject:function(e){var t=n(this,"length")||0;while(--t>=0){var r=this.objectAt(t);r===e&&this.removeAt(t)}return this},addObject:function(e){return this.contains(e)||this.pushObject(e),this}})}(),function(){var e=Ember.get,t=Ember.set,n=Ember.defineProperty;Ember.Observable=Ember.Mixin.create({get:function(t){return e(this,t)},getProperties:function(){var t={},n=arguments;arguments.length===1&&Ember.typeOf(arguments[0])==="array"&&(n=arguments[0]);for(var r=0;r=0){var N=this[w];N?"function"==typeof N.concat?E=N.concat(E):E=Ember.makeArray(N).concat(E):E=Ember.makeArray(E)}T?T.set(this,w,E):typeof this.setUnknownProperty!="function"||w in this?g?Ember.defineProperty(this,w,null,E):this[w]=E:this.setUnknownProperty(w,E)}}}v(this,u),delete u.proto,l(this),this.init.apply(this,arguments)};return o.toString=p.prototype.toString,o.willReopen=function(){e&&(o.PrototypeMixin=p.create(o.PrototypeMixin)),e=!1},o._initMixins=function(e){t=e},o._initProperties=function(e){i=e},o.proto=function(){var t=o.superclass;return t&&t.proto(),e||(e=!0,o.PrototypeMixin.applyPartial(o.prototype),f(o.prototype)),this.prototype},o}function S(e){return function(){return e}}var e=Ember.set,t=Ember.get,n=Ember.create,r=Ember.platform.defineProperty,i=Array.prototype.slice,s=Ember.GUID_KEY,o=Ember.guidFor,u=Ember.generateGuid,a=Ember.meta,f=Ember.rewatch,l=Ember.finishChains,c=Ember.destroy,h=Ember.run.schedule,p=Ember.Mixin,d=p._apply,v=p.finishPartial,m=p.prototype.reopen,g=Ember.ENV.MANDATORY_SETTER,y=Ember.EnumerableUtils.indexOf,b={configurable:!0,writable:!0,enumerable:!1,value:undefined},E=w();E.toString=function(){return"Ember.CoreObject"},E.PrototypeMixin=p.create({reopen:function(){return d(this,arguments,!0),this},isInstance:!0,init:function(){},concatenatedProperties:null,isDestroyed:!1,isDestroying:!1,destroy:function(){if(this._didCallDestroy)return;return this.isDestroying=!0,this._didCallDestroy=!0,this.willDestroy&&this.willDestroy(),h("destroy",this,this._scheduledDestroy),this},_scheduledDestroy:function(){c(this),e(this,"isDestroyed",!0),this.didDestroy&&this.didDestroy()},bind:function(e,t){return t instanceof Ember.Binding||(t=Ember.Binding.from(t)),t.to(e).connect(this),t},toString:function T(){var e=typeof this.toStringExtension=="function",t=e?":"+this.toStringExtension():"",n="<"+this.constructor.toString()+":"+o(this)+t+">";return this.toString=S(n),n}}),E.PrototypeMixin.ownerConstructor=E,Ember.config.overridePrototypeMixin&&Ember.config.overridePrototypeMixin(E.PrototypeMixin),E.__super__=null;var x=p.create({ClassMixin:Ember.required(),PrototypeMixin:Ember.required(),isClass:!0,isMethod:!1,extend:function(){var e=w(),t;return e.ClassMixin=p.create(this.ClassMixin),e.PrototypeMixin=p.create(this.PrototypeMixin),e.ClassMixin.ownerConstructor=e,e.PrototypeMixin.ownerConstructor=e,m.apply(e.PrototypeMixin,arguments),e.superclass=this,e.__super__=this.prototype,t=e.prototype=n(this.prototype),t.constructor=e,u(t,"ember"),a(t).proto=t,e.ClassMixin.apply(e),e},createWithMixins:function(){var e=this;return arguments.length>0&&this._initMixins(arguments),new e},create:function(){var e=this;return arguments.length>0&&this._initProperties(arguments),new e},reopen:function(){return this.willReopen(),m.apply(this.PrototypeMixin,arguments),this},reopenClass:function(){return m.apply(this.ClassMixin,arguments),d(this,arguments,!1),this},detect:function(e){if("function"!=typeof e)return!1;while(e){if(e===this)return!0;e=e.superclass}return!1},detectInstance:function(e){return e instanceof this},metaForProperty:function(e){var t=a(this.proto(),!1).descs[e];return t._meta||{}},eachComputedProperty:function(e,t){var n=this.proto(),r=a(n).descs,i={},s;for(var o in r)s=r[o],s instanceof Ember.ComputedProperty&&e.call(t||this,o,s._meta||i)}});x.ownerConstructor=E,Ember.config.overrideClassMixin&&Ember.config.overrideClassMixin(x),E.ClassMixin=x,x.apply(E),Ember.CoreObject=E}(),function(){var e=Ember.get,t=Ember.set,n=Ember.guidFor,r=Ember.isNone;Ember.Set=Ember.CoreObject.extend(Ember.MutableEnumerable,Ember.Copyable,Ember.Freezable,{length:0,clear:function(){if(this.isFrozen)throw new Error(Ember.FROZEN_ERROR);var r=e(this,"length");if(r===0)return this;var i;this.enumerableContentWillChange(r,0),Ember.propertyWillChange(this,"firstObject"),Ember.propertyWillChange(this,"lastObject");for(var s=0;s=0)if(!t.contains(this[n]))return!1;return!0},add:Ember.aliasMethod("addObject"),remove:Ember.aliasMethod("removeObject"),pop:function(){if(e(this,"isFrozen"))throw new Error(Ember.FROZEN_ERROR);var t=this.length>0?this[this.length-1]:null;return this.remove(t),t},push:Ember.aliasMethod("addObject"),shift:Ember.aliasMethod("pop"),unshift:Ember.aliasMethod("push"),addEach:Ember.aliasMethod("addObjects"),removeEach:Ember.aliasMethod("removeObjects"),init:function(e){this._super(),e&&this.addObjects(e)},nextObject:function(e){return this[e]},firstObject:Ember.computed(function(){return this.length>0?this[0]:undefined}),lastObject:Ember.computed(function(){return this.length>0?this[this.length-1]:undefined}),addObject:function(i){if(e(this,"isFrozen"))throw new Error(Ember.FROZEN_ERROR);if(r(i))return this;var s=n(i),o=this[s],u=e(this,"length"),a;return o>=0&&o=0&&o=0},copy:function(){var r=this.constructor,i=new r,s=e(this,"length");t(i,"length",s);while(--s>=0)i[s]=this[s],i[n(this[s])]=s;return i},toString:function(){var e=this.length,t,n=[];for(t=0;t".fmt(n.join(","))}})}(),function(){Ember.Object=Ember.CoreObject.extend(Ember.Observable),Ember.Object.toString=function(){return"Ember.Object"}}(),function(){function o(e,t,n){var u=e.length;r[e.join(".")]=t;for(var f in t){if(!i.call(t,f))continue;var c=t[f];e[u]=f;if(c&&c.toString===l)c.toString=h(e.join(".")),c[a]=e.join(".");else if(c&&c.isNamespace){if(n[s(c)])continue;n[s(c)]=!0,o(e,c,n)}}e.length=u}function u(){var e=Ember.Namespace,t=Ember.lookup,n,r;if(e.PROCESSED)return;for(var i in t){if(i==="parent"||i==="top"||i==="frameElement")continue;if(i==="globalStorage"&&t.StorageList&&t.globalStorage instanceof t.StorageList)continue;if(t.hasOwnProperty&&!t.hasOwnProperty(i))continue;try{n=Ember.lookup[i],r=n&&n.isNamespace}catch(s){continue}r&&(n[a]=i)}}function f(e){var t=e.superclass;if(t)return t[a]?t[a]:f(t);return}function l(){!Ember.BOOTED&&!this[a]&&c();var e;if(this[a])e=this[a];else{var t=f(this);t?e="(subclass of "+t+")":e="(unknown mixin)",this.toString=h(e)}return e}function c(){var e=!n.PROCESSED,t=Ember.anyUnprocessedMixins;e&&(u(),n.PROCESSED=!0);if(e||t){var r=n.NAMESPACES,i;for(var s=0,a=r.length;s=i){var a=e.objectAt(s);a&&(Ember.addBeforeObserver(a,t,r,"contentKeyWillChange"),Ember.addObserver(a,t,r,"contentKeyDidChange"),u=n(a),o[u]||(o[u]=[]),o[u].push(s))}}function u(e,t,r,i,s){var o=r._objects;o||(o=r._objects={});var u,a;while(--s>=i){var f=e.objectAt(s);f&&(Ember.removeBeforeObserver(f,t,r,"contentKeyWillChange"),Ember.removeObserver(f,t,r,"contentKeyDidChange"),a=n(f),u=o[a],u[u.indexOf(s)]=null)}}var e=Ember.set,t=Ember.get,n=Ember.guidFor,r=Ember.EnumerableUtils.forEach,i=Ember.Object.extend(Ember.Array,{init:function(e,t,n){this._super(),this._keyName=t,this._owner=n,this._content=e},objectAt:function(e){var n=this._content.objectAt(e);return n&&t(n,this._keyName)},length:Ember.computed(function(){var e=this._content;return e?t(e,"length"):0})}),s=/^.+:(before|change)$/;Ember.EachProxy=Ember.Object.extend({init:function(e){this._super(),this._content=e,e.addArrayObserver(this),r(Ember.watchedEvents(this),function(e){this.didAddListener(e)},this)},unknownProperty:function(e,t){var n;return n=new i(this._content,e,this),Ember.defineProperty(this,e,null,n),this.beginObservingContentKey(e),n},arrayWillChange:function(e,t,n,r){var i=this._keys,s,o,a;a=n>0?t+n:-1,Ember.beginPropertyChanges(this);for(s in i){if(!i.hasOwnProperty(s))continue;a>0&&u(e,s,this,t,a),Ember.propertyWillChange(this,s)}Ember.propertyWillChange(this._content,"@each"),Ember.endPropertyChanges(this)},arrayDidChange:function(e,t,n,r){var i=this._keys,s,u,a;a=r>0?t+r:-1,Ember.beginPropertyChanges(this);for(s in i){if(!i.hasOwnProperty(s))continue;a>0&&o(e,s,this,t,a),Ember.propertyDidChange(this,s)}Ember.propertyDidChange(this._content,"@each"),Ember.endPropertyChanges(this)},didAddListener:function(e){s.test(e)&&this.beginObservingContentKey(e.slice(0,-7))},didRemoveListener:function(e){s.test(e)&&this.stopObservingContentKey(e.slice(0,-7))},beginObservingContentKey:function(e){var n=this._keys;n||(n=this._keys={});if(!n[e]){n[e]=1;var r=this._content,i=t(r,"length");o(r,e,this,0,i)}else n[e]++},stopObservingContentKey:function(e){var n=this._keys;if(n&&n[e]>0&&--n[e]<=0){var r=this._content,i=t(r,"length");u(r,e,this,0,i)}},contentKeyWillChange:function(e,t){Ember.propertyWillChange(this,t)},contentKeyDidChange:function(e,t){Ember.propertyDidChange(this,t)}})}(),function(){var e=Ember.get,t=Ember.set,n=Ember.Mixin.create(Ember.MutableArray,Ember.Observable,Ember.Copyable,{get:function(e){return e==="length"?this.length:"number"==typeof e?this[e]:this._super(e)},objectAt:function(e){return this[e]},replace:function(t,n,r){if(this.isFrozen)throw Ember.FROZEN_ERROR;var i=r?e(r,"length"):0;this.arrayContentWillChange(t,n,i);if(!r||r.length===0)this.splice(t,n);else{var s=[t,n].concat(r);this.splice.apply(this,s)}return this.arrayContentDidChange(t,n,i),this},unknownProperty:function(e,t){var n;return t!==undefined&&n===undefined&&(n=this[e]=t),n},indexOf:function(e,t){var n,r=this.length;t===undefined?t=0:t=t<0?Math.ceil(t):Math.floor(t),t<0&&(t+=r);for(n=t;n=0;n--)if(this[n]===e)return n;return-1},copy:function(e){return e?this.map(function(e){return Ember.copy(e,!0)}):this.slice()}}),r=["length"];Ember.EnumerableUtils.forEach(n.keys(),function(e){Array.prototype[e]&&r.push(e)}),r.length>0&&(n=n.without.apply(n,r)),Ember.NativeArray=n,Ember.A=function(e){return e===undefined&&(e=[]),Ember.Array.detect(e)?e:Ember.NativeArray.apply(e)},Ember.NativeArray.activate=function(){n.apply(Array.prototype),Ember.A=function(e){return e||[]}},(Ember.EXTEND_PROTOTYPES===!0||Ember.EXTEND_PROTOTYPES.Array)&&Ember.NativeArray.activate()}(),function(){var e=Ember.DeferredMixin,t=Ember.Object,n=Ember.get,r=Ember.Object.extend(e);r.reopenClass({promise:function(e,t){var i=r.create();return e.call(t,i),n(i,"promise")}}),Ember.Deferred=r}(),function(){var e=Ember.ENV.EMBER_LOAD_HOOKS||{},t={};Ember.onLoad=function(n,r){var i;e[n]=e[n]||Ember.A(),e[n].pushObject(r),(i=t[n])&&r(i)},Ember.runLoadHooks=function(n,r){var i;t[n]=r,(i=e[n])&&e[n].forEach(function(e){e(r)})}}(),function(){}(),function(){var e=Ember.get;Ember.ControllerMixin=Ember.Mixin.create({isController:!0,target:null,container:null,store:null,model:Ember.computed.alias("content"),send:function(t){var n=[].slice.call(arguments,1),r;this[t]?this[t].apply(this,n):(r=e(this,"target"))&&r.send.apply(r,arguments)}}),Ember.Controller=Ember.Object.extend(Ember.ControllerMixin)}(),function(){var e=Ember.get,t=Ember.set,n=Ember.EnumerableUtils.forEach;Ember.SortableMixin=Ember.Mixin.create(Ember.MutableEnumerable,{sortProperties:null,sortAscending:!0,orderBy:function(t,r){var i=0,s=e(this,"sortProperties"),o=e(this,"sortAscending");return n(s,function(n){i===0&&(i=Ember.compare(e(t,n),e(r,n)),i!==0&&!o&&(i=-1*i))}),i},destroy:function(){var t=e(this,"content"),r=e(this,"sortProperties");return t&&r&&n(t,function(e){n(r,function(t){Ember.removeObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this),this._super()},isSorted:Ember.computed.bool("sortProperties"),arrangedContent:Ember.computed("content","sortProperties.@each",function(t,r){var i=e(this,"content"),s=e(this,"isSorted"),o=e(this,"sortProperties"),u=this;return i&&s?(i=i.slice(),i.sort(function(e,t){return u.orderBy(e,t)}),n(i,function(e){n(o,function(t){Ember.addObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this),Ember.A(i)):i}),_contentWillChange:Ember.beforeObserver(function(){var t=e(this,"content"),r=e(this,"sortProperties");t&&r&&n(t,function(e){n(r,function(t){Ember.removeObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this),this._super()},"content"),sortAscendingWillChange:Ember.beforeObserver(function(){this._lastSortAscending=e(this,"sortAscending")},"sortAscending"),sortAscendingDidChange:Ember.observer(function(){if(e(this,"sortAscending")!==this._lastSortAscending){var t=e(this,"arrangedContent");t.reverseObjects()}},"sortAscending"),contentArrayWillChange:function(t,r,i,s){var o=e(this,"isSorted");if(o){var u=e(this,"arrangedContent"),a=t.slice(r,r+i),f=e(this,"sortProperties");n(a,function(e){u.removeObject(e),n(f,function(t){Ember.removeObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this)}return this._super(t,r,i,s)},contentArrayDidChange:function(t,r,i,s){var o=e(this,"isSorted"),u=e(this,"sortProperties");if(o){var a=t.slice(r,r+s),f=e(this,"arrangedContent");n(a,function(e){this.insertItemSorted(e),n(u,function(t){Ember.addObserver(e,t,this,"contentItemSortPropertyDidChange")},this)},this)}return this._super(t,r,i,s)},insertItemSorted:function(t){var n=e(this,"arrangedContent"),r=e(n,"length"),i=this._binarySearch(t,0,r);n.insertAt(i,t)},contentItemSortPropertyDidChange:function(t){var n=e(this,"arrangedContent"),r=n.indexOf(t),i=n.objectAt(r-1),s=n.objectAt(r+1),o=i&&this.orderBy(t,i),u=s&&this.orderBy(t,s);if(o<0||u>0)n.removeObject(t),this.insertItemSorted(t)},_binarySearch:function(t,n,r){var i,s,o,u;return n===r?n:(u=e(this,"arrangedContent"),i=n+Math.floor((r-n)/2),s=u.objectAt(i),o=this.orderBy(s,t),o<0?this._binarySearch(t,i+1,r):o>0?this._binarySearch(t,n,i):i)}})}(),function(){var e=Ember.get,t=Ember.set,n=Ember.isGlobalPath,r=Ember.EnumerableUtils.forEach,i=Ember.EnumerableUtils.replace;Ember.ArrayController=Ember.ArrayProxy.extend(Ember.ControllerMixin,Ember.SortableMixin,{itemController:null,lookupItemController:function(t){return e(this,"itemController")},objectAtContent:function(t){var n=e(this,"length"),r=e(this,"arrangedContent").objectAt(t);if(t>=0&&t1;return!t&&!n}var e=function(){var e=document.createElement("div");return e.innerHTML="
",e.firstChild.innerHTML="",e.firstChild.innerHTML===""}(),t=function(){var e=document.createElement("div");return e.innerHTML="Test: Value",e.childNodes[0].nodeValue==="Test:"&&e.childNodes[2].nodeValue===" Value"}(),n=function(e,t){if(e.getAttribute("id")===t)return e;var r=e.childNodes.length,i,s,o;for(i=0;i0){var o=s.length,u;for(u=0;uTest'),t=n.options.length===1}return i[e]=t,t},o=function(e,t){var n=e.tagName;if(s(n))r(e,t);else{var i=e.outerHTML.match(new RegExp("<"+n+"([^>]*)>","i"))[0],o="",u=document.createElement("div");r(u,i+t+o),e=u.firstChild;while(e.tagName!==n)e=e.nextSibling}return e};Ember.ViewUtils={setInnerHTML:o,isSimpleClick:u}}(),function(){var e=Ember.get,t=Ember.set,n=Ember.ArrayPolyfills.indexOf,r=function(){this.seen={},this.list=[]};r.prototype={add:function(e){if(e in this.seen)return;this.seen[e]=!0,this.list.push(e)},toDOM:function(){return this.list.join(" ")}},Ember.RenderBuffer=function(e){return new Ember._RenderBuffer(e)},Ember._RenderBuffer=function(e){this.tagNames=[e||null],this.buffer=[]},Ember._RenderBuffer.prototype={_element:null,elementClasses:null,classes:null,elementId:null,elementAttributes:null,elementProperties:null,elementTag:null,elementStyle:null,parentBuffer:null,push:function(e){return this.buffer.push(e),this},addClass:function(e){var t=this.elementClasses=this.elementClasses||new r;return this.elementClasses.add(e),this.classes=this.elementClasses.list,this},setClasses:function(e){this.classes=e},id:function(e){return this.elementId=e,this},attr:function(e,t){var n=this.elementAttributes=this.elementAttributes||{};return arguments.length===1?n[e]:(n[e]=t,this)},removeAttr:function(e){var t=this.elementAttributes;return t&&delete t[e],this},prop:function(e,t){var n=this.elementProperties=this.elementProperties||{};return arguments.length===1?n[e]:(n[e]=t,this)},removeProp:function(e){var t=this.elementProperties;return t&&delete t[e],this},style:function(e,t){var n=this.elementStyle=this.elementStyle||{};return this.elementStyle[e]=t,this},begin:function(e){return this.tagNames.push(e||null),this},pushOpeningTag:function(){var e=this.currentTagName();if(!e)return;if(!this._element&&this.buffer.length===0){this._element=this.generateElement();return}var t=this.buffer,n=this.elementId,r=this.classes,i=this.elementAttributes,s=this.elementProperties,o=this.elementStyle,u,a;t.push("<"+e),n&&(t.push(' id="'+this._escapeAttribute(n)+'"'),this.elementId=null),r&&(t.push(' class="'+this._escapeAttribute(r.join(" "))+'"'),this.classes=null);if(o){t.push(' style="');for(a in o)o.hasOwnProperty(a)&&t.push(a+":"+this._escapeAttribute(o[a])+";");t.push('"'),this.elementStyle=null}if(i){for(u in i)i.hasOwnProperty(u)&&t.push(" "+u+'="'+this._escapeAttribute(i[u])+'"');this.elementAttributes=null}if(s){for(a in s)if(s.hasOwnProperty(a)){var f=s[a];if(f||typeof f=="number")f===!0?t.push(" "+a+'="'+a+'"'):t.push(" "+a+'="'+this._escapeAttribute(s[a])+'"')}this.elementProperties=null}t.push(">")},pushClosingTag:function(){var e=this.tagNames.pop();e&&this.buffer.push("")},currentTagName:function(){return this.tagNames[this.tagNames.length-1]},generateElement:function(){var e=this.tagNames.pop(),t=document.createElement(e),n=Ember.$(t),r=this.elementId,i=this.classes,s=this.elementAttributes,o=this.elementProperties,u=this.elementStyle,a="",f,l;r&&(n.attr("id",r),this.elementId=null),i&&(n.attr("class",i.join(" ")),this.classes=null);if(u){for(l in u)u.hasOwnProperty(l)&&(a+=l+":"+u[l]+";");n.attr("style",a),this.elementStyle=null}if(s){for(f in s)s.hasOwnProperty(f)&&n.attr(f,s[f]);this.elementAttributes=null}if(o){for(l in o)o.hasOwnProperty(l)&&n.prop(l,o[l]);this.elementProperties=null}return t},element:function(){var e=this.innerString();return e&&(this._element=Ember.ViewUtils.setInnerHTML(this._element,e)),this._element},string:function(){return this._element?this.element().outerHTML:this.innerString()},innerString:function(){return this.buffer.join("")},_escapeAttribute:function(e){var t={"<":"<",">":">",'"':""","'":"'","`":"`"},n=/&(?!\w+;)|[<>"'`]/g,r=/[&<>"'`]/,i=function(e){return t[e]||"&"},s=e.toString();return r.test(s)?s.replace(n,i):s}}}(),function(){var e=Ember.get,t=Ember.set,n=Ember.String.fmt;Ember.EventDispatcher=Ember.Object.extend({rootElement:"body",setup:function(t){var n,r={touchstart:"touchStart",touchmove:"touchMove",touchend:"touchEnd",touchcancel:"touchCancel",keydown:"keyDown",keyup:"keyUp",keypress:"keyPress",mousedown:"mouseDown",mouseup:"mouseUp",contextmenu:"contextMenu",click:"click",dblclick:"doubleClick",mousemove:"mouseMove",focusin:"focusIn",focusout:"focusOut",mouseenter:"mouseEnter",mouseleave:"mouseLeave",submit:"submit",input:"input",change:"change",dragstart:"dragStart",drag:"drag",dragenter:"dragEnter",dragleave:"dragLeave",dragover:"dragOver",drop:"drop",dragend:"dragEnd"};Ember.$.extend(r,t||{});var i=Ember.$(e(this,"rootElement"));i.addClass("ember-application");for(n in r)r.hasOwnProperty(n)&&this.setupHandler(i,n,r[n])},setupHandler:function(e,t,n){var r=this;e.delegate(".ember-view",t+".ember",function(e,t){return Ember.handleErrors(function(){var i=Ember.View.views[this.id],s=!0,o=null;return o=r._findNearestEventManager(i,n),o&&o!==t?s=r._dispatchEvent(o,e,n,i):i?s=r._bubbleEvent(i,e,n):e.stopPropagation(),s},this)}),e.delegate("[data-ember-action]",t+".ember",function(e){return Ember.handleErrors(function(){var t=Ember.$(e.currentTarget).attr("data-ember-action"),r=Ember.Handlebars.ActionHelper.registeredActions[t];if(r&&r.eventName===n)return r.handler(e)},this)})},_findNearestEventManager:function(t,n){var r=null;while(t){r=e(t,"eventManager");if(r&&r[n])break;t=e(t,"parentView")}return r},_dispatchEvent:function(e,t,n,r){var i=!0,s=e[n];return Ember.typeOf(s)==="function"?(i=s.call(e,t,r),t.stopPropagation()):i=this._bubbleEvent(r,t,n),i},_bubbleEvent:function(e,t,n){return Ember.run(function(){return e.handleEvent(n,t)})},destroy:function(){var t=e(this,"rootElement");return Ember.$(t).undelegate(".ember").removeClass("ember-application"),this._super()}})}(),function(){var e=Ember.run.queues;e.splice(Ember.$.inArray("actions",e)+1,0,"render","afterRender")}(),function(){var e=Ember.get,t=Ember.set;Ember.ControllerMixin.reopen({target:null,namespace:null,view:null,container:null,_childContainers:null,init:function(){this._super(),t(this,"_childContainers",{})},_modelDidChange:Ember.observer(function(){var n=e(this,"_childContainers"),r;for(var i in n){if(!n.hasOwnProperty(i))continue;n[i].destroy()}t(this,"_childContainers",{})},"model")})}(),function(){}(),function(){var e={},t=Ember.get,n=Ember.set,r=Ember.addObserver,i=Ember.removeObserver,s=Ember.meta,o=Ember.guidFor,u=Ember.String.fmt,a=[].slice,f=Ember.EnumerableUtils.forEach,l=Ember.EnumerableUtils.addObject,c=Ember.computed(function(){var e=this._childViews,n=Ember.A(),r=this;return f(e,function(e){e.isVirtual?n.pushObjects(t(e,"childViews")):n.push(e)}),n.replace=function(e,t,n){if(r instanceof Ember.ContainerView)return r.replace(e,t,n);throw new Error("childViews is immutable")},n});Ember.TEMPLATES={},Ember.CoreView=Ember.Object.extend(Ember.Evented,{isView:!0,states:e,init:function(){this._super(),this.isVirtual||(Ember.View.views[this.elementId]=this),this.addBeforeObserver("elementId",function(){throw new Error("Changing a view's elementId after creation is not allowed")}),this.transitionTo("preRender")},parentView:Ember.computed(function(){var e=this._parentView;return e&&e.isVirtual?t(e,"parentView"):e}).property("_parentView"),state:null,_parentView:null,concreteView:Ember.computed(function(){return this.isVirtual?t(this,"parentView"):this}).property("parentView").volatile(),instrumentName:"core_view",instrumentDetails:function(e){e.object=this.toString()},renderToBuffer:function(e,t){var n="render."+this.instrumentName,r={};return this.instrumentDetails(r),Ember.instrument(n,r,function(){return this._renderToBuffer(e,t)},this)},_renderToBuffer:function(e,t){Ember.run.sync();var n=this.tagName;if(n===null||n===undefined)n="div";var r=this.buffer=e&&e.begin(n)||Ember.RenderBuffer(n);return this.transitionTo("inBuffer",!1),this.beforeRender(r),this.render(r),this.afterRender(r),r},trigger:function(e){this._super.apply(this,arguments);var t=this[e];if(t){var n=[],r,i;for(r=1,i=arguments.length;r=e;r--)n[r]&&n[r].destroy()},_applyClassNameBindings:function(e){var t=this.classNames,n,r,i;f(e,function(e){var s,o=Ember.View._parsePropertyPath(e),u=function(){r=this._classStringForProperty(e),n=this.$(),s&&(n.removeClass(s),t.removeObject(s)),r?(n.addClass(r),s=r):s=null};i=this._classStringForProperty(e),i&&(l(t,i),s=i),this.registerObserver(this,o.path,u),this.one("willClearRender",function(){s&&(t.removeObject(s),s=null)})},this)},_applyAttributeBindings:function(e,n){var r,i,s;f(n,function(n){var s=n.split(":"),o=s[0],u=s[1]||o,a=function(){i=this.$();if(!i)return;r=t(this,o),Ember.View.applyAttributeBindings(i,u,r)};this.registerObserver(this,o,a),r=t(this,o),Ember.View.applyAttributeBindings(e,u,r)},this)},_classStringForProperty:function(e){var n=Ember.View._parsePropertyPath(e),r=n.path,i=t(this,r);return i===undefined&&Ember.isGlobalPath(r)&&(i=t(Ember.lookup,r)),Ember.View._classStringForValue(r,i,n.className,n.falsyClassName)},element:Ember.computed(function(e,t){return t!==undefined?this.currentState.setElement(this,t):this.currentState.getElement(this)}).property("_parentView"),$:function(e){return this.currentState.$(this,e)},mutateChildViews:function(e){var t=this._childViews,n=t.length,r;while(--n>=0)r=t[n],e.call(this,r,n);return this},forEachChildView:function(e){var t=this._childViews;if(!t)return this;var n=t.length,r,i;for(i=0;i=0;s--)e[s].removedFromDOM=!0;if(this.viewName){var o=t(this,"parentView");o&&n(o,this.viewName,null)}r&&r.removeChild(this),this.transitionTo("destroyed"),i=e.length;for(s=i-1;s>=0;s--)e[s].destroy();this.isVirtual||delete Ember.View.views[t(this,"elementId")]},createChildView:function(e,r){return e.isView&&e._parentView===this?e:(Ember.CoreView.detect(e)?(r=r||{},r._parentView=this,r.templateData=r.templateData||t(this,"templateData"),e=e.create(r),e.viewName&&n(t(this,"concreteView"),e.viewName,e)):(r&&e.setProperties(r),t(e,"templateData")||n(e,"templateData",t(this,"templateData")),n(e,"_parentView",this)),e)},becameVisible:Ember.K,becameHidden:Ember.K,_isVisibleDidChange:Ember.observer(function(){var e=this.$();if(!e)return;var n=t(this,"isVisible");e.toggle(n);if(this._isAncestorHidden())return;n?this._notifyBecameVisible():this._notifyBecameHidden()},"isVisible"),_notifyBecameVisible:function(){this.trigger("becameVisible"),this.forEachChildView(function(e){var n=t(e,"isVisible");(n||n===null)&&e._notifyBecameVisible()})},_notifyBecameHidden:function(){this.trigger("becameHidden"),this.forEachChildView(function(e){var n=t(e,"isVisible");(n||n===null)&&e._notifyBecameHidden()})},_isAncestorHidden:function(){var e=t(this,"parentView");while(e){if(t(e,"isVisible")===!1)return!0;e=t(e,"parentView")}return!1},clearBuffer:function(){this.invokeRecursively(function(e){e.buffer=null})},transitionTo:function(e,t){this.currentState=this.states[e],this.state=e,t!==!1&&this.forEachChildView(function(t){t.transitionTo(e)})},handleEvent:function(e,t){return this.currentState.handleEvent(this,e,t)},registerObserver:function(e,t,n,r){Ember.addObserver(e,t,n,r),this.one("willClearRender",function(){Ember.removeObserver(e,t,n,r)})}});var h={prepend:function(e,t){e.$().prepend(t)},after:function(e,t){e.$().after(t)},html:function(e,t){e.$().html(t)},replace:function(e){var r=t(e,"element");n(e,"element",null),e._insertElementLater(function(){Ember.$(r).replaceWith(t(e,"element"))})},remove:function(e){e.$().remove()},empty:function(e){e.$().empty()}};Ember.View.reopen({domManager:h}),Ember.View.reopenClass({_parsePropertyPath:function(e){var t=e.split(":"),n=t[0],r="",i,s;return t.length>1&&(i=t[1],t.length===3&&(s=t[2]),r=":"+i,s&&(r+=":"+s)),{path:n,classNames:r,className:i===""?undefined:i,falsyClassName:s}},_classStringForValue:function(e,t,n,r){if(n||r)return n&&!!t?n:r&&!t?r:null;if(t===!0){var i=e.split(".");return Ember.String.dasherize(i[i.length-1])}return t!==!1&&t!==undefined&&t!==null?t:null}}),Ember.View.views={},Ember.View.childViewsProperty=c,Ember.View.applyAttributeBindings=function(e,t,n){var r=Ember.typeOf(n);t!=="value"&&(r==="string"||r==="number"&&!isNaN(n))?n!==e.attr(t)&&e.attr(t,n):t==="value"||r==="boolean"?n!==e.prop(t)&&e.prop(t,n):n||e.removeAttr(t)},Ember.View.states=e}(),function(){var e=Ember.get,t=Ember.set;Ember.View.states._default={appendChild:function(){throw"You can't use appendChild outside of the rendering process"},$:function(){return undefined},getElement:function(){return null},handleEvent:function(){return!0},destroyElement:function(e){return t(e,"element",null),e._scheduledInsert&&(Ember.run.cancel(e._scheduledInsert),e._scheduledInsert=null),e},renderToBufferIfNeeded:function(){return!1},rerender:Ember.K}}(),function(){var e=Ember.View.states.preRender=Ember.create(Ember.View.states._default);Ember.merge(e,{insertElement:function(e,t){e.createElement(),e.triggerRecursively("willInsertElement"),t.call(e),e.transitionTo("inDOM"),e.triggerRecursively("didInsertElement")},renderToBufferIfNeeded:function(e){return e.renderToBuffer()},empty:Ember.K,setElement:function(e,t){return t!==null&&e.transitionTo("hasElement"),t}})}(),function(){var e=Ember.get,t=Ember.set,n=Ember.meta,r=Ember.View.states.inBuffer=Ember.create(Ember.View.states._default);Ember.merge(r,{$:function(e,t){return e.rerender(),Ember.$()},rerender:function(e){throw new Ember.Error("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.")},appendChild:function(e,t,n){var r=e.buffer;return t=e.createChildView(t,n),e._childViews.push(t),t.renderToBuffer(r),e.propertyDidChange("childViews"),t},destroyElement:function(e){return e.clearBuffer(),e._notifyWillDestroyElement(),e.transitionTo("preRender"),e},empty:function(){},renderToBufferIfNeeded:function(e){return e.buffer},insertElement:function(){throw"You can't insert an element that has already been rendered"},setElement:function(e,t){return t===null?e.transitionTo("preRender"):(e.clearBuffer(),e.transitionTo("hasElement")),t}})}(),function(){var e=Ember.get,t=Ember.set,n=Ember.meta,r=Ember.View.states.hasElement=Ember.create(Ember.View.states._default);Ember.merge(r,{$:function(t,n){var r=e(t,"element");return n?Ember.$(n,r):Ember.$(r)},getElement:function(t){var n=e(t,"parentView");return n&&(n=e(n,"element")),n?t.findElementInParentElement(n):Ember.$("#"+e(t,"elementId"))[0]},setElement:function(e,t){if(t!==null)throw"You cannot set an element to a non-null value when the element is already in the DOM.";return e.transitionTo("preRender"),t},rerender:function(e){return e.triggerRecursively("willClearRender"),e.clearRenderedChildren(),e.domManager.replace(e),e},destroyElement:function(e){return e._notifyWillDestroyElement(),e.domManager.remove(e),t(e,"element",null),e._scheduledInsert&&(Ember.run.cancel(e._scheduledInsert),e._scheduledInsert=null),e},empty:function(e){var t=e._childViews,n,r;if(t){n=t.length;for(r=0;r0){var r=e.slice(t,t+n);this.currentState.childViewsWillChange(this,e,t,n),this.initializeViews(r,null,null)}},removeChild:function(e){return this.removeObject(e),this},childViewsDidChange:function(e,n,r,i){if(i>0){var s=e.slice(n,n+i);this.initializeViews(s,this,t(this,"templateData")),this.currentState.childViewsDidChange(this,e,n,i)}this.propertyDidChange("childViews")},initializeViews:function(e,r,s){i(e,function(e){n(e,"_parentView",r),t(e,"templateData")||n(e,"templateData",s)})},currentView:null,_currentViewWillChange:Ember.beforeObserver(function(){var e=t(this,"currentView");e&&e.destroy()},"currentView"),_currentViewDidChange:Ember.observer(function(){var e=t(this,"currentView");e&&this.pushObject(e)},"currentView"),_ensureChildrenAreInDOM:function(){this.currentState.ensureChildrenAreInDOM(this)}}),Ember.merge(e._default,{childViewsWillChange:Ember.K,childViewsDidChange:Ember.K,ensureChildrenAreInDOM:Ember.K}),Ember.merge(e.inBuffer,{childViewsDidChange:function(e,t,n,r){throw new Error("You cannot modify child views while in the inBuffer state")}}),Ember.merge(e.hasElement,{childViewsWillChange:function(e,t,n,r){for(var i=n;i=n;u--)o=s[u],f&&(o.removedFromDOM=!0),o.destroy()},arrayDidChange:function(n,r,i,s){var o=e(this,"itemViewClass"),u=[],a,f,l,c,h;"string"==typeof o&&(o=e(o)),c=n?e(n,"length"):0;if(c)for(l=r;l"},v=function(){return""};if(r)u=function(e,t){var r=n.createRange(),i=n.getElementById(e.start),s=n.getElementById(e.end);return t?(r.setStartBefore(i),r.setEndAfter(s)):(r.setStartAfter(i),r.setEndBefore(s)),r},a=function(e,t){var n=u(this,t);n.deleteContents();var r=n.createContextualFragment(e);n.insertNode(r)},f=function(){var e=u(this,!0);e.deleteContents()},c=function(e){var t=n.createRange();t.setStart(e),t.collapse(!1);var r=t.createContextualFragment(this.outerHTML());e.appendChild(r)},h=function(e){var t=n.createRange(),r=n.getElementById(this.end);t.setStartAfter(r),t.setEndAfter(r);var i=t.createContextualFragment(e);t.insertNode(i)},p=function(e){var t=n.createRange(),r=n.getElementById(this.start);t.setStartAfter(r),t.setEndAfter(r);var i=t.createContextualFragment(e);t.insertNode(i)};else{var m={select:[1,""],fieldset:[1,"
","
"],table:[1,"","
"],tbody:[2,"","
"],tr:[3,"","
"],colgroup:[2,"","
"],map:[1,"",""],_default:[0,"",""]},g=function(e,t){if(e.getAttribute("id")===t)return e;var n=e.childNodes.length,r,i,s;for(r=0;r0){var i=r.length,o;for(o=0;o2?(r.data.isUnbound=!0,i=Ember.Handlebars.helpers[arguments[0]]||Ember.Handlebars.helperMissing,o=i.apply(this,Array.prototype.slice.call(arguments,1)),delete r.data.isUnbound,o):(s=n.contexts&&n.contexts[0]||this,e(s,t,n))})}(),function(){var e=Ember.Handlebars.get,t=Ember.Handlebars.normalizePath;Ember.Handlebars.registerHelper("log",function(n,r){var i=r.contexts&&r.contexts[0]||this,s=t(i,n,r.data),o=s.root,u=s.path,a=u==="this"?o:e(o,u,r);Ember.Logger.log(a)}),Ember.Handlebars.registerHelper("debugger",function(){debugger})}(),function(){var e=Ember.get,t=Ember.set;Ember.Handlebars.EachView=Ember.CollectionView.extend(Ember._Metamorph,{init:function(){var n=e(this,"itemController"),r;if(n){var i=Ember.ArrayController.create();t(i,"itemController",n),t(i,"container",e(this,"controller.container")),t(i,"_eachView",this),t(i,"target",e(this,"controller")),this.disableContentObservers(function(){t(this,"content",i),r=(new Ember.Binding("content","_eachView.dataSource")).oneWay(),r.connect(i)}),t(this,"_arrayController",i)}else this.disableContentObservers(function(){r=(new Ember.Binding("content","dataSource")).oneWay(),r.connect(this)});return this._super()},disableContentObservers:function(e){Ember.removeBeforeObserver(this,"content",null,"_contentWillChange"),Ember.removeObserver(this,"content",null,"_contentDidChange"),e.apply(this),Ember.addBeforeObserver(this,"content",null,"_contentWillChange"),Ember.addObserver(this,"content",null,"_contentDidChange")},itemViewClass:Ember._MetamorphView,emptyViewClass:Ember._MetamorphView,createChildView:function(n,r){n=this._super(n,r);var i=e(this,"keyword"),s=e(n,"content");if(i){var o=e(n,"templateData");o=Ember.copy(o),o.keywords=n.cloneKeywords(),t(n,"templateData",o),o.keywords[i]=s}return s&&e(s,"isController")&&t(n,"controller",s),n},willDestroy:function(){var t=e(this,"_arrayController");return t&&t.destroy(),this._super()}});var n=Ember.Handlebars.GroupedEach=function(e,t,n){var r=this,i=Ember.Handlebars.normalizePath(e,t,n.data);this.context=e,this.path=t,this.options=n,this.template=n.fn,this.containingView=n.data.view,this.normalizedRoot=i.root,this.normalizedPath=i.path,this.content=this.lookupContent(),this.addContentObservers(),this.addArrayObservers(),this.containingView.on("willClearRender",function(){r.destroy()})};n.prototype={contentWillChange:function(){this.removeArrayObservers()},contentDidChange:function(){this.content=this.lookupContent(),this.addArrayObservers(),this.rerenderContainingView()},contentArrayWillChange:Ember.K,contentArrayDidChange:function(){this.rerenderContainingView()},lookupContent:function(){return Ember.Handlebars.get(this.normalizedRoot,this.normalizedPath,this.options)},addArrayObservers:function(){this.content.addArrayObserver(this,{willChange:"contentArrayWillChange",didChange:"contentArrayDidChange"})},removeArrayObservers:function(){this.content.removeArrayObserver(this,{willChange:"contentArrayWillChange",didChange:"contentArrayDidChange"})},addContentObservers:function(){Ember.addBeforeObserver(this.normalizedRoot,this.normalizedPath,this,this.contentWillChange),Ember.addObserver(this.normalizedRoot,this.normalizedPath,this,this.contentDidChange)},removeContentObservers:function(){Ember.removeBeforeObserver(this.normalizedRoot,this.normalizedPath,this.contentWillChange),Ember.removeObserver(this.normalizedRoot,this.normalizedPath,this.contentDidChange)},render:function(){var t=this.content,n=e(t,"length"),r=this.options.data,i=this.template;r.insideEach=!0;for(var s=0;s'),i={},t.buffer.push(f(r._triageMustache.call(e,"view.prompt",{hash:{},contexts:[e],types:["ID"],hashTypes:i,data:t}))),t.buffer.push(""),n}function h(e,t){var n;n={contentBinding:"STRING"},t.buffer.push(f(r.view.call(e,"Ember.SelectOption",{hash:{contentBinding:"this"},contexts:[e],types:["ID"],hashTypes:n,data:t})))}this.compilerInfo=[2,">= 1.0.0-rc.3"],r=r||Ember.Handlebars.helpers,s=s||{};var o="",u,a,f=this.escapeExpression,l=this;return a={},u=r["if"].call(n,"view.prompt",{hash:{},inverse:l.noop,fn:l.program(1,c,s),contexts:[n],types:["ID"],hashTypes:a,data:s}),(u||u===0)&&s.buffer.push(u),a={},u=r.each.call(n,"view.content",{hash:{},inverse:l.noop,fn:l.program(3,h,s),contexts:[n],types:["ID"],hashTypes:a,data:s}),(u||u===0)&&s.buffer.push(u),o}),attributeBindings:["multiple","disabled","tabindex"],multiple:!1,disabled:!1,content:null,selection:null,value:Ember.computed(function(e,n){if(arguments.length===2)return n;var r=t(this,"optionValuePath").replace(/^content\.?/,"");return r?t(this,"selection."+r):t(this,"selection")}).property("selection"),prompt:null,optionLabelPath:"content",optionValuePath:"content",_change:function(){t(this,"multiple")?this._changeMultiple():this._changeSingle()},selectionDidChange:Ember.observer(function(){var n=t(this,"selection");if(t(this,"multiple")){if(!s(n)){e(this,"selection",Ember.A([n]));return}this._selectionDidChangeMultiple()}else this._selectionDidChangeSingle()},"selection.@each"),valueDidChange:Ember.observer(function(){var e=t(this,"content"),n=t(this,"value"),r=t(this,"optionValuePath").replace(/^content\.?/,""),i=r?t(this,"selection."+r):t(this,"selection"),s;n!==i&&(s=e.find(function(e){return n===(r?t(e,r):e)}),this.set("selection",s))},"value"),_triggerChange:function(){var e=t(this,"selection"),n=t(this,"value");e&&this.selectionDidChange(),n&&this.valueDidChange(),this._change()},_changeSingle:function(){var n=this.$()[0].selectedIndex,r=t(this,"content"),i=t(this,"prompt");if(!t(r,"length"))return;if(i&&n===0){e(this,"selection",null);return}i&&(n-=1),e(this,"selection",r.objectAt(n))},_changeMultiple:function(){var n=this.$("option:selected"),r=t(this,"prompt"),o=r?1:0,u=t(this,"content"),a=t(this,"selection");if(!u)return;if(n){var f=n.map(function(){return this.index-o}).toArray(),l=u.objectsAt(f);s(a)?i(a,0,t(a,"length"),l):e(this,"selection",l)}},_selectionDidChangeSingle:function(){var e=this.get("element");if(!e)return;var r=t(this,"content"),i=t(this,"selection"),s=r?n(r,i):-1,o=t(this,"prompt");o&&(s+=1),e&&(e.selectedIndex=s)},_selectionDidChangeMultiple:function(){var e=t(this,"content"),i=t(this,"selection"),s=e?r(e,i):[-1],o=t(this,"prompt"),u=o?1:0,a=this.$("option"),f;a&&a.each(function(){f=this.index>-1?this.index-u:-1,this.selected=n(s,f)>-1})},init:function(){this._super(),this.on("didInsertElement",this,this._triggerChange),this.on("change",this,this._change)}}),Ember.SelectOption=Ember.View.extend({tagName:"option",attributeBindings:["value","selected"],defaultTemplate:function(e,t){t={data:t.data,hash:{}},Ember.Handlebars.helpers.bind.call(e,"view.label",t)},init:function(){this.labelPathDidChange(),this.valuePathDidChange(),this._super()},selected:Ember.computed(function(){var e=t(this,"content"),r=t(this,"parentView.selection");return t(this,"parentView.multiple")?r&&n(r,e.valueOf())>-1:e==r}).property("content","parentView.selection").volatile(),labelPathDidChange:Ember.observer(function(){var e=t(this,"parentView.optionLabelPath");if(!e)return;Ember.defineProperty(this,"label",Ember.computed(function(){return t(this,e)}).property(e))},"parentView.optionLabelPath"),valuePathDidChange:Ember.observer(function(){var e=t(this,"parentView.optionValuePath");if(!e)return;Ember.defineProperty(this,"value",Ember.computed(function(){return t(this,e)}).property(e))},"parentView.optionValuePath")})}(),function(){}(),function(){function e(){Ember.Handlebars.bootstrap(Ember.$(document))}Ember.Handlebars.bootstrap=function(e){var t='script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';Ember.$(t,e).each(function(){var e=Ember.$(this),t=e.attr("type"),n=e.attr("type")==="text/x-raw-handlebars"?Ember.$.proxy(Handlebars.compile,Handlebars):Ember.$.proxy(Ember.Handlebars.compile,Ember.Handlebars),r=e.attr("data-template-name")||e.attr("id")||"application",i=n(e.html());Ember.TEMPLATES[r]=i,e.remove()})},Ember.onLoad("application",e)}(),function(){Ember.runLoadHooks("Ember.Handlebars",Ember.Handlebars)}(),function(){e("route-recognizer",[],function(){"use strict";function n(e){this.string=e}function r(e){this.name=e}function i(e){this.name=e}function s(){}function o(e,t,o){e.charAt(0)==="/"&&(e=e.substr(1));var u=e.split("/"),a=[];for(var f=0,l=u.length;f1&&e.charAt(i-1)==="/"&&(e=e.substr(0,i-1));for(n=0,r=e.length;n=0;i--){var s=n[i],o=s.handler;if(o.events&&o.events[r]){o.events[r].apply(o,t);return}}throw new Error("Nothing handled the event '"+r+"'.")}function d(e,t){e.context=t,e.contextDidChange&&e.contextDidChange()}return t.prototype={map:function(e){this.recognizer.delegate=this.delegate,this.recognizer.map(e,function(e,t){var n=t[t.length-1].handler,r=[t,{as:n}];e.add.apply(e,r)})},hasRoute:function(e){return this.recognizer.hasRoute(e)},handleURL:function(e){var t=this.recognizer.recognize(e),n=[];if(!t)throw new Error("No route matched the URL '"+e+"'");a(this,t,0,[])},updateURL:function(){throw"updateURL is not implemented"},replaceURL:function(e){this.updateURL(e)},transitionTo:function(e){var t=Array.prototype.slice.call(arguments,1);u(this,e,this.updateURL,t)},replaceWith:function(e){var t=Array.prototype.slice.call(arguments,1);u(this,e,this.replaceURL,t)},paramsForHandler:function(e,t){var n=this._paramsForHandler(e,[].slice.call(arguments,1));return n.params},generate:function(e){var t=this.paramsForHandler.apply(this,arguments);return this.recognizer.generate(e,t)},_paramsForHandler:function(e,t,r){var i=this.recognizer.handlersFor(e),s={},o=[],u=i.length,a=t.length,f,l,c,h,p,v,m;for(v=i.length-1;v>=0&&a>0;v--)i[v].names.length&&(a--,u=v);if(a>0)throw"More objects were passed than dynamic segments";for(v=0,m=i.length;v=u?(f=t.shift(),l=!0):f=h.context,h.serialize&&n(s,h.serialize(f,p))):r&&(v>u||!h.hasOwnProperty("context")?h.deserialize&&(f=h.deserialize({}),l=!0):f=h.context),r&&l&&d(h,f),o.push({isDynamic:!!c.names.length,handler:c.handler,name:c.name,context:f});return{params:s,toSetup:o}},isActive:function(e){var t=[].slice.call(arguments,1),n=this.currentHandlerInfos,r=!1,i,s,o,u;for(var a=n.length-1;a>=0;a--){o=n[a],o.name===e&&(r=!0);if(r){if(t.length===0)break;if(o.isDynamic){s=t.pop();if(o.context!==s)return!1}}}return t.length===0&&r},trigger:function(e){var t=[].slice.call(arguments);p(this,t)}},t})}(),function(){function e(e){this.parent=e,this.matches=[]}e.prototype={resource:function(t,n,r){arguments.length===2&&typeof n=="function"&&(r=n,n={}),arguments.length===1&&(n={}),typeof n.path!="string"&&(n.path="/"+t);if(r){var i=new e(t);r.call(i),this.push(n.path,t,i.generate())}else this.push(n.path,t)},push:function(e,t,n){if(e===""||e==="/")this.explicitIndex=!0;this.matches.push([e,t,n])},route:function(e,t){t=t||{},typeof t.path!="string"&&(t.path="/"+e),this.parent&&this.parent!=="application"&&(e=this.parent+"."+e),this.push(t.path,e)},generate:function(){var e=this.matches;return this.explicitIndex||this.route("index",{path:"/"}),function(t){for(var n=0,r=e.length;n0){if(n>=0)i=this.enterStates[n--];else{if(this.enterStates.length){i=e(this.enterStates[0],"parentState");if(!i)throw"Cannot match all contexts to states"}else i=this.resolveState;this.enterStates.unshift(i),this.exitStates.unshift(i)}e(i,"hasContext")?s=t.pop():s=null,r.unshift(s)}this.contexts=r},addInitialStates:function(){var t=this.finalState,n;for(;;){n=e(t,"initialState")||"start",t=e(t,"states."+n);if(!t)break;this.finalState=t,this.enterStates.push(t),this.contexts.push(undefined)}},removeUnchangedContexts:function(e){while(this.enterStates.length>0){if(this.enterStates[0]!==this.exitStates[0])break;if(this.enterStates.length===this.contexts.length){if(e.getStateMeta(this.enterStates[0],"context")!==this.contexts[0])break;this.contexts.shift()}this.resolveState=this.enterStates.shift(),this.exitStates.shift()}}};var s=function(t,r,i){var u=this.enableLogging,a=i?"unhandledEvent":t,f=r[a],l,c,h;l=[].slice.call(arguments,3);if(typeof f=="function")return u&&(i?Ember.Logger.log(n("STATEMANAGER: Unhandled event '%@' being sent to state %@.",[t,e(r,"path")])):Ember.Logger.log(n("STATEMANAGER: Sending event '%@' to state %@.",[t,e(r,"path")]))),h=l,i&&h.unshift(t),h.unshift(this),f.apply(r,h);var p=e(r,"parentState");if(p)return c=l,c.unshift(t,p,i),s.apply(this,c);if(!i)return o.call(this,t,l,!0)},o=function(t,n,r){return n.unshift(t,e(this,"currentState"),r),s.apply(this,n)};Ember.StateManager=Ember.State.extend({init:function(){this._super(),t(this,"stateMeta",Ember.Map.create());var n=e(this,"initialState");!n&&e(this,"states.start")&&(n="start"),n&&this.transitionTo(n)},stateMetaFor:function(t){var n=e(this,"stateMeta"),r=n.get(t);return r||(r={},n.set(t,r)),r},setStateMeta:function(e,n,r){return t(this.stateMetaFor(e),n,r)},getStateMeta:function(t,n){return e(this.stateMetaFor(t),n)},currentState:null,currentPath:Ember.computed.alias("currentState.path"),transitionEvent:"setup",errorOnUnhandledEvent:!0,send:function(e){var t=[].slice.call(arguments,1);return o.call(this,e,t,!1)},unhandledEvent:function(t,n){if(e(this,"errorOnUnhandledEvent"))throw new Ember.Error(this.toString()+" could not respond to event "+n+" in state "+e(this,"currentState.path")+".")},getStateByPath:function(t,n){var r=n.split("."),i=t;for(var s=0,o=r.length;s0&&i[0]===s[0])o=i.shift(),s.shift();var u=t.pathsCache[n]={exitStates:s,enterStates:i,resolveState:o};return u},triggerSetupContext:function(t){var n=t.contexts,i=t.enterStates.length-n.length,s=t.enterStates,o=e(this,"transitionEvent");r.call(s,function(e,t){e.trigger(o,this,n[t-i])},this)},getState:function(t){var n=e(this,t),r=e(this,"parentState");if(n)return n;if(r)return r.getState(t)},enterState:function(n){var i=this.enableLogging,s=n.exitStates.slice(0).reverse();r.call(s,function(e){e.trigger("exit",this)},this),r.call(n.enterStates,function(t){i&&Ember.Logger.log("STATEMANAGER: Entering "+e(t,"path")),t.trigger("enter",this)},this),t(this,"currentState",n.finalState)}})}(),function(){}()})(),typeof location!="undefined"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1")&&console.warn("You are running a production build of Ember on localhost and won't receive detailed error messages. If you want full error messages please use the non-minified build provided on the Ember website."); \ No newline at end of file diff --git a/htdocs/portal/assets/js/ember-data.js b/htdocs/portal/assets/js/ember-data.js new file mode 100644 index 0000000000..9b920311e6 --- /dev/null +++ b/htdocs/portal/assets/js/ember-data.js @@ -0,0 +1,7832 @@ +(function() { +window.DS = Ember.Namespace.create({ + // this one goes to 11 + CURRENT_API_REVISION: 11 +}); + +})(); + + + +(function() { +var DeferredMixin = Ember.DeferredMixin, // ember-runtime/mixins/deferred + Evented = Ember.Evented, // ember-runtime/mixins/evented + run = Ember.run, // ember-metal/run-loop + get = Ember.get; // ember-metal/accessors + +var LoadPromise = Ember.Mixin.create(Evented, DeferredMixin, { + init: function() { + this._super.apply(this, arguments); + this.one('didLoad', function() { + run(this, 'resolve', this); + }); + + if (get(this, 'isLoaded')) { + this.trigger('didLoad'); + } + } +}); + +DS.LoadPromise = LoadPromise; + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set; + +var LoadPromise = DS.LoadPromise; // system/mixins/load_promise + +/** + A record array is an array that contains records of a certain type. The record + array materializes records as needed when they are retrieved for the first + time. You should not create record arrays yourself. Instead, an instance of + DS.RecordArray or its subclasses will be returned by your application's store + in response to queries. +*/ + +DS.RecordArray = Ember.ArrayProxy.extend(Ember.Evented, LoadPromise, { + /** + The model type contained by this record array. + + @type DS.Model + */ + type: null, + + // The array of client ids backing the record array. When a + // record is requested from the record array, the record + // for the client id at the same index is materialized, if + // necessary, by the store. + content: null, + + isLoaded: false, + isUpdating: false, + + // The store that created this record array. + store: null, + + objectAtContent: function(index) { + var content = get(this, 'content'), + reference = content.objectAt(index), + store = get(this, 'store'); + + if (reference) { + return store.findByClientId(get(this, 'type'), reference.clientId); + } + }, + + materializedObjectAt: function(index) { + var reference = get(this, 'content').objectAt(index); + if (!reference) { return; } + + if (get(this, 'store').recordIsMaterialized(reference.clientId)) { + return this.objectAt(index); + } + }, + + update: function() { + if (get(this, 'isUpdating')) { return; } + + var store = get(this, 'store'), + type = get(this, 'type'); + + store.fetchAll(type, this); + }, + + addReference: function(reference) { + get(this, 'content').addObject(reference); + }, + + removeReference: function(reference) { + get(this, 'content').removeObject(reference); + } +}); + +})(); + + + +(function() { +var get = Ember.get; + +DS.FilteredRecordArray = DS.RecordArray.extend({ + filterFunction: null, + isLoaded: true, + + replace: function() { + var type = get(this, 'type').toString(); + throw new Error("The result of a client-side filter (on " + type + ") is immutable."); + }, + + updateFilter: Ember.observer(function() { + var store = get(this, 'store'); + store.updateRecordArrayFilter(this, get(this, 'type'), get(this, 'filterFunction')); + }, 'filterFunction') +}); + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set; + +DS.AdapterPopulatedRecordArray = DS.RecordArray.extend({ + query: null, + + replace: function() { + var type = get(this, 'type').toString(); + throw new Error("The result of a server query (on " + type + ") is immutable."); + }, + + load: function(references) { + var store = get(this, 'store'), type = get(this, 'type'); + + this.beginPropertyChanges(); + set(this, 'content', Ember.A(references)); + set(this, 'isLoaded', true); + this.endPropertyChanges(); + + var self = this; + // TODO: does triggering didLoad event should be the last action of the runLoop? + Ember.run.once(function() { + self.trigger('didLoad'); + }); + } +}); + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set; + +/** + A ManyArray is a RecordArray that represents the contents of a has-many + relationship. + + The ManyArray is instantiated lazily the first time the relationship is + requested. + + ### Inverses + + Often, the relationships in Ember Data applications will have + an inverse. For example, imagine the following models are + defined: + + App.Post = DS.Model.extend({ + comments: DS.hasMany('App.Comment') + }); + + App.Comment = DS.Model.extend({ + post: DS.belongsTo('App.Post') + }); + + If you created a new instance of `App.Post` and added + a `App.Comment` record to its `comments` has-many + relationship, you would expect the comment's `post` + property to be set to the post that contained + the has-many. + + We call the record to which a relationship belongs the + relationship's _owner_. +*/ +DS.ManyArray = DS.RecordArray.extend({ + init: function() { + this._super.apply(this, arguments); + this._changesToSync = Ember.OrderedSet.create(); + }, + + /** + @private + + The record to which this relationship belongs. + + @property {DS.Model} + */ + owner: null, + + // LOADING STATE + + isLoaded: false, + + loadingRecordsCount: function(count) { + this.loadingRecordsCount = count; + }, + + loadedRecord: function() { + this.loadingRecordsCount--; + if (this.loadingRecordsCount === 0) { + set(this, 'isLoaded', true); + this.trigger('didLoad'); + } + }, + + fetch: function() { + var references = get(this, 'content'), + store = get(this, 'store'), + type = get(this, 'type'), + owner = get(this, 'owner'); + + store.fetchUnloadedReferences(type, references, owner); + }, + + // Overrides Ember.Array's replace method to implement + replaceContent: function(index, removed, added) { + // Map the array of record objects into an array of client ids. + added = added.map(function(record) { + Ember.assert("You can only add records of " + (get(this, 'type') && get(this, 'type').toString()) + " to this relationship.", !get(this, 'type') || (get(this, 'type') === record.constructor)); + return get(record, '_reference'); + }, this); + + this._super(index, removed, added); + }, + + arrangedContentDidChange: function() { + this.fetch(); + }, + + arrayContentWillChange: function(index, removed, added) { + var owner = get(this, 'owner'), + name = get(this, 'name'); + + if (!owner._suspendedRelationships) { + // This code is the first half of code that continues inside + // of arrayContentDidChange. It gets or creates a change from + // the child object, adds the current owner as the old + // parent if this is the first time the object was removed + // from a ManyArray, and sets `newParent` to null. + // + // Later, if the object is added to another ManyArray, + // the `arrayContentDidChange` will set `newParent` on + // the change. + for (var i=index; i "created.uncommitted" + + The `DS.Model` states are themselves stateless. What we mean is that, + though each instance of a record also has a unique instance of a + `DS.StateManager`, the hierarchical states that each of *those* points + to is a shared data structure. For performance reasons, instead of each + record getting its own copy of the hierarchy of states, each state + manager points to this global, immutable shared instance. How does a + state know which record it should be acting on? We pass a reference to + the current state manager as the first parameter to every method invoked + on a state. + + The state manager passed as the first parameter is where you should stash + state about the record if needed; you should never store data on the state + object itself. If you need access to the record being acted on, you can + retrieve the state manager's `record` property. For example, if you had + an event handler `myEvent`: + + myEvent: function(manager) { + var record = manager.get('record'); + record.doSomething(); + } + + For more information about state managers in general, see the Ember.js + documentation on `Ember.StateManager`. + + ### Events, Flags, and Transitions + + A state may implement zero or more events, flags, or transitions. + + #### Events + + Events are named functions that are invoked when sent to a record. The + state manager will first look for a method with the given name on the + current state. If no method is found, it will search the current state's + parent, and then its grandparent, and so on until reaching the top of + the hierarchy. If the root is reached without an event handler being found, + an exception will be raised. This can be very helpful when debugging new + features. + + Here's an example implementation of a state with a `myEvent` event handler: + + aState: DS.State.create({ + myEvent: function(manager, param) { + console.log("Received myEvent with "+param); + } + }) + + To trigger this event: + + record.send('myEvent', 'foo'); + //=> "Received myEvent with foo" + + Note that an optional parameter can be sent to a record's `send()` method, + which will be passed as the second parameter to the event handler. + + Events should transition to a different state if appropriate. This can be + done by calling the state manager's `transitionTo()` method with a path to the + desired state. The state manager will attempt to resolve the state path + relative to the current state. If no state is found at that path, it will + attempt to resolve it relative to the current state's parent, and then its + parent, and so on until the root is reached. For example, imagine a hierarchy + like this: + + * created + * start <-- currentState + * inFlight + * updated + * inFlight + + If we are currently in the `start` state, calling + `transitionTo('inFlight')` would transition to the `created.inFlight` state, + while calling `transitionTo('updated.inFlight')` would transition to + the `updated.inFlight` state. + + Remember that *only events* should ever cause a state transition. You should + never call `transitionTo()` from outside a state's event handler. If you are + tempted to do so, create a new event and send that to the state manager. + + #### Flags + + Flags are Boolean values that can be used to introspect a record's current + state in a more user-friendly way than examining its state path. For example, + instead of doing this: + + var statePath = record.get('stateManager.currentPath'); + if (statePath === 'created.inFlight') { + doSomething(); + } + + You can say: + + if (record.get('isNew') && record.get('isSaving')) { + doSomething(); + } + + If your state does not set a value for a given flag, the value will + be inherited from its parent (or the first place in the state hierarchy + where it is defined). + + The current set of flags are defined below. If you want to add a new flag, + in addition to the area below, you will also need to declare it in the + `DS.Model` class. + + #### Transitions + + Transitions are like event handlers but are called automatically upon + entering or exiting a state. To implement a transition, just call a method + either `enter` or `exit`: + + myState: DS.State.create({ + // Gets called automatically when entering + // this state. + enter: function(manager) { + console.log("Entered myState"); + } + }) + + Note that enter and exit events are called once per transition. If the + current state changes, but changes to another child state of the parent, + the transition event on the parent will not be triggered. +*/ + +var stateProperty = Ember.computed(function(key) { + var parent = get(this, 'parentState'); + if (parent) { + return get(parent, key); + } +}).property(); + +var isEmptyObject = function(object) { + for (var name in object) { + if (object.hasOwnProperty(name)) { return false; } + } + + return true; +}; + +var hasDefinedProperties = function(object) { + for (var name in object) { + if (object.hasOwnProperty(name) && object[name]) { return true; } + } + + return false; +}; + +var didChangeData = function(manager) { + var record = get(manager, 'record'); + record.materializeData(); +}; + +var willSetProperty = function(manager, context) { + context.oldValue = get(get(manager, 'record'), context.name); + + var change = DS.AttributeChange.createChange(context); + get(manager, 'record')._changesToSync[context.attributeName] = change; +}; + +var didSetProperty = function(manager, context) { + var change = get(manager, 'record')._changesToSync[context.attributeName]; + change.value = get(get(manager, 'record'), context.name); + change.sync(); +}; + +// Whenever a property is set, recompute all dependent filters +var updateRecordArrays = function(manager) { + var record = manager.get('record'); + record.updateRecordArraysLater(); +}; + +DS.State = Ember.State.extend({ + isLoaded: stateProperty, + isReloading: stateProperty, + isDirty: stateProperty, + isSaving: stateProperty, + isDeleted: stateProperty, + isError: stateProperty, + isNew: stateProperty, + isValid: stateProperty, + + // For states that are substates of a + // DirtyState (updated or created), it is + // useful to be able to determine which + // type of dirty state it is. + dirtyType: stateProperty +}); + +// Implementation notes: +// +// Each state has a boolean value for all of the following flags: +// +// * isLoaded: The record has a populated `data` property. When a +// record is loaded via `store.find`, `isLoaded` is false +// until the adapter sets it. When a record is created locally, +// its `isLoaded` property is always true. +// * isDirty: The record has local changes that have not yet been +// saved by the adapter. This includes records that have been +// created (but not yet saved) or deleted. +// * isSaving: The record's transaction has been committed, but +// the adapter has not yet acknowledged that the changes have +// been persisted to the backend. +// * isDeleted: The record was marked for deletion. When `isDeleted` +// is true and `isDirty` is true, the record is deleted locally +// but the deletion was not yet persisted. When `isSaving` is +// true, the change is in-flight. When both `isDirty` and +// `isSaving` are false, the change has persisted. +// * isError: The adapter reported that it was unable to save +// local changes to the backend. This may also result in the +// record having its `isValid` property become false if the +// adapter reported that server-side validations failed. +// * isNew: The record was created on the client and the adapter +// did not yet report that it was successfully saved. +// * isValid: No client-side validations have failed and the +// adapter did not report any server-side validation failures. + +// The dirty state is a abstract state whose functionality is +// shared between the `created` and `updated` states. +// +// The deleted state shares the `isDirty` flag with the +// subclasses of `DirtyState`, but with a very different +// implementation. +// +// Dirty states have three child states: +// +// `uncommitted`: the store has not yet handed off the record +// to be saved. +// `inFlight`: the store has handed off the record to be saved, +// but the adapter has not yet acknowledged success. +// `invalid`: the record has invalid information and cannot be +// send to the adapter yet. +var DirtyState = DS.State.extend({ + initialState: 'uncommitted', + + // FLAGS + isDirty: true, + + // SUBSTATES + + // When a record first becomes dirty, it is `uncommitted`. + // This means that there are local pending changes, but they + // have not yet begun to be saved, and are not invalid. + uncommitted: DS.State.extend({ + // TRANSITIONS + enter: function(manager) { + var dirtyType = get(this, 'dirtyType'), + record = get(manager, 'record'); + + record.withTransaction(function (t) { + t.recordBecameDirty(dirtyType, record); + }); + }, + + // EVENTS + willSetProperty: willSetProperty, + didSetProperty: didSetProperty, + + becomeDirty: Ember.K, + + willCommit: function(manager) { + manager.transitionTo('inFlight'); + }, + + becameClean: function(manager) { + var record = get(manager, 'record'), + dirtyType = get(this, 'dirtyType'); + + record.withTransaction(function(t) { + t.recordBecameClean(dirtyType, record); + }); + + manager.transitionTo('loaded.materializing'); + }, + + becameInvalid: function(manager) { + var dirtyType = get(this, 'dirtyType'), + record = get(manager, 'record'); + + record.withTransaction(function (t) { + t.recordBecameInFlight(dirtyType, record); + }); + + manager.transitionTo('invalid'); + }, + + rollback: function(manager) { + get(manager, 'record').rollback(); + } + }), + + // Once a record has been handed off to the adapter to be + // saved, it is in the 'in flight' state. Changes to the + // record cannot be made during this window. + inFlight: DS.State.extend({ + // FLAGS + isSaving: true, + + // TRANSITIONS + enter: function(manager) { + var dirtyType = get(this, 'dirtyType'), + record = get(manager, 'record'); + + record.becameInFlight(); + + record.withTransaction(function (t) { + t.recordBecameInFlight(dirtyType, record); + }); + }, + + // EVENTS + didCommit: function(manager) { + var dirtyType = get(this, 'dirtyType'), + record = get(manager, 'record'); + + record.withTransaction(function(t) { + t.recordBecameClean('inflight', record); + }); + + manager.transitionTo('saved'); + manager.send('invokeLifecycleCallbacks', dirtyType); + }, + + becameInvalid: function(manager, errors) { + var record = get(manager, 'record'); + + set(record, 'errors', errors); + + manager.transitionTo('invalid'); + manager.send('invokeLifecycleCallbacks'); + }, + + becameError: function(manager) { + manager.transitionTo('error'); + manager.send('invokeLifecycleCallbacks'); + } + }), + + // A record is in the `invalid` state when its client-side + // invalidations have failed, or if the adapter has indicated + // the the record failed server-side invalidations. + invalid: DS.State.extend({ + // FLAGS + isValid: false, + + exit: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function (t) { + t.recordBecameClean('inflight', record); + }); + }, + + // EVENTS + deleteRecord: function(manager) { + manager.transitionTo('deleted'); + get(manager, 'record').clearRelationships(); + }, + + willSetProperty: willSetProperty, + + didSetProperty: function(manager, context) { + var record = get(manager, 'record'), + errors = get(record, 'errors'), + key = context.name; + + set(errors, key, null); + + if (!hasDefinedProperties(errors)) { + manager.send('becameValid'); + } + + didSetProperty(manager, context); + }, + + becomeDirty: Ember.K, + + rollback: function(manager) { + manager.send('becameValid'); + manager.send('rollback'); + }, + + becameValid: function(manager) { + manager.transitionTo('uncommitted'); + }, + + invokeLifecycleCallbacks: function(manager) { + var record = get(manager, 'record'); + record.trigger('becameInvalid', record); + } + }) +}); + +// The created and updated states are created outside the state +// chart so we can reopen their substates and add mixins as +// necessary. + +var createdState = DirtyState.create({ + dirtyType: 'created', + + // FLAGS + isNew: true +}); + +var updatedState = DirtyState.create({ + dirtyType: 'updated' +}); + +createdState.states.uncommitted.reopen({ + deleteRecord: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function(t) { + t.recordIsMoving('created', record); + }); + + record.clearRelationships(); + manager.transitionTo('deleted.saved'); + } +}); + +createdState.states.uncommitted.reopen({ + rollback: function(manager) { + this._super(manager); + manager.transitionTo('deleted.saved'); + } +}); + +updatedState.states.uncommitted.reopen({ + deleteRecord: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function(t) { + t.recordIsMoving('updated', record); + }); + + manager.transitionTo('deleted'); + get(manager, 'record').clearRelationships(); + } +}); + +var states = { + rootState: Ember.State.create({ + // FLAGS + isLoaded: false, + isReloading: false, + isDirty: false, + isSaving: false, + isDeleted: false, + isError: false, + isNew: false, + isValid: true, + + // SUBSTATES + + // A record begins its lifecycle in the `empty` state. + // If its data will come from the adapter, it will + // transition into the `loading` state. Otherwise, if + // the record is being created on the client, it will + // transition into the `created` state. + empty: DS.State.create({ + // EVENTS + loadingData: function(manager) { + manager.transitionTo('loading'); + }, + + loadedData: function(manager) { + manager.transitionTo('loaded.created'); + } + }), + + // A record enters this state when the store askes + // the adapter for its data. It remains in this state + // until the adapter provides the requested data. + // + // Usually, this process is asynchronous, using an + // XHR to retrieve the data. + loading: DS.State.create({ + // EVENTS + loadedData: didChangeData, + + materializingData: function(manager) { + manager.transitionTo('loaded.materializing.firstTime'); + } + }), + + // A record enters this state when its data is populated. + // Most of a record's lifecycle is spent inside substates + // of the `loaded` state. + loaded: DS.State.create({ + initialState: 'saved', + + // FLAGS + isLoaded: true, + + // SUBSTATES + + materializing: DS.State.create({ + // FLAGS + isLoaded: false, + + // EVENTS + willSetProperty: Ember.K, + didSetProperty: Ember.K, + + didChangeData: didChangeData, + + finishedMaterializing: function(manager) { + manager.transitionTo('loaded.saved'); + }, + + // SUBSTATES + firstTime: DS.State.create({ + exit: function(manager) { + var record = get(manager, 'record'); + + Ember.run.once(function() { + record.trigger('didLoad'); + }); + } + }) + }), + + reloading: DS.State.create({ + // FLAGS + isReloading: true, + + // TRANSITIONS + enter: function(manager) { + var record = get(manager, 'record'), + store = get(record, 'store'); + + store.reloadRecord(record); + }, + + exit: function(manager) { + var record = get(manager, 'record'); + + once(record, 'trigger', 'didReload'); + }, + + // EVENTS + loadedData: didChangeData, + + materializingData: function(manager) { + manager.transitionTo('loaded.materializing'); + } + }), + + // If there are no local changes to a record, it remains + // in the `saved` state. + saved: DS.State.create({ + // EVENTS + willSetProperty: willSetProperty, + didSetProperty: didSetProperty, + + didChangeData: didChangeData, + loadedData: didChangeData, + + reloadRecord: function(manager) { + manager.transitionTo('loaded.reloading'); + }, + + materializingData: function(manager) { + manager.transitionTo('loaded.materializing'); + }, + + becomeDirty: function(manager) { + manager.transitionTo('updated'); + }, + + deleteRecord: function(manager) { + manager.transitionTo('deleted'); + get(manager, 'record').clearRelationships(); + }, + + unloadRecord: function(manager) { + manager.transitionTo('deleted.saved'); + get(manager, 'record').clearRelationships(); + }, + + willCommit: function(manager) { + manager.transitionTo('relationshipsInFlight'); + }, + + invokeLifecycleCallbacks: function(manager, dirtyType) { + var record = get(manager, 'record'); + if (dirtyType === 'created') { + record.trigger('didCreate', record); + } else { + record.trigger('didUpdate', record); + } + } + }), + + relationshipsInFlight: Ember.State.create({ + // TRANSITIONS + enter: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function (t) { + t.recordBecameInFlight('clean', record); + }); + }, + + // EVENTS + didCommit: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function(t) { + t.recordBecameClean('inflight', record); + }); + + manager.transitionTo('saved'); + + manager.send('invokeLifecycleCallbacks'); + } + }), + + // A record is in this state after it has been locally + // created but before the adapter has indicated that + // it has been saved. + created: createdState, + + // A record is in this state if it has already been + // saved to the server, but there are new local changes + // that have not yet been saved. + updated: updatedState + }), + + // A record is in this state if it was deleted from the store. + deleted: DS.State.create({ + initialState: 'uncommitted', + dirtyType: 'deleted', + + // FLAGS + isDeleted: true, + isLoaded: true, + isDirty: true, + + // TRANSITIONS + setup: function(manager) { + var record = get(manager, 'record'), + store = get(record, 'store'); + + store.removeFromRecordArrays(record); + }, + + // SUBSTATES + + // When a record is deleted, it enters the `start` + // state. It will exit this state when the record's + // transaction starts to commit. + uncommitted: DS.State.create({ + // TRANSITIONS + enter: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function(t) { + t.recordBecameDirty('deleted', record); + }); + }, + + // EVENTS + willCommit: function(manager) { + manager.transitionTo('inFlight'); + }, + + rollback: function(manager) { + get(manager, 'record').rollback(); + }, + + becomeDirty: Ember.K, + + becameClean: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function(t) { + t.recordBecameClean('deleted', record); + }); + + manager.transitionTo('loaded.materializing'); + } + }), + + // After a record's transaction is committing, but + // before the adapter indicates that the deletion + // has saved to the server, a record is in the + // `inFlight` substate of `deleted`. + inFlight: DS.State.create({ + // FLAGS + isSaving: true, + + // TRANSITIONS + enter: function(manager) { + var record = get(manager, 'record'); + + record.becameInFlight(); + + record.withTransaction(function (t) { + t.recordBecameInFlight('deleted', record); + }); + }, + + // EVENTS + didCommit: function(manager) { + var record = get(manager, 'record'); + + record.withTransaction(function(t) { + t.recordBecameClean('inflight', record); + }); + + manager.transitionTo('saved'); + + manager.send('invokeLifecycleCallbacks'); + } + }), + + // Once the adapter indicates that the deletion has + // been saved, the record enters the `saved` substate + // of `deleted`. + saved: DS.State.create({ + // FLAGS + isDirty: false, + + setup: function(manager) { + var record = get(manager, 'record'), + store = get(record, 'store'); + + store.dematerializeRecord(record); + }, + + invokeLifecycleCallbacks: function(manager) { + var record = get(manager, 'record'); + record.trigger('didDelete', record); + } + }) + }), + + // If the adapter indicates that there was an unknown + // error saving a record, the record enters the `error` + // state. + error: DS.State.create({ + isError: true, + + // EVENTS + + invokeLifecycleCallbacks: function(manager) { + var record = get(manager, 'record'); + record.trigger('becameError', record); + } + }) + }) +}; + +DS.StateManager = Ember.StateManager.extend({ + record: null, + initialState: 'rootState', + states: states, + unhandledEvent: function(manager, originalEvent) { + var record = manager.get('record'), + contexts = [].slice.call(arguments, 2), + errorMessage; + errorMessage = "Attempted to handle event `" + originalEvent + "` "; + errorMessage += "on " + record.toString() + " while in state "; + errorMessage += get(manager, 'currentState.path') + ". Called with "; + errorMessage += arrayMap.call(contexts, function(context){ + return Ember.inspect(context); + }).join(', '); + throw new Ember.Error(errorMessage); + } +}); + +})(); + + + +(function() { +var LoadPromise = DS.LoadPromise; // system/mixins/load_promise + +var get = Ember.get, set = Ember.set, none = Ember.isNone, map = Ember.EnumerableUtils.map; + +var retrieveFromCurrentState = Ember.computed(function(key) { + return get(get(this, 'stateManager.currentState'), key); +}).property('stateManager.currentState'); + +DS.Model = Ember.Object.extend(Ember.Evented, LoadPromise, { + isLoaded: retrieveFromCurrentState, + isReloading: retrieveFromCurrentState, + isDirty: retrieveFromCurrentState, + isSaving: retrieveFromCurrentState, + isDeleted: retrieveFromCurrentState, + isError: retrieveFromCurrentState, + isNew: retrieveFromCurrentState, + isValid: retrieveFromCurrentState, + + clientId: null, + id: null, + transaction: null, + stateManager: null, + errors: null, + + /** + Create a JSON representation of the record, using the serialization + strategy of the store's adapter. + + Available options: + + * `includeId`: `true` if the record's ID should be included in the + JSON representation. + + @param {Object} options + @returns {Object} an object whose values are primitive JSON values only + */ + serialize: function(options) { + var store = get(this, 'store'); + return store.serialize(this, options); + }, + + didLoad: Ember.K, + didReload: Ember.K, + didUpdate: Ember.K, + didCreate: Ember.K, + didDelete: Ember.K, + becameInvalid: Ember.K, + becameError: Ember.K, + + data: Ember.computed(function() { + if (!this._data) { + this.materializeData(); + } + + return this._data; + }).property(), + + materializeData: function() { + this.send('materializingData'); + + get(this, 'store').materializeData(this); + + this.suspendRelationshipObservers(function() { + this.notifyPropertyChange('data'); + }); + }, + + _data: null, + + init: function() { + this._super(); + + var stateManager = DS.StateManager.create({ record: this }); + set(this, 'stateManager', stateManager); + + this._setup(); + + stateManager.goToState('empty'); + }, + + _setup: function() { + this._relationshipChanges = {}; + this._changesToSync = {}; + }, + + send: function(name, context) { + return get(this, 'stateManager').send(name, context); + }, + + withTransaction: function(fn) { + var transaction = get(this, 'transaction'); + if (transaction) { fn(transaction); } + }, + + loadingData: function() { + this.send('loadingData'); + }, + + loadedData: function() { + this.send('loadedData'); + }, + + didChangeData: function() { + this.send('didChangeData'); + }, + + setProperty: function(key, value, oldValue) { + this.send('setProperty', { key: key, value: value, oldValue: oldValue }); + }, + + /** + Reload the record from the adapter. + + This will only work if the record has already finished loading + and has not yet been modified (`isLoaded` but not `isDirty`, + or `isSaving`). + */ + reload: function() { + this.send('reloadRecord'); + }, + + deleteRecord: function() { + this.send('deleteRecord'); + }, + + unloadRecord: function() { + Ember.assert("You can only unload a loaded, non-dirty record.", !get(this, 'isDirty')); + + this.send('unloadRecord'); + }, + + clearRelationships: function() { + this.eachRelationship(function(name, relationship) { + if (relationship.kind === 'belongsTo') { + set(this, name, null); + } else if (relationship.kind === 'hasMany') { + get(this, name).clear(); + } + }, this); + }, + + updateRecordArrays: function() { + var store = get(this, 'store'); + if (store) { + store.dataWasUpdated(this.constructor, get(this, 'clientId'), this); + } + }, + + /** + If the adapter did not return a hash in response to a commit, + merge the changed attributes and relationships into the existing + saved data. + */ + adapterDidCommit: function() { + var attributes = get(this, 'data').attributes; + + get(this.constructor, 'attributes').forEach(function(name, meta) { + attributes[name] = get(this, name); + }, this); + + this.send('didCommit'); + this.updateRecordArraysLater(); + }, + + adapterDidDirty: function() { + this.send('becomeDirty'); + this.updateRecordArraysLater(); + }, + + dataDidChange: Ember.observer(function() { + var relationships = get(this.constructor, 'relationshipsByName'); + + this.updateRecordArraysLater(); + + relationships.forEach(function(name, relationship) { + if (relationship.kind === 'hasMany') { + this.hasManyDidChange(relationship.key); + } + }, this); + + this.send('finishedMaterializing'); + }, 'data'), + + hasManyDidChange: function(key) { + var cachedValue = this.cacheFor(key); + + if (cachedValue) { + var type = get(this.constructor, 'relationshipsByName').get(key).type; + var store = get(this, 'store'); + var ids = this._data.hasMany[key] || []; + + var references = map(ids, function(id) { + // if it was already a reference, return the reference + if (typeof id === 'object') { return id; } + return store.referenceForId(type, id); + }); + + set(cachedValue, 'content', Ember.A(references)); + } + }, + + updateRecordArraysLater: function() { + Ember.run.once(this, this.updateRecordArrays); + }, + + setupData: function(prematerialized) { + this._data = { + attributes: {}, + belongsTo: {}, + hasMany: {}, + id: null + }; + }, + + materializeId: function(id) { + set(this, 'id', id); + }, + + materializeAttributes: function(attributes) { + Ember.assert("Must pass a hash of attributes to materializeAttributes", !!attributes); + this._data.attributes = attributes; + }, + + materializeAttribute: function(name, value) { + this._data.attributes[name] = value; + }, + + materializeHasMany: function(name, ids) { + this._data.hasMany[name] = ids; + }, + + materializeBelongsTo: function(name, id) { + this._data.belongsTo[name] = id; + }, + + rollback: function() { + this._setup(); + this.send('becameClean'); + + this.suspendRelationshipObservers(function() { + this.notifyPropertyChange('data'); + }); + }, + + toStringExtension: function() { + return get(this, 'id'); + }, + + /** + @private + + The goal of this method is to temporarily disable specific observers + that take action in response to application changes. + + This allows the system to make changes (such as materialization and + rollback) that should not trigger secondary behavior (such as setting an + inverse relationship or marking records as dirty). + + The specific implementation will likely change as Ember proper provides + better infrastructure for suspending groups of observers, and if Array + observation becomes more unified with regular observers. + */ + suspendRelationshipObservers: function(callback, binding) { + var observers = get(this.constructor, 'relationshipNames').belongsTo; + var self = this; + + try { + this._suspendedRelationships = true; + Ember._suspendObservers(self, observers, null, 'belongsToDidChange', function() { + Ember._suspendBeforeObservers(self, observers, null, 'belongsToWillChange', function() { + callback.call(binding || self); + }); + }); + } finally { + this._suspendedRelationships = false; + } + }, + + becameInFlight: function() { + }, + + // FOR USE DURING COMMIT PROCESS + + adapterDidUpdateAttribute: function(attributeName, value) { + + // If a value is passed in, update the internal attributes and clear + // the attribute cache so it picks up the new value. Otherwise, + // collapse the current value into the internal attributes because + // the adapter has acknowledged it. + if (value !== undefined) { + get(this, 'data.attributes')[attributeName] = value; + this.notifyPropertyChange(attributeName); + } else { + value = get(this, attributeName); + get(this, 'data.attributes')[attributeName] = value; + } + + this.updateRecordArraysLater(); + }, + + _reference: Ember.computed(function() { + return get(this, 'store').referenceForClientId(get(this, 'clientId')); + }), + + adapterDidInvalidate: function(errors) { + this.send('becameInvalid', errors); + }, + + adapterDidError: function() { + this.send('becameError'); + }, + + /** + @private + + Override the default event firing from Ember.Evented to + also call methods with the given name. + */ + trigger: function(name) { + Ember.tryInvoke(this, name, [].slice.call(arguments, 1)); + this._super.apply(this, arguments); + } +}); + +// Helper function to generate store aliases. +// This returns a function that invokes the named alias +// on the default store, but injects the class as the +// first parameter. +var storeAlias = function(methodName) { + return function() { + var store = get(DS, 'defaultStore'), + args = [].slice.call(arguments); + + args.unshift(this); + return store[methodName].apply(store, args); + }; +}; + +DS.Model.reopenClass({ + isLoaded: storeAlias('recordIsLoaded'), + find: storeAlias('find'), + all: storeAlias('all'), + filter: storeAlias('filter'), + + _create: DS.Model.create, + + create: function() { + throw new Ember.Error("You should not call `create` on a model. Instead, call `createRecord` with the attributes you would like to set."); + }, + + createRecord: storeAlias('createRecord') +}); + +})(); + + + +(function() { +var get = Ember.get; +DS.Model.reopenClass({ + attributes: Ember.computed(function() { + var map = Ember.Map.create(); + + this.eachComputedProperty(function(name, meta) { + if (meta.isAttribute) { + Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.toString(), name !== 'id'); + + meta.name = name; + map.set(name, meta); + } + }); + + return map; + }) +}); + +var AttributeChange = DS.AttributeChange = function(options) { + this.reference = options.reference; + this.store = options.store; + this.name = options.name; + this.oldValue = options.oldValue; +}; + +AttributeChange.createChange = function(options) { + return new AttributeChange(options); +}; + +AttributeChange.prototype = { + sync: function() { + this.store.recordAttributeDidChange(this.reference, this.name, this.value, this.oldValue); + + // TODO: Use this object in the commit process + this.destroy(); + }, + + destroy: function() { + delete this.store.recordForReference(this.reference)._changesToSync[this.name]; + } +}; + +DS.Model.reopen({ + eachAttribute: function(callback, binding) { + get(this.constructor, 'attributes').forEach(function(name, meta) { + callback.call(binding, name, meta); + }, binding); + }, + + attributeWillChange: Ember.beforeObserver(function(record, key) { + var reference = get(record, '_reference'), + store = get(record, 'store'); + + record.send('willSetProperty', { reference: reference, store: store, name: key }); + }), + + attributeDidChange: Ember.observer(function(record, key) { + record.send('didSetProperty', { name: key }); + }) +}); + +function getAttr(record, options, key) { + var attributes = get(record, 'data').attributes; + var value = attributes[key]; + + if (value === undefined) { + value = options.defaultValue; + } + + return value; +} + +DS.attr = function(type, options) { + options = options || {}; + + var meta = { + type: type, + isAttribute: true, + options: options + }; + + return Ember.computed(function(key, value, oldValue) { + var data; + + if (arguments.length > 1) { + Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.constructor.toString(), key !== 'id'); + } else { + value = getAttr(this, options, key); + } + + return value; + // `data` is never set directly. However, it may be + // invalidated from the state manager's setData + // event. + }).property('data').meta(meta); +}; + + +})(); + + + +(function() { + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set, + none = Ember.isNone; + +DS.belongsTo = function(type, options) { + Ember.assert("The first argument DS.belongsTo must be a model type or string, like DS.belongsTo(App.Person)", !!type && (typeof type === 'string' || DS.Model.detect(type))); + + options = options || {}; + + var meta = { type: type, isRelationship: true, options: options, kind: 'belongsTo' }; + + return Ember.computed(function(key, value) { + if (arguments.length === 2) { + return value === undefined ? null : value; + } + + var data = get(this, 'data').belongsTo, + store = get(this, 'store'), id; + + if (typeof type === 'string') { + type = get(this, type, false) || get(Ember.lookup, type); + } + + id = data[key]; + + if(!id) { + return null; + } else if (typeof id === 'object') { + return store.findByClientId(type, id.clientId); + } else { + return store.find(type, id); + } + }).property('data').meta(meta); +}; + +/** + These observers observe all `belongsTo` relationships on the record. See + `relationships/ext` to see how these observers get their dependencies. + +*/ + +DS.Model.reopen({ + /** @private */ + belongsToWillChange: Ember.beforeObserver(function(record, key) { + if (get(record, 'isLoaded')) { + var oldParent = get(record, key); + + var childId = get(record, 'clientId'), + store = get(record, 'store'); + if (oldParent){ + var change = DS.RelationshipChange.createChange(childId, get(oldParent, 'clientId'), store, { key: key, kind:"belongsTo", changeType: "remove" }); + change.sync(); + this._changesToSync[key] = change; + } + } + }), + + /** @private */ + belongsToDidChange: Ember.immediateObserver(function(record, key) { + if (get(record, 'isLoaded')) { + var newParent = get(record, key); + if(newParent){ + var childId = get(record, 'clientId'), + store = get(record, 'store'); + var change = DS.RelationshipChange.createChange(childId, get(newParent, 'clientId'), store, { key: key, kind:"belongsTo", changeType: "add" }); + change.sync(); + if(this._changesToSync[key]){ + DS.OneToManyChange.ensureSameTransaction([change, this._changesToSync[key]], store); + } + } + } + delete this._changesToSync[key]; + }) +}); + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set; +var hasRelationship = function(type, options) { + options = options || {}; + + var meta = { type: type, isRelationship: true, options: options, kind: 'hasMany' }; + + return Ember.computed(function(key, value) { + var data = get(this, 'data').hasMany, + store = get(this, 'store'), + ids, relationship; + + if (typeof type === 'string') { + type = get(this, type, false) || get(Ember.lookup, type); + } + + ids = data[key]; + relationship = store.findMany(type, ids || [], this, meta); + set(relationship, 'owner', this); + set(relationship, 'name', key); + + return relationship; + }).property().meta(meta); +}; + +DS.hasMany = function(type, options) { + Ember.assert("The type passed to DS.hasMany must be defined", !!type); + return hasRelationship(type, options); +}; + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set; + +/** + @private + + This file defines several extensions to the base `DS.Model` class that + add support for one-to-many relationships. +*/ + +DS.Model.reopen({ + // This Ember.js hook allows an object to be notified when a property + // is defined. + // + // In this case, we use it to be notified when an Ember Data user defines a + // belongs-to relationship. In that case, we need to set up observers for + // each one, allowing us to track relationship changes and automatically + // reflect changes in the inverse has-many array. + // + // This hook passes the class being set up, as well as the key and value + // being defined. So, for example, when the user does this: + // + // DS.Model.extend({ + // parent: DS.belongsTo(App.User) + // }); + // + // This hook would be called with "parent" as the key and the computed + // property returned by `DS.belongsTo` as the value. + didDefineProperty: function(proto, key, value) { + // Check if the value being set is a computed property. + if (value instanceof Ember.Descriptor) { + + // If it is, get the metadata for the relationship. This is + // populated by the `DS.belongsTo` helper when it is creating + // the computed property. + var meta = value.meta(); + + if (meta.isRelationship && meta.kind === 'belongsTo') { + Ember.addObserver(proto, key, null, 'belongsToDidChange'); + Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange'); + } + + if (meta.isAttribute) { + Ember.addObserver(proto, key, null, 'attributeDidChange'); + Ember.addBeforeObserver(proto, key, null, 'attributeWillChange'); + } + + meta.parentType = proto.constructor; + } + } +}); + +/** + These DS.Model extensions add class methods that provide relationship + introspection abilities about relationships. + + A note about the computed properties contained here: + + **These properties are effectively sealed once called for the first time.** + To avoid repeatedly doing expensive iteration over a model's fields, these + values are computed once and then cached for the remainder of the runtime of + your application. + + If your application needs to modify a class after its initial definition + (for example, using `reopen()` to add additional attributes), make sure you + do it before using your model with the store, which uses these properties + extensively. +*/ + +DS.Model.reopenClass({ + /** + For a given relationship name, returns the model type of the relationship. + + For example, if you define a model like this: + + App.Post = DS.Model.extend({ + comments: DS.hasMany(App.Comment) + }); + + Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`. + + @param {String} name the name of the relationship + @return {subclass of DS.Model} the type of the relationship, or undefined + */ + typeForRelationship: function(name) { + var relationship = get(this, 'relationshipsByName').get(name); + return relationship && relationship.type; + }, + + /** + The model's relationships as a map, keyed on the type of the + relationship. The value of each entry is an array containing a descriptor + for each relationship with that type, describing the name of the relationship + as well as the type. + + For example, given the following model definition: + + App.Blog = DS.Model.extend({ + users: DS.hasMany(App.User), + owner: DS.belongsTo(App.User), + + posts: DS.hasMany(App.Post) + }); + + This computed property would return a map describing these + relationships, like this: + + var relationships = Ember.get(App.Blog, 'relationships'); + associatons.get(App.User); + //=> [ { name: 'users', kind: 'hasMany' }, + // { name: 'owner', kind: 'belongsTo' } ] + relationships.get(App.Post); + //=> [ { name: 'posts', kind: 'hasMany' } ] + + @type Ember.Map + @readOnly + */ + relationships: Ember.computed(function() { + var map = new Ember.MapWithDefault({ + defaultValue: function() { return []; } + }); + + // Loop through each computed property on the class + this.eachComputedProperty(function(name, meta) { + + // If the computed property is a relationship, add + // it to the map. + if (meta.isRelationship) { + if (typeof meta.type === 'string') { + meta.type = Ember.get(Ember.lookup, meta.type); + } + + var relationshipsForType = map.get(meta.type); + + relationshipsForType.push({ name: name, kind: meta.kind }); + } + }); + + return map; + }), + + /** + A hash containing lists of the model's relationships, grouped + by the relationship kind. For example, given a model with this + definition: + + App.Blog = DS.Model.extend({ + users: DS.hasMany(App.User), + owner: DS.belongsTo(App.User), + + posts: DS.hasMany(App.Post) + }); + + This property would contain the following: + + var relationshipNames = Ember.get(App.Blog, 'relationshipNames'); + relationshipNames.hasMany; + //=> ['users', 'posts'] + relationshipNames.belongsTo; + //=> ['owner'] + + @type Object + @readOnly + */ + relationshipNames: Ember.computed(function() { + var names = { hasMany: [], belongsTo: [] }; + + this.eachComputedProperty(function(name, meta) { + if (meta.isRelationship) { + names[meta.kind].push(name); + } + }); + + return names; + }), + + /** + A map whose keys are the relationships of a model and whose values are + relationship descriptors. + + For example, given a model with this + definition: + + App.Blog = DS.Model.extend({ + users: DS.hasMany(App.User), + owner: DS.belongsTo(App.User), + + posts: DS.hasMany(App.Post) + }); + + This property would contain the following: + + var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName'); + relationshipsByName.get('users'); + //=> { key: 'users', kind: 'hasMany', type: App.User } + relationshipsByName.get('owner'); + //=> { key: 'owner', kind: 'belongsTo', type: App.User } + + @type Ember.Map + @readOnly + */ + relationshipsByName: Ember.computed(function() { + var map = Ember.Map.create(), type; + + this.eachComputedProperty(function(name, meta) { + if (meta.isRelationship) { + meta.key = name; + type = meta.type; + + if (typeof type === 'string') { + type = get(this, type, false) || get(Ember.lookup, type); + meta.type = type; + } + + map.set(name, meta); + } + }); + + return map; + }), + + /** + A map whose keys are the fields of the model and whose values are strings + describing the kind of the field. A model's fields are the union of all of its + attributes and relationships. + + For example: + + App.Blog = DS.Model.extend({ + users: DS.hasMany(App.User), + owner: DS.belongsTo(App.User), + + posts: DS.hasMany(App.Post), + + title: DS.attr('string') + }); + + var fields = Ember.get(App.Blog, 'fields'); + fields.forEach(function(field, kind) { + console.log(field, kind); + }); + + // prints: + // users, hasMany + // owner, belongsTo + // posts, hasMany + // title, attribute + + @type Ember.Map + @readOnly + */ + fields: Ember.computed(function() { + var map = Ember.Map.create(), type; + + this.eachComputedProperty(function(name, meta) { + if (meta.isRelationship) { + map.set(name, meta.kind); + } else if (meta.isAttribute) { + map.set(name, 'attribute'); + } + }); + + return map; + }), + + /** + Given a callback, iterates over each of the relationships in the model, + invoking the callback with the name of each relationship and its relationship + descriptor. + + @param {Function} callback the callback to invoke + @param {any} binding the value to which the callback's `this` should be bound + */ + eachRelationship: function(callback, binding) { + get(this, 'relationshipsByName').forEach(function(name, relationship) { + callback.call(binding, name, relationship); + }); + } +}); + +DS.Model.reopen({ + /** + Given a callback, iterates over each of the relationships in the model, + invoking the callback with the name of each relationship and its relationship + descriptor. + + @param {Function} callback the callback to invoke + @param {any} binding the value to which the callback's `this` should be bound + */ + eachRelationship: function(callback, binding) { + this.constructor.eachRelationship(callback, binding); + } +}); + +/** + @private + + Helper method to look up the name of the inverse of a relationship. + + In a has-many relationship, there are always two sides: the `belongsTo` side + and the `hasMany` side. When one side changes, the other side should be updated + automatically. + + Given a model, the model of the inverse, and the kind of the relationship, this + helper returns the name of the relationship on the inverse. + + For example, imagine the following two associated models: + + App.Post = DS.Model.extend({ + comments: DS.hasMany('App.Comment') + }); + + App.Comment = DS.Model.extend({ + post: DS.belongsTo('App.Post') + }); + + If the `post` property of a `Comment` was modified, Ember Data would invoke + this helper like this: + + DS._inverseNameFor(App.Comment, App.Post, 'hasMany'); + //=> 'comments' + + Ember Data uses the name of the relationship returned to reflect the changed + relationship on the other side. +*/ +DS._inverseRelationshipFor = function(modelType, inverseModelType) { + var relationshipMap = get(modelType, 'relationships'), + possibleRelationships = relationshipMap.get(inverseModelType), + possible, actual, oldValue; + + if (!possibleRelationships) { return; } + if (possibleRelationships.length > 1) { return; } + return possibleRelationships[0]; +}; + +/** + @private + + Given a model and a relationship name, returns the model type of + the named relationship. + + App.Post = DS.Model.extend({ + comments: DS.hasMany('App.Comment') + }); + + DS._inverseTypeFor(App.Post, 'comments'); + //=> App.Comment + @param {DS.Model class} modelType + @param {String} relationshipName + @return {DS.Model class} +*/ +DS._inverseTypeFor = function(modelType, relationshipName) { + var relationships = get(modelType, 'relationshipsByName'), + relationship = relationships.get(relationshipName); + + if (relationship) { return relationship.type; } +}; + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set; +var forEach = Ember.EnumerableUtils.forEach; + +DS.RelationshipChange = function(options) { + this.firstRecordClientId = options.firstRecordClientId; + this.firstRecordKind = options.firstRecordKind; + this.firstRecordName = options.firstRecordName; + this.secondRecordClientId = options.secondRecordClientId; + this.secondRecordKind = options.secondRecordKind; + this.secondRecordName = options.secondRecordName; + this.store = options.store; + this.committed = {}; + this.changeType = options.changeType; +}; + +DS.RelationshipChangeAdd = function(options){ + DS.RelationshipChange.call(this, options); +}; + +DS.RelationshipChangeRemove = function(options){ + DS.RelationshipChange.call(this, options); +}; + +/** @private */ +DS.RelationshipChange.create = function(options) { + return new DS.RelationshipChange(options); +}; + +/** @private */ +DS.RelationshipChangeAdd.create = function(options) { + return new DS.RelationshipChangeAdd(options); +}; + +/** @private */ +DS.RelationshipChangeRemove.create = function(options) { + return new DS.RelationshipChangeRemove(options); +}; + +DS.OneToManyChange = {}; +DS.OneToNoneChange = {}; +DS.ManyToNoneChange = {}; +DS.OneToOneChange = {}; +DS.ManyToManyChange = {}; + +DS.RelationshipChange._createChange = function(options){ + if(options.changeType === "add"){ + return DS.RelationshipChangeAdd.create(options); + } + if(options.changeType === "remove"){ + return DS.RelationshipChangeRemove.create(options); + } +}; + + +DS.RelationshipChange.determineRelationshipType = function(recordType, knownSide){ + var knownKey = knownSide.key, key, type, otherContainerType,assoc; + var knownContainerType = knownSide.kind; + var options = recordType.metaForProperty(knownKey).options; + var otherType = DS._inverseTypeFor(recordType, knownKey); + + if(options.inverse){ + key = options.inverse; + otherContainerType = get(otherType, 'relationshipsByName').get(key).kind; + } + else if(assoc = DS._inverseRelationshipFor(otherType, recordType)){ + key = assoc.name; + otherContainerType = assoc.kind; + } + if(!key){ + return knownContainerType === "belongsTo" ? "oneToNone" : "manyToNone"; + } + else{ + if(otherContainerType === "belongsTo"){ + return knownContainerType === "belongsTo" ? "oneToOne" : "manyToOne"; + } + else{ + return knownContainerType === "belongsTo" ? "oneToMany" : "manyToMany"; + } + } + +}; + +DS.RelationshipChange.createChange = function(firstRecordClientId, secondRecordClientId, store, options){ + // Get the type of the child based on the child's client ID + var firstRecordType = store.typeForClientId(firstRecordClientId), key, changeType; + changeType = DS.RelationshipChange.determineRelationshipType(firstRecordType, options); + if (changeType === "oneToMany"){ + return DS.OneToManyChange.createChange(firstRecordClientId, secondRecordClientId, store, options); + } + else if (changeType === "manyToOne"){ + return DS.OneToManyChange.createChange(secondRecordClientId, firstRecordClientId, store, options); + } + else if (changeType === "oneToNone"){ + return DS.OneToNoneChange.createChange(firstRecordClientId, "", store, options); + } + else if (changeType === "manyToNone"){ + return DS.ManyToNoneChange.createChange(firstRecordClientId, "", store, options); + } + else if (changeType === "oneToOne"){ + return DS.OneToOneChange.createChange(firstRecordClientId, secondRecordClientId, store, options); + } + else if (changeType === "manyToMany"){ + return DS.ManyToManyChange.createChange(firstRecordClientId, secondRecordClientId, store, options); + } +}; + +/** @private */ +DS.OneToNoneChange.createChange = function(childClientId, parentClientId, store, options) { + var key = options.key; + var change = DS.RelationshipChange._createChange({ + firstRecordClientId: childClientId, + store: store, + changeType: options.changeType, + firstRecordName: key, + firstRecordKind: "belongsTo" + }); + + store.addRelationshipChangeFor(childClientId, key, parentClientId, null, change); + + return change; +}; + +/** @private */ +DS.ManyToNoneChange.createChange = function(childClientId, parentClientId, store, options) { + var key = options.key; + var change = DS.RelationshipChange._createChange({ + secondRecordClientId: childClientId, + store: store, + changeType: options.changeType, + secondRecordName: options.key, + secondRecordKind: "hasMany" + }); + + store.addRelationshipChangeFor(childClientId, key, parentClientId, null, change); + return change; +}; + + +/** @private */ +DS.ManyToManyChange.createChange = function(childClientId, parentClientId, store, options) { + // Get the type of the child based on the child's client ID + var childType = store.typeForClientId(childClientId), key; + + // If the name of the belongsTo side of the relationship is specified, + // use that + // If the type of the parent is specified, look it up on the child's type + // definition. + key = options.key; + + var change = DS.RelationshipChange._createChange({ + firstRecordClientId: childClientId, + secondRecordClientId: parentClientId, + firstRecordKind: "hasMany", + secondRecordKind: "hasMany", + store: store, + changeType: options.changeType, + firstRecordName: key + }); + + store.addRelationshipChangeFor(childClientId, key, parentClientId, null, change); + + + return change; +}; + +/** @private */ +DS.OneToOneChange.createChange = function(childClientId, parentClientId, store, options) { + // Get the type of the child based on the child's client ID + var childType = store.typeForClientId(childClientId), key; + + // If the name of the belongsTo side of the relationship is specified, + // use that + // If the type of the parent is specified, look it up on the child's type + // definition. + if (options.parentType) { + key = inverseBelongsToName(options.parentType, childType, options.key); + //DS.OneToOneChange.maintainInvariant( options, store, childClientId, key ); + } else if (options.key) { + key = options.key; + } else { + Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); + } + + var change = DS.RelationshipChange._createChange({ + firstRecordClientId: childClientId, + secondRecordClientId: parentClientId, + firstRecordKind: "belongsTo", + secondRecordKind: "belongsTo", + store: store, + changeType: options.changeType, + firstRecordName: key + }); + + store.addRelationshipChangeFor(childClientId, key, parentClientId, null, change); + + + return change; +}; + +DS.OneToOneChange.maintainInvariant = function(options, store, childClientId, key){ + if (options.changeType === "add" && store.recordIsMaterialized(childClientId)) { + var child = store.findByClientId(null, childClientId); + var oldParent = get(child, key); + if (oldParent){ + var correspondingChange = DS.OneToOneChange.createChange(childClientId, oldParent.get('clientId'), store, { + parentType: options.parentType, + hasManyName: options.hasManyName, + changeType: "remove", + key: options.key + }); + store.addRelationshipChangeFor(childClientId, key, options.parentClientId , null, correspondingChange); + correspondingChange.sync(); + } + } +}; + +/** @private */ +DS.OneToManyChange.createChange = function(childClientId, parentClientId, store, options) { + // Get the type of the child based on the child's client ID + var childType = store.typeForClientId(childClientId), key; + + // If the name of the belongsTo side of the relationship is specified, + // use that + // If the type of the parent is specified, look it up on the child's type + // definition. + if (options.parentType) { + key = inverseBelongsToName(options.parentType, childType, options.key); + DS.OneToManyChange.maintainInvariant( options, store, childClientId, key ); + } else if (options.key) { + key = options.key; + } else { + Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); + } + + var change = DS.RelationshipChange._createChange({ + firstRecordClientId: childClientId, + secondRecordClientId: parentClientId, + firstRecordKind: "belongsTo", + secondRecordKind: "hasMany", + store: store, + changeType: options.changeType, + firstRecordName: key + }); + + store.addRelationshipChangeFor(childClientId, key, parentClientId, null, change); + + + return change; +}; + + +DS.OneToManyChange.maintainInvariant = function(options, store, childClientId, key){ + if (options.changeType === "add" && store.recordIsMaterialized(childClientId)) { + var child = store.findByClientId(null, childClientId); + var oldParent = get(child, key); + if (oldParent){ + var correspondingChange = DS.OneToManyChange.createChange(childClientId, oldParent.get('clientId'), store, { + parentType: options.parentType, + hasManyName: options.hasManyName, + changeType: "remove", + key: options.key + }); + store.addRelationshipChangeFor(childClientId, key, options.parentClientId , null, correspondingChange); + correspondingChange.sync(); + } + } +}; + +DS.OneToManyChange.ensureSameTransaction = function(changes, store){ + var records = Ember.A(); + forEach(changes, function(change){ + records.addObject(change.getSecondRecord()); + records.addObject(change.getFirstRecord()); + }); + var transaction = store.ensureSameTransaction(records); + forEach(changes, function(change){ + change.transaction = transaction; + }); +}; + +DS.RelationshipChange.prototype = { + + /** + Get the child type and ID, if available. + + @returns {Array} an array of type and ID + */ + getChildTypeAndId: function() { + return this.getTypeAndIdFor(this.child); + }, + + getSecondRecordName: function() { + var name = this.secondRecordName, store = this.store, parent; + + if (!name) { + parent = this.secondRecordClientId; + if (!parent) { return; } + + var childType = store.typeForClientId(this.firstRecordClientId); + var inverseType = DS._inverseTypeFor(childType, this.firstRecordName); + name = inverseHasManyName(inverseType, childType, this.firstRecordName); + this.secondRecordName = name; + } + + return name; + }, + + /** + Get the name of the relationship on the belongsTo side. + + @returns {String} + */ + getFirstRecordName: function() { + var name = this.firstRecordName, store = this.store, parent; + + if (!name) { + parent = this.secondRecordClientId; + if (!parent) { return; } + + var childType = store.typeForClientId(this.firstRecordClientId); + var parentType = store.typeForClientId(parent); + if (!(childType && parentType)) { return; } + name = DS._inverseRelationshipFor(childType, parentType).name; + + this.firstRecordName = name; + } + + return name; + }, + + /** @private */ + getTypeAndIdFor: function(clientId) { + if (clientId) { + var store = this.store; + + return [ + store.typeForClientId(clientId), + store.idForClientId(clientId) + ]; + } + }, + + /** @private */ + destroy: function() { + var childClientId = this.firstRecordClientId, + belongsToName = this.getFirstRecordName(), + hasManyName = this.getSecondRecordName(), + store = this.store, + child, oldParent, newParent, lastParent, transaction; + + store.removeRelationshipChangeFor(childClientId, belongsToName, this.secondRecordClientId, hasManyName, this.changeType); + + if (transaction = this.transaction) { + transaction.relationshipBecameClean(this); + } + }, + + /** @private */ + getByClientId: function(clientId) { + var store = this.store; + + // return null or undefined if the original clientId was null or undefined + if (!clientId) { return clientId; } + + if (store.recordIsMaterialized(clientId)) { + return store.findByClientId(null, clientId); + } + }, + + getSecondRecord: function(){ + return this.getByClientId(this.secondRecordClientId); + }, + + /** @private */ + getFirstRecord: function() { + return this.getByClientId(this.firstRecordClientId); + }, + + /** + @private + + Make sure that all three parts of the relationship change are part of + the same transaction. If any of the three records is clean and in the + default transaction, and the rest are in a different transaction, move + them all into that transaction. + */ + ensureSameTransaction: function() { + var child = this.getFirstRecord(), + parentRecord = this.getSecondRecord(); + + var transaction = this.store.ensureSameTransaction([child, parentRecord]); + + this.transaction = transaction; + return transaction; + }, + + callChangeEvents: function(){ + var hasManyName = this.getSecondRecordName(), + belongsToName = this.getFirstRecordName(), + child = this.getFirstRecord(), + parentRecord = this.getSecondRecord(); + + var dirtySet = new Ember.OrderedSet(); + + // TODO: This implementation causes a race condition in key-value + // stores. The fix involves buffering changes that happen while + // a record is loading. A similar fix is required for other parts + // of ember-data, and should be done as new infrastructure, not + // a one-off hack. [tomhuda] + if (parentRecord && get(parentRecord, 'isLoaded')) { + this.store.recordHasManyDidChange(dirtySet, parentRecord, this); + } + + if (child) { + this.store.recordBelongsToDidChange(dirtySet, child, this); + } + + dirtySet.forEach(function(record) { + record.adapterDidDirty(); + }); + }, + + coalesce: function(){ + var relationshipPairs = this.store.relationshipChangePairsFor(this.firstRecordClientId); + forEach(relationshipPairs, function(pair){ + var addedChange = pair["add"]; + var removedChange = pair["remove"]; + if(addedChange && removedChange) { + addedChange.destroy(); + removedChange.destroy(); + } + }); + } +}; + +DS.RelationshipChangeAdd.prototype = Ember.create(DS.RelationshipChange.create({})); +DS.RelationshipChangeRemove.prototype = Ember.create(DS.RelationshipChange.create({})); + +DS.RelationshipChangeAdd.prototype.changeType = "add"; +DS.RelationshipChangeAdd.prototype.sync = function() { + var secondRecordName = this.getSecondRecordName(), + firstRecordName = this.getFirstRecordName(), + firstRecord = this.getFirstRecord(), + secondRecord = this.getSecondRecord(); + + //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); + //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); + + var transaction = this.ensureSameTransaction(); + transaction.relationshipBecameDirty(this); + + this.callChangeEvents(); + + if (secondRecord && firstRecord) { + if(this.secondRecordKind === "belongsTo"){ + secondRecord.suspendRelationshipObservers(function(){ + set(secondRecord, secondRecordName, firstRecord); + }); + + } + else if(this.secondRecordKind === "hasMany"){ + secondRecord.suspendRelationshipObservers(function(){ + get(secondRecord, secondRecordName).addObject(firstRecord); + }); + } + } + + if (firstRecord && secondRecord && get(firstRecord, firstRecordName) !== secondRecord) { + if(this.firstRecordKind === "belongsTo"){ + firstRecord.suspendRelationshipObservers(function(){ + set(firstRecord, firstRecordName, secondRecord); + }); + } + else if(this.firstdRecordKind === "hasMany"){ + firstRecord.suspendRelationshipObservers(function(){ + get(firstRecord, firstRecordName).addObject(secondRecord); + }); + } + } + + this.coalesce(); +}; + +DS.RelationshipChangeRemove.prototype.changeType = "remove"; +DS.RelationshipChangeRemove.prototype.sync = function() { + var secondRecordName = this.getSecondRecordName(), + firstRecordName = this.getFirstRecordName(), + firstRecord = this.getFirstRecord(), + secondRecord = this.getSecondRecord(); + + //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); + //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); + + var transaction = this.ensureSameTransaction(firstRecord, secondRecord, secondRecordName, firstRecordName); + transaction.relationshipBecameDirty(this); + + this.callChangeEvents(); + + if (secondRecord && firstRecord) { + if(this.secondRecordKind === "belongsTo"){ + set(secondRecord, secondRecordName, null); + } + else if(this.secondRecordKind === "hasMany"){ + secondRecord.suspendRelationshipObservers(function(){ + get(secondRecord, secondRecordName).removeObject(firstRecord); + }); + } + } + + if (firstRecord && get(firstRecord, firstRecordName)) { + if(this.firstRecordKind === "belongsTo"){ + firstRecord.suspendRelationshipObservers(function(){ + set(firstRecord, firstRecordName, null); + }); + } + else if(this.firstdRecordKind === "hasMany"){ + firstRecord.suspendRelationshipObservers(function(){ + get(firstRecord, firstRecordName).removeObject(secondRecord); + }); + } + } + + this.coalesce(); +}; + +function inverseBelongsToName(parentType, childType, hasManyName) { + // Get the options passed to the parent's DS.hasMany() + var options = parentType.metaForProperty(hasManyName).options; + var belongsToName; + + if (belongsToName = options.inverse) { + return belongsToName; + } + + return DS._inverseRelationshipFor(childType, parentType).name; +} + +function inverseHasManyName(parentType, childType, belongsToName) { + var options = childType.metaForProperty(belongsToName).options; + var hasManyName; + + if (hasManyName = options.inverse) { + return hasManyName; + } + + return DS._inverseRelationshipFor(parentType, childType).name; +} + +})(); + + + +(function() { + +})(); + + + +(function() { +var set = Ember.set; + +/** + This code registers an injection for Ember.Application. + + If an Ember.js developer defines a subclass of DS.Store on their application, + this code will automatically instantiate it and make it available on the + router. + + Additionally, after an application's controllers have been injected, they will + each have the store made available to them. + + For example, imagine an Ember.js application with the following classes: + + App.Store = DS.Store.extend({ + adapter: 'App.MyCustomAdapter' + }); + + App.PostsController = Ember.ArrayController.extend({ + // ... + }); + + When the application is initialized, `App.Store` will automatically be + instantiated, and the instance of `App.PostsController` will have its `store` + property set to that instance. + + Note that this code will only be run if the `ember-application` package is + loaded. If Ember Data is being used in an environment other than a + typical application (e.g., node.js where only `ember-runtime` is available), + this code will be ignored. +*/ + +Ember.onLoad('Ember.Application', function(Application) { + if (Application.registerInjection) { + Application.registerInjection({ + name: "store", + before: "controllers", + + // If a store subclass is defined, like App.Store, + // instantiate it and inject it into the router. + injection: function(app, stateManager, property) { + if (!stateManager) { return; } + if (property === 'Store') { + set(stateManager, 'store', app[property].create()); + } + } + }); + + Application.registerInjection({ + name: "giveStoreToControllers", + after: ['store','controllers'], + + // For each controller, set its `store` property + // to the DS.Store instance we created above. + injection: function(app, stateManager, property) { + if (!stateManager) { return; } + if (/^[A-Z].*Controller$/.test(property)) { + var controllerName = property.charAt(0).toLowerCase() + property.substr(1); + var store = stateManager.get('store'); + var controller = stateManager.get(controllerName); + if(!controller) { return; } + + controller.set('store', store); + } + } + }); + } else if (Application.initializer) { + Application.initializer({ + name: "store", + + initialize: function(container, application) { + container.register('store', 'main', application.Store); + + // Eagerly generate the store so defaultStore is populated. + // TODO: Do this in a finisher hook + container.lookup('store:main'); + } + }); + + Application.initializer({ + name: "injectStore", + + initialize: function(container) { + container.typeInjection('controller', 'store', 'store:main'); + container.typeInjection('route', 'store', 'store:main'); + } + }); + } +}); + +})(); + + + +(function() { +var get = Ember.get, set = Ember.set, map = Ember.ArrayPolyfills.map, isNone = Ember.isNone; + +function mustImplement(name) { + return function() { + throw new Ember.Error("Your serializer " + this.toString() + " does not implement the required method " + name); + }; +} + +/** + A serializer is responsible for serializing and deserializing a group of + records. + + `DS.Serializer` is an abstract base class designed to help you build a + serializer that can read to and write from any serialized form. While most + applications will use `DS.JSONSerializer`, which reads and writes JSON, the + serializer architecture allows your adapter to transmit things like XML, + strings, or custom binary data. + + Typically, your application's `DS.Adapter` is responsible for both creating a + serializer as well as calling the appropriate methods when it needs to + materialize data or serialize a record. + + The serializer API is designed as a series of layered hooks that you can + override to customize any of the individual steps of serialization and + deserialization. + + The hooks are organized by the three responsibilities of the serializer: + + 1. Determining naming conventions + 2. Serializing records into a serialized form + 3. Deserializing records from a serialized form + + Because Ember Data lazily materializes records, the deserialization + step, and therefore the hooks you implement, are split into two phases: + + 1. Extraction, where the serialized forms for multiple records are + extracted from a single payload. The IDs of each record are also + extracted for indexing. + 2. Materialization, where a newly-created record has its attributes + and relationships initialized based on the serialized form loaded + by the adapter. + + Additionally, a serializer can convert values from their JavaScript + versions into their serialized versions via a declarative API. + + ## Naming Conventions + + One of the most common uses of the serializer is to map attribute names + from the serialized form to your `DS.Model`. For example, in your model, + you may have an attribute called `firstName`: + + ```javascript + App.Person = DS.Model.extend({ + firstName: DS.attr('string') + }); + ``` + + However, because the web API your adapter is communicating with is + legacy, it calls this attribute `FIRST_NAME`. + + You can determine the attribute name used in the serialized form + by implementing `keyForAttributeName`: + + ```javascript + keyForAttributeName: function(type, name) { + return name.underscore.toUpperCase(); + } + ``` + + If your attribute names are not predictable, you can re-map them + one-by-one using the `map` API: + + ```javascript + App.Person.map('App.Person', { + firstName: { key: '*API_USER_FIRST_NAME*' } + }); + ``` + + ## Serialization + + During the serialization process, a record or records are converted + from Ember.js objects into their serialized form. + + These methods are designed in layers, like a delicious 7-layer + cake (but with fewer layers). + + The main entry point for serialization is the `serialize` + method, which takes the record and options. + + The `serialize` method is responsible for: + + * turning the record's attributes (`DS.attr`) into + attributes on the JSON object. + * optionally adding the record's ID onto the hash + * adding relationships (`DS.hasMany` and `DS.belongsTo`) + to the JSON object. + + Depending on the backend, the serializer can choose + whether to include the `hasMany` or `belongsTo` + relationships on the JSON hash. + + For very custom serialization, you can implement your + own `serialize` method. In general, however, you will want + to override the hooks described below. + + ### Adding the ID + + The default `serialize` will optionally call your serializer's + `addId` method with the JSON hash it is creating, the + record's type, and the record's ID. The `serialize` method + will not call `addId` if the record's ID is undefined. + + Your adapter must specifically request ID inclusion by + passing `{ includeId: true }` as an option to `serialize`. + + NOTE: You may not want to include the ID when updating an + existing record, because your server will likely disallow + changing an ID after it is created, and the PUT request + itself will include the record's identification. + + By default, `addId` will: + + 1. Get the primary key name for the record by calling + the serializer's `primaryKey` with the record's type. + Unless you override the `primaryKey` method, this + will be `'id'`. + 2. Assign the record's ID to the primary key in the + JSON hash being built. + + If your backend expects a JSON object with the primary + key at the root, you can just override the `primaryKey` + method on your serializer subclass. + + Otherwise, you can override the `addId` method for + more specialized handling. + + ### Adding Attributes + + By default, the serializer's `serialize` method will call + `addAttributes` with the JSON object it is creating + and the record to serialize. + + The `addAttributes` method will then call `addAttribute` + in turn, with the JSON object, the record to serialize, + the attribute's name and its type. + + Finally, the `addAttribute` method will serialize the + attribute: + + 1. It will call `keyForAttributeName` to determine + the key to use in the JSON hash. + 2. It will get the value from the record. + 3. It will call `serializeValue` with the attribute's + value and attribute type to convert it into a + JSON-compatible value. For example, it will convert a + Date into a String. + + If your backend expects a JSON object with attributes as + keys at the root, you can just override the `serializeValue` + and `keyForAttributeName` methods in your serializer + subclass and let the base class do the heavy lifting. + + If you need something more specialized, you can probably + override `addAttribute` and let the default `addAttributes` + handle the nitty gritty. + + ### Adding Relationships + + By default, `serialize` will call your serializer's + `addRelationships` method with the JSON object that is + being built and the record being serialized. The default + implementation of this method is to loop over all of the + relationships defined on your record type and: + + * If the relationship is a `DS.hasMany` relationship, + call `addHasMany` with the JSON object, the record + and a description of the relationship. + * If the relationship is a `DS.belongsTo` relationship, + call `addBelongsTo` with the JSON object, the record + and a description of the relationship. + + The relationship description has the following keys: + + * `type`: the class of the associated information (the + first parameter to `DS.hasMany` or `DS.belongsTo`) + * `kind`: either `hasMany` or `belongsTo` + + The relationship description may get additional + information in the future if more capabilities or + relationship types are added. However, it will + remain backwards-compatible, so the mere existence + of new features should not break existing adapters. +*/ +DS.Serializer = Ember.Object.extend({ + init: function() { + this.mappings = Ember.Map.create(); + this.configurations = Ember.Map.create(); + this.globalConfigurations = {}; + }, + + extract: mustImplement('extract'), + extractMany: mustImplement('extractMany'), + + extractRecordRepresentation: function(loader, type, json, shouldSideload) { + var mapping = this.mappingForType(type); + var embeddedData, prematerialized = {}, reference; + + if (shouldSideload) { + reference = loader.sideload(type, json); + } else { + reference = loader.load(type, json); + } + + this.eachEmbeddedHasMany(type, function(name, relationship) { + var embeddedData = json[this.keyFor(relationship)]; + if (!isNone(embeddedData)) { + this.extractEmbeddedHasMany(loader, relationship, embeddedData, reference, prematerialized); + } + }, this); + + this.eachEmbeddedBelongsTo(type, function(name, relationship) { + var embeddedData = json[this.keyFor(relationship)]; + if (!isNone(embeddedData)) { + this.extractEmbeddedBelongsTo(loader, relationship, embeddedData, reference, prematerialized); + } + }, this); + + loader.prematerialize(reference, prematerialized); + + return reference; + }, + + extractEmbeddedHasMany: function(loader, relationship, array, parent, prematerialized) { + var references = map.call(array, function(item) { + if (!item) { return; } + + var reference = this.extractRecordRepresentation(loader, relationship.type, item, true); + + // If the embedded record should also be saved back when serializing the parent, + // make sure we set its parent since it will not have an ID. + var embeddedType = this.embeddedType(parent.type, relationship.key); + if (embeddedType === 'always') { + reference.parent = parent; + } + + return reference; + }, this); + + prematerialized[relationship.key] = references; + }, + + extractEmbeddedBelongsTo: function(loader, relationship, data, parent, prematerialized) { + var reference = loader.sideload(relationship.type, data); + prematerialized[relationship.key] = reference; + + // If the embedded record should also be saved back when serializing the parent, + // make sure we set its parent since it will not have an ID. + var embeddedType = this.embeddedType(parent.type, relationship.key); + if (embeddedType === 'always') { + reference.parent = parent; + } + }, + + //....................... + //. SERIALIZATION HOOKS + //....................... + + /** + The main entry point for serializing a record. While you can consider this + a hook that can be overridden in your serializer, you will have to manually + handle serialization. For most cases, there are more granular hooks that you + can override. + + If overriding this method, these are the responsibilities that you will need + to implement yourself: + + * If the option hash contains `includeId`, add the record's ID to the serialized form. + By default, `serialize` calls `addId` if appropriate. + * Add the record's attributes to the serialized form. By default, `serialize` calls + `addAttributes`. + * Add the record's relationships to the serialized form. By default, `serialize` calls + `addRelationships`. + + @param {DS.Model} record the record to serialize + @param {Object} [options] a hash of options + @returns {any} the serialized form of the record + */ + serialize: function(record, options) { + options = options || {}; + + var serialized = this.createSerializedForm(), id; + + if (options.includeId) { + if (id = get(record, 'id')) { + this._addId(serialized, record.constructor, id); + } + } + + this.addAttributes(serialized, record); + this.addRelationships(serialized, record); + + return serialized; + }, + + /** + @private + + Given an attribute type and value, convert the value into the + serialized form using the transform registered for that type. + + @param {any} value the value to convert to the serialized form + @param {String} attributeType the registered type (e.g. `string` + or `boolean`) + @returns {any} the serialized form of the value + */ + serializeValue: function(value, attributeType) { + var transform = this.transforms ? this.transforms[attributeType] : null; + + Ember.assert("You tried to use an attribute type (" + attributeType + ") that has not been registered", transform); + return transform.serialize(value); + }, + + /** + A hook you can use to normalize IDs before adding them to the + serialized representation. + + Because the store coerces all IDs to strings for consistency, + this is the opportunity for the serializer to, for example, + convert numerical IDs back into number form. + + @param {String} id the id from the record + @returns {any} the serialized representation of the id + */ + serializeId: function(id) { + if (isNaN(id)) { return id; } + return +id; + }, + + /** + A hook you can use to change how attributes are added to the serialized + representation of a record. + + By default, `addAttributes` simply loops over all of the attributes of the + passed record, maps the attribute name to the key for the serialized form, + and invokes any registered transforms on the value. It then invokes the + more granular `addAttribute` with the key and transformed value. + + Since you can override `keyForAttributeName`, `addAttribute`, and register + custom tranforms, you should rarely need to override this hook. + + @param {any} data the serialized representation that is being built + @param {DS.Model} record the record to serialize + */ + addAttributes: function(data, record) { + record.eachAttribute(function(name, attribute) { + this._addAttribute(data, record, name, attribute.type); + }, this); + }, + + /** + A hook you can use to customize how the key/value pair is added to + the serialized data. + + @param {any} serialized the serialized form being built + @param {String} key the key to add to the serialized data + @param {any} value the value to add to the serialized data + */ + addAttribute: Ember.K, + + /** + A hook you can use to customize how the record's id is added to + the serialized data. + + The `addId` hook is called with: + + * the serialized representation being built + * the resolved primary key (taking configurations and the + `primaryKey` hook into consideration) + * the serialized id (after calling the `serializeId` hook) + + @param {any} data the serialized representation that is being built + @param {String} key the resolved primary key + @param {id} id the serialized id + */ + addId: Ember.K, + + /** + A hook you can use to change how relationships are added to the serialized + representation of a record. + + By default, `addAttributes` loops over all of the relationships of the + passed record, maps the relationship names to the key for the serialized form, + and then invokes the public `addBelongsTo` and `addHasMany` hooks. + + Since you can override `keyForBelongsTo`, `keyForHasMany`, `addBelongsTo`, + `addHasMany`, and register mappings, you should rarely need to override this + hook. + + @param {any} data the serialized representation that is being built + @param {DS.Model} record the record to serialize + */ + addRelationships: function(data, record) { + record.eachRelationship(function(name, relationship) { + if (relationship.kind === 'belongsTo') { + this._addBelongsTo(data, record, name, relationship); + } else if (relationship.kind === 'hasMany') { + this._addHasMany(data, record, name, relationship); + } + }, this); + }, + + /** + A hook you can use to add a `belongsTo` relationship to the + serialized representation. + + The specifics of this hook are very adapter-specific, so there + is no default implementation. You can see `DS.JSONSerializer` + for an example of an implementation of the `addBelongsTo` hook. + + The `belongsTo` relationship object has the following properties: + + * **type** a subclass of DS.Model that is the type of the + relationship. This is the first parameter to DS.belongsTo + * **options** the options passed to the call to DS.belongsTo + * **kind** always `belongsTo` + + Additional properties may be added in the future. + + @param {any} data the serialized representation that is being built + @param {DS.Model} record the record to serialize + @param {String} key the key for the serialized object + @param {Object} relationship an object representing the relationship + */ + addBelongsTo: Ember.K, + + /** + A hook you can use to add a `hasMany` relationship to the + serialized representation. + + The specifics of this hook are very adapter-specific, so there + is no default implementation. You may not need to implement this, + for example, if your backend only expects relationships on the + child of a one to many relationship. + + The `hasMany` relationship object has the following properties: + + * **type** a subclass of DS.Model that is the type of the + relationship. This is the first parameter to DS.hasMany + * **options** the options passed to the call to DS.hasMany + * **kind** always `hasMany` + + Additional properties may be added in the future. + + @param {any} data the serialized representation that is being built + @param {DS.Model} record the record to serialize + @param {String} key the key for the serialized object + @param {Object} relationship an object representing the relationship + */ + addHasMany: Ember.K, + + /** + NAMING CONVENTIONS + + The most commonly overridden APIs of the serializer are + the naming convention methods: + + * `keyForAttributeName`: converts a camelized attribute name + into a key in the adapter-provided data hash. For example, + if the model's attribute name was `firstName`, and the + server used underscored names, you would return `first_name`. + * `primaryKey`: returns the key that should be used to + extract the id from the adapter-provided data hash. It is + also used when serializing a record. + */ + + /** + A hook you can use in your serializer subclass to customize + how an unmapped attribute name is converted into a key. + + By default, this method returns the `name` parameter. + + For example, if the attribute names in your JSON are underscored, + you will want to convert them into JavaScript conventional + camelcase: + + ```javascript + App.MySerializer = DS.Serializer.extend({ + // ... + + keyForAttributeName: function(type, name) { + return name.camelize(); + } + }); + ``` + + @param {DS.Model subclass} type the type of the record with + the attribute name `name` + @param {String} name the attribute name to convert into a key + + @returns {String} the key + */ + keyForAttributeName: function(type, name) { + return name; + }, + + /** + A hook you can use in your serializer to specify a conventional + primary key. + + By default, this method will return the string `id`. + + In general, you should not override this hook to specify a special + primary key for an individual type; use `configure` instead. + + For example, if your primary key is always `__id__`: + + ```javascript + App.MySerializer = DS.Serializer.extend({ + // ... + primaryKey: function(type) { + return '__id__'; + } + }); + ``` + + In another example, if the primary key always includes the + underscored version of the type before the string `id`: + + ```javascript + App.MySerializer = DS.Serializer.extend({ + // ... + primaryKey: function(type) { + // If the type is `BlogPost`, this will return + // `blog_post_id`. + var typeString = type.toString.split(".")[1].underscore(); + return typeString + "_id"; + } + }); + ``` + + @param {DS.Model subclass} type + @returns {String} the primary key for the type + */ + primaryKey: function(type) { + return "id"; + }, + + /** + A hook you can use in your serializer subclass to customize + how an unmapped `belongsTo` relationship is converted into + a key. + + By default, this method calls `keyForAttributeName`, so if + your naming convention is uniform across attributes and + relationships, you can use the default here and override + just `keyForAttributeName` as needed. + + For example, if the `belongsTo` names in your JSON always + begin with `BT_` (e.g. `BT_posts`), you can strip out the + `BT_` prefix:" + + ```javascript + App.MySerializer = DS.Serializer.extend({ + // ... + keyForBelongsTo: function(type, name) { + return name.match(/^BT_(.*)$/)[1].camelize(); + } + }); + ``` + + @param {DS.Model subclass} type the type of the record with + the `belongsTo` relationship. + @param {String} name the relationship name to convert into a key + + @returns {String} the key + */ + keyForBelongsTo: function(type, name) { + return this.keyForAttributeName(type, name); + }, + + /** + A hook you can use in your serializer subclass to customize + how an unmapped `hasMany` relationship is converted into + a key. + + By default, this method calls `keyForAttributeName`, so if + your naming convention is uniform across attributes and + relationships, you can use the default here and override + just `keyForAttributeName` as needed. + + For example, if the `hasMany` names in your JSON always + begin with the "table name" for the current type (e.g. + `post_comments`), you can strip out the prefix:" + + ```javascript + App.MySerializer = DS.Serializer.extend({ + // ... + keyForHasMany: function(type, name) { + // if your App.BlogPost has many App.BlogComment, the key from + // the server would look like: `blog_post_blog_comments` + // + // 1. Convert the type into a string and underscore the + // second part (App.BlogPost -> blog_post) + // 2. Extract the part after `blog_post_` (`blog_comments`) + // 3. Underscore it, to become `blogComments` + var typeString = type.toString().split(".")[1].underscore(); + return name.match(new RegExp("^" + typeString + "_(.*)$"))[1].camelize(); + } + }); + ``` + + @param {DS.Model subclass} type the type of the record with + the `belongsTo` relationship. + @param {String} name the relationship name to convert into a key + + @returns {String} the key + */ + keyForHasMany: function(type, name) { + return this.keyForAttributeName(type, name); + }, + + //......................... + //. MATERIALIZATION HOOKS + //......................... + + materialize: function(record, serialized, prematerialized) { + var id; + if (Ember.isNone(get(record, 'id'))) { + if (prematerialized && prematerialized.hasOwnProperty('id')) { + id = prematerialized.id; + } else { + id = this.extractId(record.constructor, serialized); + } + record.materializeId(id); + } + + this.materializeAttributes(record, serialized, prematerialized); + this.materializeRelationships(record, serialized, prematerialized); + }, + + deserializeValue: function(value, attributeType) { + var transform = this.transforms ? this.transforms[attributeType] : null; + + Ember.assert("You tried to use a attribute type (" + attributeType + ") that has not been registered", transform); + return transform.deserialize(value); + }, + + materializeAttributes: function(record, serialized, prematerialized) { + record.eachAttribute(function(name, attribute) { + if (prematerialized && prematerialized.hasOwnProperty(name)) { + record.materializeAttribute(name, prematerialized[name]); + } else { + this.materializeAttribute(record, serialized, name, attribute.type); + } + }, this); + }, + + materializeAttribute: function(record, serialized, attributeName, attributeType) { + var value = this.extractAttribute(record.constructor, serialized, attributeName); + value = this.deserializeValue(value, attributeType); + + record.materializeAttribute(attributeName, value); + }, + + materializeRelationships: function(record, hash, prematerialized) { + record.eachRelationship(function(name, relationship) { + if (relationship.kind === 'hasMany') { + if (prematerialized && prematerialized.hasOwnProperty(name)) { + record.materializeHasMany(name, prematerialized[name]); + } else { + this.materializeHasMany(name, record, hash, relationship, prematerialized); + } + } else if (relationship.kind === 'belongsTo') { + if (prematerialized && prematerialized.hasOwnProperty(name)) { + record.materializeBelongsTo(name, prematerialized[name]); + } else { + this.materializeBelongsTo(name, record, hash, relationship, prematerialized); + } + } + }, this); + }, + + materializeHasMany: function(name, record, hash, relationship) { + var key = this._keyForHasMany(record.constructor, relationship.key); + record.materializeHasMany(name, this.extractHasMany(record.constructor, hash, key)); + }, + + materializeBelongsTo: function(name, record, hash, relationship) { + var key = this._keyForBelongsTo(record.constructor, relationship.key); + record.materializeBelongsTo(name, this.extractBelongsTo(record.constructor, hash, key)); + }, + + _extractEmbeddedRelationship: function(type, hash, name, relationshipType) { + var key = this['_keyFor' + relationshipType](type, name); + + if (this.embeddedType(type, name)) { + return this['extractEmbedded' + relationshipType](type, hash, key); + } + }, + + _extractEmbeddedBelongsTo: function(type, hash, name) { + return this._extractEmbeddedRelationship(type, hash, name, 'BelongsTo'); + }, + + _extractEmbeddedHasMany: function(type, hash, name) { + return this._extractEmbeddedRelationship(type, hash, name, 'HasMany'); + }, + + /** + @private + + This method is called to get the primary key for a given + type. + + If a primary key configuration exists for this type, this + method will return the configured value. Otherwise, it will + call the public `primaryKey` hook. + + @param {DS.Model subclass} type + @returns {String} the primary key for the type + */ + _primaryKey: function(type) { + var config = this.configurationForType(type), + primaryKey = config && config.primaryKey; + + if (primaryKey) { + return primaryKey; + } else { + return this.primaryKey(type); + } + }, + + /** + @private + + This method looks up the key for the attribute name and transforms the + attribute's value using registered transforms. + + Specifically: + + 1. Look up the key for the attribute name. If available, this will use + any registered mappings. Otherwise, it will invoke the public + `keyForAttributeName` hook. + 2. Get the value from the record using the `attributeName`. + 3. Transform the value using registered transforms for the `attributeType`. + 4. Invoke the public `addAttribute` hook with the hash, key, and + transformed value. + + @param {any} data the serialized representation being built + @param {DS.Model} record the record to serialize + @param {String} attributeName the name of the attribute on the record + @param {String} attributeType the type of the attribute (e.g. `string` + or `boolean`) + */ + _addAttribute: function(data, record, attributeName, attributeType) { + var key = this._keyForAttributeName(record.constructor, attributeName); + var value = get(record, attributeName); + + this.addAttribute(data, key, this.serializeValue(value, attributeType)); + }, + + /** + @private + + This method looks up the primary key for the `type` and invokes + `serializeId` on the `id`. + + It then invokes the public `addId` hook with the primary key and + the serialized id. + + @param {any} data the serialized representation that is being built + @param {Ember.Model subclass} type + @param {any} id the materialized id from the record + */ + _addId: function(hash, type, id) { + var primaryKey = this._primaryKey(type); + + this.addId(hash, primaryKey, this.serializeId(id)); + }, + + /** + @private + + This method is called to get a key used in the data from + an attribute name. It first checks for any mappings before + calling the public hook `keyForAttributeName`. + + @param {DS.Model subclass} type the type of the record with + the attribute name `name` + @param {String} name the attribute name to convert into a key + + @returns {String} the key + */ + _keyForAttributeName: function(type, name) { + return this._keyFromMappingOrHook('keyForAttributeName', type, name); + }, + + /** + @private + + This method is called to get a key used in the data from + a belongsTo relationship. It first checks for any mappings before + calling the public hook `keyForBelongsTo`. + + @param {DS.Model subclass} type the type of the record with + the `belongsTo` relationship. + @param {String} name the relationship name to convert into a key + + @returns {String} the key + */ + _keyForBelongsTo: function(type, name) { + return this._keyFromMappingOrHook('keyForBelongsTo', type, name); + }, + + keyFor: function(description) { + var type = description.parentType, + name = description.key; + + switch (description.kind) { + case 'belongsTo': + return this._keyForBelongsTo(type, name); + case 'hasMany': + return this._keyForHasMany(type, name); + } + }, + + /** + @private + + This method is called to get a key used in the data from + a hasMany relationship. It first checks for any mappings before + calling the public hook `keyForHasMany`. + + @param {DS.Model subclass} type the type of the record with + the `hasMany` relationship. + @param {String} name the relationship name to convert into a key + + @returns {String} the key + */ + _keyForHasMany: function(type, name) { + return this._keyFromMappingOrHook('keyForHasMany', type, name); + }, + /** + @private + + This method converts the relationship name to a key for serialization, + and then invokes the public `addBelongsTo` hook. + + @param {any} data the serialized representation that is being built + @param {DS.Model} record the record to serialize + @param {String} name the relationship name + @param {Object} relationship an object representing the relationship + */ + _addBelongsTo: function(data, record, name, relationship) { + var key = this._keyForBelongsTo(record.constructor, name); + this.addBelongsTo(data, record, key, relationship); + }, + + /** + @private + + This method converts the relationship name to a key for serialization, + and then invokes the public `addHasMany` hook. + + @param {any} data the serialized representation that is being built + @param {DS.Model} record the record to serialize + @param {String} name the relationship name + @param {Object} relationship an object representing the relationship + */ + _addHasMany: function(data, record, name, relationship) { + var key = this._keyForHasMany(record.constructor, name); + this.addHasMany(data, record, key, relationship); + }, + + /** + @private + + An internal method that handles checking whether a mapping + exists for a particular attribute or relationship name before + calling the public hooks. + + If a mapping is found, and the mapping has a key defined, + use that instead of invoking the hook. + + @param {String} publicMethod the public hook to invoke if + a mapping is not found (e.g. `keyForAttributeName`) + @param {DS.Model subclass} type the type of the record with + the attribute or relationship name. + @param {String} name the attribute or relationship name to + convert into a key + */ + _keyFromMappingOrHook: function(publicMethod, type, name) { + var key = this.mappingOption(type, name, 'key'); + + if (key) { + return key; + } else { + return this[publicMethod](type, name); + } + }, + + /** + TRANSFORMS + */ + + registerTransform: function(type, transform) { + this.transforms[type] = transform; + }, + + registerEnumTransform: function(type, objects) { + var transform = { + deserialize: function(deserialized) { + return objects.objectAt(deserialized); + }, + serialize: function(serialized) { + return objects.indexOf(serialized); + }, + values: objects + }; + this.registerTransform(type, transform); + }, + + /** + MAPPING CONVENIENCE + */ + + map: function(type, mappings) { + this.mappings.set(type, mappings); + }, + + configure: function(type, configuration) { + if (type && !configuration) { + Ember.merge(this.globalConfigurations, type); + return; + } + + var config = Ember.create(this.globalConfigurations); + Ember.merge(config, configuration); + + this.configurations.set(type, config); + }, + + mappingForType: function(type) { + this._reifyMappings(); + return this.mappings.get(type) || {}; + }, + + configurationForType: function(type) { + this._reifyConfigurations(); + return this.configurations.get(type) || this.globalConfigurations; + }, + + _reifyMappings: function() { + if (this._didReifyMappings) { return; } + + var mappings = this.mappings, + reifiedMappings = Ember.Map.create(); + + mappings.forEach(function(key, mapping) { + if (typeof key === 'string') { + var type = Ember.get(Ember.lookup, key); + Ember.assert("Could not find model at path " + key, type); + + reifiedMappings.set(type, mapping); + } else { + reifiedMappings.set(key, mapping); + } + }); + + this.mappings = reifiedMappings; + + this._didReifyMappings = true; + }, + + _reifyConfigurations: function() { + if (this._didReifyConfigurations) { return; } + + var configurations = this.configurations, + reifiedConfigurations = Ember.Map.create(); + + configurations.forEach(function(key, mapping) { + if (typeof key === 'string' && key !== 'plurals') { + var type = Ember.get(Ember.lookup, key); + Ember.assert("Could not find model at path " + key, type); + + reifiedConfigurations.set(type, mapping); + } else { + reifiedConfigurations.set(key, mapping); + } + }); + + this.configurations = reifiedConfigurations; + + this._didReifyConfigurations = true; + }, + + mappingOption: function(type, name, option) { + var mapping = this.mappingForType(type)[name]; + + return mapping && mapping[option]; + }, + + configOption: function(type, option) { + var config = this.configurationForType(type); + + return config[option]; + }, + + // EMBEDDED HELPERS + + embeddedType: function(type, name) { + return this.mappingOption(type, name, 'embedded'); + }, + + eachEmbeddedRecord: function(record, callback, binding) { + this.eachEmbeddedBelongsToRecord(record, callback, binding); + this.eachEmbeddedHasManyRecord(record, callback, binding); + }, + + eachEmbeddedBelongsToRecord: function(record, callback, binding) { + var type = record.constructor; + + this.eachEmbeddedBelongsTo(record.constructor, function(name, relationship, embeddedType) { + var embeddedRecord = get(record, name); + if (embeddedRecord) { callback.call(binding, embeddedRecord, embeddedType); } + }); + }, + + eachEmbeddedHasManyRecord: function(record, callback, binding) { + var type = record.constructor; + + this.eachEmbeddedHasMany(record.constructor, function(name, relationship, embeddedType) { + var array = get(record, name); + for (var i=0, l=get(array, 'length'); i 'low' + Server Response / Load: { myTask: {priority: 0} } + + @param {String} type of the transform + @param {Array} array of String objects to use for the enumerated values. + This is an ordered list and the index values will be used for the transform. + */ + registerEnumTransform: function(attributeType, objects) { + get(this, 'serializer').registerEnumTransform(attributeType, objects); + }, + + /** + If the globally unique IDs for your records should be generated on the client, + implement the `generateIdForRecord()` method. This method will be invoked + each time you create a new record, and the value returned from it will be + assigned to the record's `primaryKey`. + + Most traditional REST-like HTTP APIs will not use this method. Instead, the ID + of the record will be set by the server, and your adapter will update the store + with the new ID when it calls `didCreateRecord()`. Only implement this method if + you intend to generate record IDs on the client-side. + + The `generateIdForRecord()` method will be invoked with the requesting store as + the first parameter and the newly created record as the second parameter: + + generateIdForRecord: function(store, record) { + var uuid = App.generateUUIDWithStatisticallyLowOddsOfCollision(); + return uuid; + } + */ + generateIdForRecord: null, + + materialize: function(record, data, prematerialized) { + get(this, 'serializer').materialize(record, data, prematerialized); + }, + + serialize: function(record, options) { + return get(this, 'serializer').serialize(record, options); + }, + + extractId: function(type, data) { + return get(this, 'serializer').extractId(type, data); + }, + + groupByType: function(enumerable) { + var map = Ember.MapWithDefault.create({ + defaultValue: function() { return Ember.OrderedSet.create(); } + }); + + enumerable.forEach(function(item) { + map.get(item.constructor).add(item); + }); + + return map; + }, + + commit: function(store, commitDetails) { + this.save(store, commitDetails); + }, + + save: function(store, commitDetails) { + var adapter = this; + + function filter(records) { + var filteredSet = Ember.OrderedSet.create(); + + records.forEach(function(record) { + if (adapter.shouldSave(record)) { + filteredSet.add(record); + } + }); + + return filteredSet; + } + + this.groupByType(commitDetails.created).forEach(function(type, set) { + this.createRecords(store, type, filter(set)); + }, this); + + this.groupByType(commitDetails.updated).forEach(function(type, set) { + this.updateRecords(store, type, filter(set)); + }, this); + + this.groupByType(commitDetails.deleted).forEach(function(type, set) { + this.deleteRecords(store, type, filter(set)); + }, this); + }, + + shouldSave: Ember.K, + + createRecords: function(store, type, records) { + records.forEach(function(record) { + this.createRecord(store, type, record); + }, this); + }, + + updateRecords: function(store, type, records) { + records.forEach(function(record) { + this.updateRecord(store, type, record); + }, this); + }, + + deleteRecords: function(store, type, records) { + records.forEach(function(record) { + this.deleteRecord(store, type, record); + }, this); + }, + + findMany: function(store, type, ids) { + ids.forEach(function(id) { + this.find(store, type, id); + }, this); + } +}); + +DS.Adapter.reopenClass({ + registerTransform: function(attributeType, transform) { + var registeredTransforms = this._registeredTransforms || {}; + + registeredTransforms[attributeType] = transform; + + this._registeredTransforms = registeredTransforms; + }, + + map: DS._Mappable.generateMapFunctionFor('attributes', function(key, newValue, map) { + var existingValue = map.get(key); + + merge(existingValue, newValue); + }), + + configure: DS._Mappable.generateMapFunctionFor('configurations', function(key, newValue, map) { + var existingValue = map.get(key); + + // If a mapping configuration is provided, peel it off and apply it + // using the DS.Adapter.map API. + var mappings = newValue && newValue.mappings; + if (mappings) { + this.map(key, mappings); + delete newValue.mappings; + } + + merge(existingValue, newValue); + }), + + resolveMapConflict: function(oldValue, newValue, mappingsKey) { + merge(newValue, oldValue); + + return newValue; + } +}); + +})(); + + + +(function() { +var get = Ember.get; + +DS.FixtureAdapter = DS.Adapter.extend({ + + simulateRemoteResponse: true, + + latency: 50, + + /* + Implement this method in order to provide data associated with a type + */ + fixturesForType: function(type) { + if (type.FIXTURES) { + var fixtures = Ember.A(type.FIXTURES); + return fixtures.map(function(fixture){ + if(!fixture.id){ + throw new Error('the id property must be defined for fixture %@'.fmt(fixture)); + } + fixture.id = fixture.id + ''; + return fixture; + }); + } + return null; + }, + + /* + Implement this method in order to query fixtures data + */ + queryFixtures: function(fixtures, query, type) { + return fixtures; + }, + + /* + Implement this method in order to provide provide json for CRUD methods + */ + mockJSON: function(type, record) { + return this.serialize(record, { includeId: true }); + }, + + /* + Adapter methods + */ + generateIdForRecord: function(store, record) { + return Ember.guidFor(record); + }, + + find: function(store, type, id) { + var fixtures = this.fixturesForType(type); + + Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); + + if (fixtures) { + fixtures = fixtures.findProperty('id', id); + } + + if (fixtures) { + this.simulateRemoteCall(function() { + store.load(type, fixtures); + }, store, type); + } + }, + + findMany: function(store, type, ids) { + var fixtures = this.fixturesForType(type); + + Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); + + if (fixtures) { + fixtures = fixtures.filter(function(item) { + return ids.indexOf(item.id) !== -1; + }); + } + + if (fixtures) { + this.simulateRemoteCall(function() { + store.loadMany(type, fixtures); + }, store, type); + } + }, + + findAll: function(store, type) { + var fixtures = this.fixturesForType(type); + + Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); + + this.simulateRemoteCall(function() { + store.loadMany(type, fixtures); + store.didUpdateAll(type); + }, store, type); + }, + + findQuery: function(store, type, query, array) { + var fixtures = this.fixturesForType(type); + + Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); + + fixtures = this.queryFixtures(fixtures, query, type); + + if (fixtures) { + this.simulateRemoteCall(function() { + array.load(fixtures); + }, store, type); + } + }, + + createRecord: function(store, type, record) { + var fixture = this.mockJSON(type, record); + + fixture.id = this.generateIdForRecord(store, record); + + this.simulateRemoteCall(function() { + store.didSaveRecord(record, fixture); + }, store, type, record); + }, + + updateRecord: function(store, type, record) { + var fixture = this.mockJSON(type, record); + + this.simulateRemoteCall(function() { + store.didSaveRecord(record, fixture); + }, store, type, record); + }, + + deleteRecord: function(store, type, record) { + this.simulateRemoteCall(function() { + store.didSaveRecord(record); + }, store, type, record); + }, + + /* + @private + */ + simulateRemoteCall: function(callback, store, type, record) { + if (get(this, 'simulateRemoteResponse')) { + setTimeout(callback, get(this, 'latency')); + } else { + callback(); + } + } +}); + +})(); + + + +(function() { +DS.RESTSerializer = DS.JSONSerializer.extend({ + keyForAttributeName: function(type, name) { + return Ember.String.decamelize(name); + }, + + keyForBelongsTo: function(type, name) { + var key = this.keyForAttributeName(type, name); + + if (this.embeddedType(type, name)) { + return key; + } + + return key + "_id"; + } +}); + +})(); + + + +(function() { +/*global jQuery*/ + +var get = Ember.get, set = Ember.set, merge = Ember.merge; + +/** + The REST adapter allows your store to communicate with an HTTP server by + transmitting JSON via XHR. Most Ember.js apps that consume a JSON API + should use the REST adapter. + + This adapter is designed around the idea that the JSON exchanged with + the server should be conventional. + + ## JSON Structure + + The REST adapter expects the JSON returned from your server to follow + these conventions. + + ### Object Root + + The JSON payload should be an object that contains the record inside a + root property. For example, in response to a `GET` request for + `/posts/1`, the JSON should look like this: + + ```js + { + "post": { + title: "I'm Running to Reform the W3C's Tag", + author: "Yehuda Katz" + } + } + ``` + + ### Conventional Names + + Attribute names in your JSON payload should be the underscored versions of + the attributes in your Ember.js models. + + For example, if you have a `Person` model: + + ```js + App.Person = DS.Model.extend({ + firstName: DS.attr('string'), + lastName: DS.attr('string'), + occupation: DS.attr('string') + }); + ``` + + The JSON returned should look like this: + + ```js + { + "person": { + "first_name": "Barack", + "last_name": "Obama", + "occupation": "President" + } + } + ``` +*/ +DS.RESTAdapter = DS.Adapter.extend({ + bulkCommit: false, + since: 'since', + + serializer: DS.RESTSerializer, + + init: function() { + this._super.apply(this, arguments); + }, + + shouldSave: function(record) { + var reference = get(record, '_reference'); + + return !reference.parent; + }, + + createRecord: function(store, type, record) { + var root = this.rootForType(type); + + var data = {}; + data[root] = this.serialize(record, { includeId: true }); + + this.ajax(this.buildURL(root), "POST", { + data: data, + context: this, + success: function(json) { + Ember.run(this, function(){ + this.didCreateRecord(store, type, record, json); + }); + }, + error: function(xhr) { + this.didError(store, type, record, xhr); + } + }); + }, + + dirtyRecordsForRecordChange: function(dirtySet, record) { + dirtySet.add(record); + + get(this, 'serializer').eachEmbeddedRecord(record, function(embeddedRecord, embeddedType) { + if (embeddedType !== 'always') { return; } + if (dirtySet.has(embeddedRecord)) { return; } + this.dirtyRecordsForRecordChange(dirtySet, embeddedRecord); + }, this); + + var reference = record.get('_reference'); + + if (reference.parent) { + var store = get(record, 'store'); + var parent = store.recordForReference(reference.parent); + this.dirtyRecordsForRecordChange(dirtySet, parent); + } + }, + + dirtyRecordsForHasManyChange: Ember.K, + + createRecords: function(store, type, records) { + if (get(this, 'bulkCommit') === false) { + return this._super(store, type, records); + } + + var root = this.rootForType(type), + plural = this.pluralize(root); + + var data = {}; + data[plural] = []; + records.forEach(function(record) { + data[plural].push(this.serialize(record, { includeId: true })); + }, this); + + this.ajax(this.buildURL(root), "POST", { + data: data, + context: this, + success: function(json) { + Ember.run(this, function(){ + this.didCreateRecords(store, type, records, json); + }); + } + }); + }, + + updateRecord: function(store, type, record) { + var id = get(record, 'id'); + var root = this.rootForType(type); + + var data = {}; + data[root] = this.serialize(record); + + this.ajax(this.buildURL(root, id), "PUT", { + data: data, + context: this, + success: function(json) { + Ember.run(this, function(){ + this.didSaveRecord(store, type, record, json); + }); + }, + error: function(xhr) { + this.didError(store, type, record, xhr); + } + }); + }, + + updateRecords: function(store, type, records) { + if (get(this, 'bulkCommit') === false) { + return this._super(store, type, records); + } + + var root = this.rootForType(type), + plural = this.pluralize(root); + + var data = {}; + data[plural] = []; + records.forEach(function(record) { + data[plural].push(this.serialize(record, { includeId: true })); + }, this); + + this.ajax(this.buildURL(root, "bulk"), "PUT", { + data: data, + context: this, + success: function(json) { + Ember.run(this, function(){ + this.didSaveRecords(store, type, records, json); + }); + } + }); + }, + + deleteRecord: function(store, type, record) { + var id = get(record, 'id'); + var root = this.rootForType(type); + + this.ajax(this.buildURL(root, id), "DELETE", { + context: this, + success: function(json) { + Ember.run(this, function(){ + this.didSaveRecord(store, type, record, json); + }); + } + }); + }, + + deleteRecords: function(store, type, records) { + if (get(this, 'bulkCommit') === false) { + return this._super(store, type, records); + } + + var root = this.rootForType(type), + plural = this.pluralize(root), + serializer = get(this, 'serializer'); + + var data = {}; + data[plural] = []; + records.forEach(function(record) { + data[plural].push(serializer.serializeId( get(record, 'id') )); + }); + + this.ajax(this.buildURL(root, 'bulk'), "DELETE", { + data: data, + context: this, + success: function(json) { + Ember.run(this, function(){ + this.didSaveRecords(store, type, records, json); + }); + } + }); + }, + + find: function(store, type, id) { + var root = this.rootForType(type); + + this.ajax(this.buildURL(root, id), "GET", { + success: function(json) { + Ember.run(this, function(){ + this.didFindRecord(store, type, json, id); + }); + } + }); + }, + + findAll: function(store, type, since) { + var root = this.rootForType(type); + + this.ajax(this.buildURL(root), "GET", { + data: this.sinceQuery(since), + success: function(json) { + Ember.run(this, function(){ + this.didFindAll(store, type, json); + }); + } + }); + }, + + findQuery: function(store, type, query, recordArray) { + var root = this.rootForType(type); + + this.ajax(this.buildURL(root), "GET", { + data: query, + success: function(json) { + Ember.run(this, function(){ + this.didFindQuery(store, type, json, recordArray); + }); + } + }); + }, + + findMany: function(store, type, ids, owner) { + var root = this.rootForType(type); + ids = this.serializeIds(ids); + + this.ajax(this.buildURL(root), "GET", { + data: {ids: ids}, + success: function(json) { + Ember.run(this, function(){ + this.didFindMany(store, type, json); + }); + } + }); + }, + + /** + @private + + This method serializes a list of IDs using `serializeId` + + @returns {Array} an array of serialized IDs + */ + serializeIds: function(ids) { + var serializer = get(this, 'serializer'); + + return Ember.EnumerableUtils.map(ids, function(id) { + return serializer.serializeId(id); + }); + }, + + didError: function(store, type, record, xhr) { + if (xhr.status === 422) { + var data = JSON.parse(xhr.responseText); + store.recordWasInvalid(record, data['errors']); + } else { + this._super.apply(this, arguments); + } + }, + + ajax: function(url, type, hash) { + hash.url = url; + hash.type = type; + hash.dataType = 'json'; + hash.contentType = 'application/json; charset=utf-8'; + hash.context = this; + + if (hash.data && type !== 'GET') { + hash.data = JSON.stringify(hash.data); + } + + jQuery.ajax(hash); + }, + + url: "", + + rootForType: function(type) { + var serializer = get(this, 'serializer'); + return serializer.rootForType(type); + }, + + pluralize: function(string) { + var serializer = get(this, 'serializer'); + return serializer.pluralize(string); + }, + + buildURL: function(record, suffix) { + var url = [this.url]; + + Ember.assert("Namespace URL (" + this.namespace + ") must not start with slash", !this.namespace || this.namespace.toString().charAt(0) !== "/"); + Ember.assert("Record URL (" + record + ") must not start with slash", !record || record.toString().charAt(0) !== "/"); + Ember.assert("URL suffix (" + suffix + ") must not start with slash", !suffix || suffix.toString().charAt(0) !== "/"); + + if (this.namespace !== undefined) { + url.push(this.namespace); + } + + url.push(this.pluralize(record)); + if (suffix !== undefined) { + url.push(suffix); + } + + return url.join("/"); + }, + + sinceQuery: function(since) { + var query = {}; + query[get(this, 'since')] = since; + return since ? query : null; + } +}); + + +})(); + + + +(function() { + +})(); + + + +(function() { +//Copyright (C) 2011 by Living Social, Inc. + +//Permission is hereby granted, free of charge, to any person obtaining a copy of +//this software and associated documentation files (the "Software"), to deal in +//the Software without restriction, including without limitation the rights to +//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +//of the Software, and to permit persons to whom the Software is furnished to do +//so, subject to the following conditions: + +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. + +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + +})(); diff --git a/htdocs/portal/assets/js/fsportal.js b/htdocs/portal/assets/js/fsportal.js new file mode 100644 index 0000000000..4689474414 --- /dev/null +++ b/htdocs/portal/assets/js/fsportal.js @@ -0,0 +1,373 @@ +/* + * The FreeSWITCH Portal Project + * Copyright (C) 2013-2013, Seven Du + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is The FreeSWITCH Portal Project Software/Application + * + * The Initial Developer of the Original Code is + * Seven Du + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Seven Du + * + * + * fsportal.js -- The FreeSWITCH Portal Project + * + */ + +var App = Ember.Application.create({ + LOG_TRANSITIONS: true, + rootElement: $('#container'), + total: 0, + ready: function(){ + } +}); + +App.CallsRoute = Ember.Route.extend({ + setupController: function(controller) { + // Set the IndexController's `title` + // controller.set('title', "My App"); + // alert("a") + console.log("callsRoute"); + App.callsController.load(); + }//, + // renderTemplate: function() { + // this.render('calls'); + // } +}); + +App.ChannelsRoute = Ember.Route.extend({ + setupController: function(controller) { + // Set the IndexController's `title` + // controller.set('title', "My App"); + // alert("a") + console.log("callsRoute"); + App.channelsController.load(); + }//, + // renderTemplate: function() { + // this.render('calls'); + // } +}); + + +App.ShowApplicationsRoute = Ember.Route.extend({ + setupController: function(controller) { + // Set the Controller's `title` + controller.set('title', "ShowApplications"); + console.log("showApplications"); + App.applicationsController.load(); + }//, + // renderTemplate: function() { + // this.render('calls'); + // } +}); + +App.ShowEndpointsRoute = Ember.Route.extend({ + setupController: function(controller) { + // Set the Controller's `title` + controller.set('title', "ShowEndpoints"); + console.log(controller); + App.showEndpointsController.load(); + }//, + // renderTemplate: function() { + // this.render('calls'); + // } +}); + +App.ShowCodecsRoute = Ember.Route.extend({ + setupController: function(controller) { + App.showCodecsController.load(); + } +}); + +App.UsersRoute = Ember.Route.extend({ + setupController: function(controller) { + App.usersController.load(); + } +}); + +App.Router.map(function(){ + this.route("calls"); + this.route("channels"); + this.route("showApplications"); + this.route("showEndpoints"); + this.route("showCodecs"); + this.route("showFiles"); + this.route("showAPIs"); + this.route("show"); + this.route("users"); + this.route("about", { path: "/about" }); +}); + +App.User = Em.Object.extend({ + id: null, + context: null, + domain: null, + group: null, + contact: null +}); + +App.Call = Em.Object.extend({ + uuid: null, + cidName: null, + cidNumber: null + +}); + +App.Channel = Em.Object.extend({ + uuid: null, + cidName: null, + cidNumber: null + +}); + +App.callsController = Ember.ArrayController.create({ + content: [], + init: function(){ + }, + load: function() { + var me = this; + $.getJSON("/txtapi/show?calls%20as%20json", function(data){ + // var channels = JSON.parse(data); + console.log(data.row_count); + me.set('total', data.row_count); + me.content.clear(); + if (data.row_count == 0) return; + + // me.pushObjects(data.rows); + data.rows.forEach(function(r) { + me.pushObject(App.Call.create(r)); + }); + + }); + }, + dump: function(uuid) { + var obj = this.content.findProperty("uuid", uuid); + console.log(obj.getProperties(["uuid", "cid_num"])); + }, + raw: function() { + $.get("/api/show?calls", function(data){ + $('#aa').html(data); + }); + } +}); + +App.channelsController = Ember.ArrayController.create({ + content: [], + listener: undefined, + init: function(){ + }, + load: function() { + var me = this; + $.getJSON("/txtapi/show?channels%20as%20json", function(data){ + // var channels = JSON.parse(data); + console.log(data.row_count); + me.set('total', data.row_count); + me.content.clear(); + if (data.row_count == 0) return; + data.rows.forEach(function(row) { + me.pushObject(App.Channel.create(row)); + }); + + }); + }, + delete: function(uuid) { + var obj = this.content.findProperty("uuid", uuid); + if (obj) this.content.removeObject(obj);// else alert(uuid); + }, + dump: function(uuid) { + var obj = this.content.findProperty("uuid", uuid); + console.log(obj.getProperties(["uuid", "cid_num"])); + }, + checkEvent: function () { // event_sink with json is not yet support in FS + console.log("check"); + var me = this; + if (!this.get("listener")) { + $.getJSON("/api/event_sink?command=create-listener&events=ALL&format=json", function(data){ + console.log(data); + if (data.listener) { + me.set("listener", data.listener["listen-id"]); + } + }); + } + if (!me.get("listener")) return; + + $.getJSON("/api/event_sink?command=check-listener&listen-id=" + + me.get("listener") + "&format=json", function(data){ + console.log(data); + if (!data.listener) { + me.set("listener", undefined); + } else { + data.events.forEach(function(e) { + eventCallback(e); + }); + } + }); + }, + checkXMLEvent: function() { + console.log("check XML Event"); + var me = this; + if (!this.get("listener")) { + $.get("/api/event_sink?command=create-listener&events=ALL", function(data){ + // console.log(data); + var listen_id = data.getElementsByTagName("listen-id")[0]; + if (listen_id) { + me.set("listener", listen_id.textContent); + } + }); + } + + if (!me.get("listener")) return; + + $.get("/api/event_sink?command=check-listener&listen-id=" + me.get("listener"), function(data){ + // console.log(data); + var listener = data.getElementsByTagName("listener")[0]; + if (!listener) { + me.set("listener", undefined); + } else { + var events = data.getElementsByTagName("event"); + for (var i=0; i= 1.0.0-rc.3' +}; + +Handlebars.helpers = {}; +Handlebars.partials = {}; + +Handlebars.registerHelper = function(name, fn, inverse) { + if(inverse) { fn.not = inverse; } + this.helpers[name] = fn; +}; + +Handlebars.registerPartial = function(name, str) { + this.partials[name] = str; +}; + +Handlebars.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; + } else { + throw new Error("Could not find property '" + arg + "'"); + } +}); + +var toString = Object.prototype.toString, functionType = "[object Function]"; + +Handlebars.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; + + + var ret = ""; + var type = toString.call(context); + + if(type === functionType) { context = context.call(this); } + + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if(type === "[object Array]") { + if(context.length > 0) { + return Handlebars.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + return fn(context); + } +}); + +Handlebars.K = function() {}; + +Handlebars.createFrame = Object.create || function(object) { + Handlebars.K.prototype = object; + var obj = new Handlebars.K(); + Handlebars.K.prototype = null; + return obj; +}; + +Handlebars.logger = { + DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3, + + methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'}, + + // can be overridden in the host environment + log: function(level, obj) { + if (Handlebars.logger.level <= level) { + var method = Handlebars.logger.methodMap[level]; + if (typeof console !== 'undefined' && console[method]) { + console[method].call(console, obj); + } + } + } +}; + +Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); }; + +Handlebars.registerHelper('each', function(context, options) { + var fn = options.fn, inverse = options.inverse; + var i = 0, ret = "", data; + + if (options.data) { + data = Handlebars.createFrame(options.data); + } + + if(context && typeof context === 'object') { + if(context instanceof Array){ + for(var j = context.length; i 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; +} +}; +/* Jison generated lexer */ +var lexer = (function(){ +var lexer = ({EOF:1, +parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, +setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + if (this.options.ranges) this.yylloc.range = [0,0]; + this.offset = 0; + return this; + }, +input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, +unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length-len-1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length-1); + this.matched = this.matched.substr(0, this.matched.length-1); + + if (lines.length-1) this.yylineno -= lines.length-1; + var r = this.yylloc.range; + + this.yylloc = {first_line: this.yylloc.first_line, + last_line: this.yylineno+1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length: + this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, +more:function () { + this._more = true; + return this; + }, +less:function (n) { + this.unput(this.match.slice(n)); + }, +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length}; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, +lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +popState:function popState() { + return this.conditionStack.pop(); + }, +_currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, +topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, +pushState:function begin(condition) { + this.begin(condition); + }}); +lexer.options = {}; +lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + +var YYSTATE=YY_START +switch($avoiding_name_collisions) { +case 0: + if(yy_.yytext.slice(-1) !== "\\") this.begin("mu"); + if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu"); + if(yy_.yytext) return 14; + +break; +case 1: return 14; +break; +case 2: + if(yy_.yytext.slice(-1) !== "\\") this.popState(); + if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1); + return 14; + +break; +case 3: yy_.yytext = yy_.yytext.substr(0, yy_.yyleng-4); this.popState(); return 15; +break; +case 4: this.begin("par"); return 24; +break; +case 5: return 16; +break; +case 6: return 20; +break; +case 7: return 19; +break; +case 8: return 19; +break; +case 9: return 23; +break; +case 10: return 23; +break; +case 11: this.popState(); this.begin('com'); +break; +case 12: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; +break; +case 13: return 22; +break; +case 14: return 36; +break; +case 15: return 35; +break; +case 16: return 35; +break; +case 17: return 39; +break; +case 18: /*ignore whitespace*/ +break; +case 19: this.popState(); return 18; +break; +case 20: this.popState(); return 18; +break; +case 21: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 30; +break; +case 22: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\'/g,"'"); return 30; +break; +case 23: yy_.yytext = yy_.yytext.substr(1); return 28; +break; +case 24: return 32; +break; +case 25: return 32; +break; +case 26: return 31; +break; +case 27: return 35; +break; +case 28: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 35; +break; +case 29: return 'INVALID'; +break; +case 30: /*ignore whitespace*/ +break; +case 31: this.popState(); return 37; +break; +case 32: return 5; +break; +} +}; +lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:\s+)/,/^(?:[a-zA-Z0-9_$-/]+)/,/^(?:$)/]; +lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"par":{"rules":[30,31],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}}; +return lexer;})() +parser.lexer = lexer; +function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; +return new Parser; +})();; +// lib/handlebars/compiler/base.js +Handlebars.Parser = handlebars; + +Handlebars.parse = function(input) { + + // Just return if an already-compile AST was passed in. + if(input.constructor === Handlebars.AST.ProgramNode) { return input; } + + Handlebars.Parser.yy = Handlebars.AST; + return Handlebars.Parser.parse(input); +}; + +Handlebars.print = function(ast) { + return new Handlebars.PrintVisitor().accept(ast); +};; +// lib/handlebars/compiler/ast.js +(function() { + + Handlebars.AST = {}; + + Handlebars.AST.ProgramNode = function(statements, inverse) { + this.type = "program"; + this.statements = statements; + if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); } + }; + + Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) { + this.type = "mustache"; + this.escaped = !unescaped; + this.hash = hash; + + var id = this.id = rawParams[0]; + var params = this.params = rawParams.slice(1); + + // a mustache is an eligible helper if: + // * its id is simple (a single part, not `this` or `..`) + var eligibleHelper = this.eligibleHelper = id.isSimple; + + // a mustache is definitely a helper if: + // * it is an eligible helper, and + // * it has at least one parameter or hash segment + this.isHelper = eligibleHelper && (params.length || hash); + + // if a mustache is an eligible helper but not a definite + // helper, it is ambiguous, and will be resolved in a later + // pass or at runtime. + }; + + Handlebars.AST.PartialNode = function(partialName, context) { + this.type = "partial"; + this.partialName = partialName; + this.context = context; + }; + + var verifyMatch = function(open, close) { + if(open.original !== close.original) { + throw new Handlebars.Exception(open.original + " doesn't match " + close.original); + } + }; + + Handlebars.AST.BlockNode = function(mustache, program, inverse, close) { + verifyMatch(mustache.id, close); + this.type = "block"; + this.mustache = mustache; + this.program = program; + this.inverse = inverse; + + if (this.inverse && !this.program) { + this.isInverse = true; + } + }; + + Handlebars.AST.ContentNode = function(string) { + this.type = "content"; + this.string = string; + }; + + Handlebars.AST.HashNode = function(pairs) { + this.type = "hash"; + this.pairs = pairs; + }; + + Handlebars.AST.IdNode = function(parts) { + this.type = "ID"; + this.original = parts.join("."); + + var dig = [], depth = 0; + + for(var i=0,l=parts.length; i 0) { throw new Handlebars.Exception("Invalid path: " + this.original); } + else if (part === "..") { depth++; } + else { this.isScoped = true; } + } + else { dig.push(part); } + } + + this.parts = dig; + this.string = dig.join('.'); + this.depth = depth; + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + this.isSimple = parts.length === 1 && !this.isScoped && depth === 0; + + this.stringModeValue = this.string; + }; + + Handlebars.AST.PartialNameNode = function(name) { + this.type = "PARTIAL_NAME"; + this.name = name; + }; + + Handlebars.AST.DataNode = function(id) { + this.type = "DATA"; + this.id = id; + }; + + Handlebars.AST.StringNode = function(string) { + this.type = "STRING"; + this.string = string; + this.stringModeValue = string; + }; + + Handlebars.AST.IntegerNode = function(integer) { + this.type = "INTEGER"; + this.integer = integer; + this.stringModeValue = Number(integer); + }; + + Handlebars.AST.BooleanNode = function(bool) { + this.type = "BOOLEAN"; + this.bool = bool; + this.stringModeValue = bool === "true"; + }; + + Handlebars.AST.CommentNode = function(comment) { + this.type = "comment"; + this.comment = comment; + }; + +})();; +// lib/handlebars/utils.js + +var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + +Handlebars.Exception = function(message) { + var tmp = Error.prototype.constructor.apply(this, arguments); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } +}; +Handlebars.Exception.prototype = new Error(); + +// Build out our basic SafeString type +Handlebars.SafeString = function(string) { + this.string = string; +}; +Handlebars.SafeString.prototype.toString = function() { + return this.string.toString(); +}; + +(function() { + var escape = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; + + var escapeChar = function(chr) { + return escape[chr] || "&"; + }; + + Handlebars.Utils = { + escapeExpression: function(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof Handlebars.SafeString) { + return string.toString(); + } else if (string == null || string === false) { + return ""; + } + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + }, + + isEmpty: function(value) { + if (!value && value !== 0) { + return true; + } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { + return true; + } else { + return false; + } + } + }; +})();; +// lib/handlebars/compiler/compiler.js + +/*jshint eqnull:true*/ +Handlebars.Compiler = function() {}; +Handlebars.JavaScriptCompiler = function() {}; + +(function(Compiler, JavaScriptCompiler) { + // the foundHelper register will disambiguate helper lookup from finding a + // function in a context. This is necessary for mustache compatibility, which + // requires that context functions in blocks are evaluated by blockHelperMissing, + // and then proceed as if the resulting value was provided to blockHelperMissing. + + Compiler.prototype = { + compiler: Compiler, + + disassemble: function() { + var opcodes = this.opcodes, opcode, out = [], params, param; + + for (var i=0, l=opcodes.length; i 0) { + this.source[1] = this.source[1] + ", " + locals.join(", "); + } + + // Generate minimizer alias mappings + if (!this.isChild) { + for (var alias in this.context.aliases) { + this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; + } + } + + if (this.source[1]) { + this.source[1] = "var " + this.source[1].substring(2) + ";"; + } + + // Merge children + if (!this.isChild) { + this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; + } + + if (!this.environment.isSimple) { + this.source.push("return buffer;"); + } + + var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; + + for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } + return this.topStackName(); + }, + topStackName: function() { + return "stack" + this.stackSlot; + }, + flushInline: function() { + var inlineStack = this.inlineStack; + if (inlineStack.length) { + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + this.pushStack(entry); + } + } + } + }, + isInline: function() { + return this.inlineStack.length; + }, + + popStack: function(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && (item instanceof Literal)) { + return item.value; + } else { + if (!inline) { + this.stackSlot--; + } + return item; + } + }, + + topStack: function(wrapped) { + var stack = (this.isInline() ? this.inlineStack : this.compileStack), + item = stack[stack.length - 1]; + + if (!wrapped && (item instanceof Literal)) { + return item.value; + } else { + return item; + } + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + '"'; + }, + + setupHelper: function(paramSize, name, missingParams) { + var params = []; + this.setupParams(paramSize, params, missingParams); + var foundHelper = this.nameLookup('helpers', name, 'helper'); + + return { + params: params, + name: foundHelper, + callParams: ["depth0"].concat(params).join(", "), + helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ") + }; + }, + + // the params and contexts arguments are passed in arrays + // to fill in + setupParams: function(paramSize, params, useRegister) { + var options = [], contexts = [], types = [], param, inverse, program; + + options.push("hash:" + this.popStack()); + + inverse = this.popStack(); + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + if (!program) { + this.context.aliases.self = "this"; + program = "self.noop"; + } + + if (!inverse) { + this.context.aliases.self = "this"; + inverse = "self.noop"; + } + + options.push("inverse:" + inverse); + options.push("fn:" + program); + } + + for(var i=0; i)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="
t
",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj; +return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="
",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l) +}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("