static switch_status_t route_lookup(char *dn, easyroute_results_t *results, int noat, char *separator) { switch_status_t sstatus = SWITCH_STATUS_SUCCESS; char *sql = NULL; route_callback_t pdata; if (!switch_odbc_available()) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "mod_easyroute requires core ODBC support. Please refer to the documentation on how to enable this\n"); return sstatus; } memset(&pdata, 0, sizeof(pdata)); if (!globals.custom_query) { sql = switch_mprintf(SQL_LOOKUP, dn); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing static Query\n[%s]\n", sql); } else { sql = switch_mprintf(globals.custom_query, dn); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing custom Query\n[%s]\n", sql); } if (globals.mutex) { switch_mutex_lock(globals.mutex); } /* Do the Query */ if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, route_callback, &pdata, NULL) == SWITCH_ODBC_SUCCESS) { char tmp_profile[129]; char tmp_gateway[129]; if (zstr(pdata.limit)) { switch_set_string(results->limit, "9999"); } else { switch_set_string(results->limit, pdata.limit); } if (zstr(pdata.techprofile)) { switch_set_string(tmp_profile, globals.default_techprofile); } else { switch_set_string(tmp_profile, pdata.techprofile); } if (zstr(pdata.gateway)) { switch_set_string(tmp_gateway, globals.default_gateway); } else { switch_set_string(tmp_gateway, pdata.gateway); } if (zstr(pdata.translated)) { switch_set_string(results->translated, dn); } else { switch_set_string(results->translated, pdata.translated); } if (noat) { switch_snprintf(results->dialstring, 256, "%s/%s%s", tmp_profile, results->translated, tmp_gateway); } else if (separator) { switch_snprintf(results->dialstring, 256, "%s/%s%s%s", tmp_profile, results->translated, separator, tmp_gateway); } else { switch_snprintf(results->dialstring, 256, "%s/%s@%s", tmp_profile, results->translated, tmp_gateway); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "THE ROUTE [%s]\n", results->dialstring); if (zstr(pdata.group)) { switch_set_string(results->group, ""); } else { switch_set_string(results->group, pdata.group); } if (zstr(pdata.acctcode)) { switch_set_string(results->acctcode, ""); } else { switch_set_string(results->acctcode, pdata.acctcode); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DB Error Setting Default Route!\n"); switch_set_string(results->limit, "9999"); if (noat) { switch_snprintf(results->dialstring, 256, "%s/%s%s", globals.default_techprofile, dn, globals.default_gateway); } else if (separator) { switch_snprintf(results->dialstring, 256, "%s/%s%s%s", globals.default_techprofile, dn, separator, globals.default_gateway); } else { switch_snprintf(results->dialstring, 256, "%s/%s@%s", globals.default_techprofile, dn, globals.default_gateway); } switch_set_string(results->group, ""); switch_set_string(results->acctcode, ""); } switch_safe_free(sql); if (globals.mutex) { switch_mutex_unlock(globals.mutex); } return sstatus; }
static switch_status_t load_config(switch_bool_t reload) { switch_status_t status = SWITCH_STATUS_SUCCESS; switch_xml_t cfg, xml = NULL, settings, param, x_profiles, x_profile; switch_cache_db_handle_t *dbh = NULL; if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); return SWITCH_STATUS_TERM; } switch_mutex_lock(globals.mutex); if ((settings = switch_xml_child(cfg, "settings"))) { 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, "odbc-dsn") && !zstr(val)) { if (switch_odbc_available()) { switch_set_string(globals.odbc_dsn, val); if ((globals.odbc_user = strchr(globals.odbc_dsn, ':'))) { *globals.odbc_user++ = '\0'; if ((globals.odbc_pass = strchr(globals.odbc_user, ':'))) { *globals.odbc_pass++ = '\0'; } } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n"); } } else if (!strcasecmp(var, "dbname") && !zstr(val)) { globals.dbname = switch_core_strdup(globals.pool, val); } if (!strcasecmp(var, "debug")) { globals.debug = atoi(val); } } } if ((x_profiles = switch_xml_child(cfg, "profiles"))) { for (x_profile = switch_xml_child(x_profiles, "profile"); x_profile; x_profile = x_profile->next) { load_profile(switch_xml_attr_soft(x_profile, "name")); } } if (zstr(globals.odbc_dsn) && zstr(globals.dbname)) { globals.dbname = switch_core_sprintf(globals.pool, "directory"); } dbh = directory_get_db_handle(); if (dbh) { if (!reload) { switch_cache_db_test_reactive(dbh, "delete from directory_search where uuid != '' and name_visible != '' ", "drop table directory_search", dir_sql); } switch_cache_db_release_db_handle(&dbh); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!2\n"); status = SWITCH_STATUS_TERM; goto end; } end: switch_mutex_unlock(globals.mutex); switch_xml_free(xml); return status; }
static void *SWITCH_THREAD_FUNC switch_nat_multicast_runtime(switch_thread_t * thread, void *obj) { char *buf = NULL; char newip[16] = ""; char *pos; switch_event_t *event = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread started\n"); buf = (char *) malloc(MULTICAST_BUFFSIZE); switch_assert(buf); nat_globals_perm.running = 1; while (nat_globals_perm.running == 1) { size_t len = MULTICAST_BUFFSIZE; switch_status_t status; switch_bool_t do_repub = SWITCH_FALSE; memset(buf, 0, len); status = switch_socket_recvfrom(nat_globals_perm.maddress, nat_globals_perm.msocket, 0, buf, &len); if (!len) { if (SWITCH_STATUS_IS_BREAK(status)) { switch_yield(5000000); continue; } break; } if (nat_globals.nat_type == SWITCH_NAT_TYPE_UPNP) { /* look for our desc URL and servicetype in the packet */ if (strstr(buf, nat_globals.descURL) && (buf == NULL || strstr(buf, nat_globals.data.servicetype))) { if ((pos = strstr(buf, "NTS:"))) { pos = pos + 4; while (*pos && *pos == ' ') { pos++; } if (!strncmp(pos, "ssdp:alive", 10)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP keep alive packet: \n%s\n", buf); /* did pub ip change */ newip[0] = '\0'; if (get_upnp_pubaddr(newip) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to get current pubaddr after receiving UPnP keep alive packet.\n"); } } else if (!strncmp(pos, "ssdp:byebye", 11)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "got UPnP signoff packet. Your NAT gateway is probably going offline.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP signoff packet: \n%s\n", buf); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UNKNOWN UPnP keep alive packet: \n%s\n", buf); } } } } else { /* got some data in NAT-PMP mode, treat any data as a republish event */ if (get_pmp_pubaddr(newip) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to get current pubaddr after receiving UPnP keep alive packet.\n"); } } if ((strlen(newip) > 0) && strcmp(newip, "0.0.0.0") && strcmp(newip, nat_globals.pub_addr)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Public IP changed from '%s' to '%s'.\n", nat_globals.pub_addr, newip); do_repub = SWITCH_TRUE; switch_event_create(&event, SWITCH_EVENT_TRAP); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", nat_globals.pub_addr); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", newip); switch_event_fire(&event); switch_set_string(nat_globals.pub_addr, newip); switch_nat_reinit(); } if (do_repub) { switch_nat_republish(); } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread ending\n"); nat_globals_perm.running = 0; switch_safe_free(buf); return NULL; }
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) { char name[128]; switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; if ((*new_session = switch_core_session_request(modem_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) { private_t *tech_pvt; switch_channel_t *channel; switch_caller_profile_t *caller_profile; char *dest = switch_core_session_strdup(*new_session, outbound_profile->destination_number); char *modem_id_string = NULL; char *number = NULL; int modem_id = 0; modem_t *modem = NULL; if ((modem_id_string = dest)) { if ((number = strchr(modem_id_string, '/'))) { *number++ = '\0'; } } if (zstr(modem_id_string) || zstr(number)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Invalid dial string.\n"); cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; goto fail; } if (!strcasecmp(modem_id_string, "a")) { modem_id = -1; } else { modem_id = atoi(modem_id_string); } if (!(modem = acquire_modem(modem_id))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Cannot find a modem.\n"); cause = SWITCH_CAUSE_USER_BUSY; goto fail; } switch_core_session_add_stream(*new_session, NULL); if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { channel = switch_core_session_get_channel(*new_session); switch_snprintf(name, sizeof(name), "modem/%d/%s", modem->slot, number); switch_channel_set_name(channel, name); if (tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) { cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail; } switch_set_string(modem->digits, number); tech_attach(tech_pvt, modem); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); switch_core_session_destroy(new_session); cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail; } if (outbound_profile) { caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); caller_profile->source = switch_core_strdup(caller_profile->pool, "mod_spandsp"); switch_channel_set_caller_profile(channel, caller_profile); tech_pvt->caller_profile = caller_profile; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Doh! no caller profile\n"); cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail; } switch_channel_set_state(channel, CS_INIT); return SWITCH_CAUSE_SUCCESS; fail: if (new_session) { switch_core_session_destroy(new_session); } if (modem) { modem_set_state(modem, MODEM_STATE_ONHOOK); } } return cause; }
static int control_handler(modem_t *modem, const char *num, int op) { switch_core_session_t *session = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Control Handler op:%d state:[%s] %s\n", op, modem_state2name(modem_get_state(modem)), modem->devlink); switch (op) { case AT_MODEM_CONTROL_ANSWER: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - Answering\n", modem->devlink, modem_state2name(modem_get_state(modem))); modem_set_state(modem, MODEM_STATE_ANSWERED); break; case AT_MODEM_CONTROL_CALL: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - Dialing '%s'\n", modem->devlink, modem_state2name(modem_get_state(modem)), num); modem_set_state(modem, MODEM_STATE_DIALING); switch_clear_flag(modem, MODEM_FLAG_XOFF); wake_modem_thread(modem); switch_set_string(modem->digits, num); if (create_session(&session, modem) != SWITCH_STATUS_SUCCESS) { t31_call_event(modem->t31_state, AT_CALL_EVENT_HANGUP); } else { switch_core_session_thread_launch(session); } } break; case AT_MODEM_CONTROL_OFFHOOK: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - Going off hook\n", modem->devlink, modem_state2name(modem_get_state(modem))); modem_set_state(modem, MODEM_STATE_OFFHOOK); break; case AT_MODEM_CONTROL_ONHOOK: case AT_MODEM_CONTROL_HANGUP: { if (modem_get_state(modem) != MODEM_STATE_RINGING) { int set_state = 1; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - Hanging up\n", modem->devlink, modem_state2name(modem_get_state(modem))); switch_clear_flag(modem, MODEM_FLAG_XOFF); wake_modem_thread(modem); modem_set_state(modem, MODEM_STATE_HANGUP); if (!zstr(modem->uuid_str)) { switch_core_session_t *session; if ((session = switch_core_session_force_locate(modem->uuid_str))) { switch_channel_t *channel = switch_core_session_get_channel(session); if (switch_channel_up(channel)) { switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); set_state = 0; } switch_core_session_rwunlock(session); } } if (set_state) { modem_set_state(modem, MODEM_STATE_ONHOOK); } } } break; case AT_MODEM_CONTROL_DTR: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - DTR %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num); break; case AT_MODEM_CONTROL_RTS: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - RTS %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num); break; case AT_MODEM_CONTROL_CTS: { u_char x[1]; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Modem %s [%s] - CTS %s\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num ? "XON" : "XOFF"); if (num) { x[0] = 0x11; t31_at_tx_handler(&modem->t31_state->at_state, modem, x, 1); switch_clear_flag(modem, MODEM_FLAG_XOFF); wake_modem_thread(modem); } else { x[0] = 0x13; t31_at_tx_handler(&modem->t31_state->at_state, modem, x, 1); switch_set_flag(modem, MODEM_FLAG_XOFF); } } break; case AT_MODEM_CONTROL_CAR: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - CAR %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num); break; case AT_MODEM_CONTROL_RNG: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - RNG %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num); break; case AT_MODEM_CONTROL_DSR: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - DSR %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num); break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Modem %s [%s] - operation %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), op); break; } /*endswitch*/ return 0; }
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj) { local_stream_source_t *source = obj; switch_file_handle_t fh = { 0 }; local_stream_context_t *cp; char file_buf[128] = "", path_buf[512] = "", last_path[512], png_buf[512] = "", tmp_buf[512] = ""; switch_timer_t timer = { 0 }; int fd = -1; switch_buffer_t *audio_buffer; switch_byte_t *dist_buf; switch_size_t used; int skip = 0; switch_memory_pool_t *temp_pool = NULL; uint32_t dir_count = 0, do_shuffle = 0; char *p; switch_mutex_lock(globals.mutex); THREADS++; switch_mutex_unlock(globals.mutex); if (!source->prebuf) { source->prebuf = DEFAULT_PREBUFFER_SIZE; } if (source->shuffle) { do_shuffle = 1; } switch_queue_create(&source->video_q, 500, source->pool); switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0); dist_buf = switch_core_alloc(source->pool, source->prebuf + 10); switch_thread_rwlock_create(&source->rwlock, source->pool); if (RUNNING) { switch_mutex_lock(globals.mutex); switch_core_hash_insert(globals.source_hash, source->name, source); switch_mutex_unlock(globals.mutex); source->ready = 1; } while (RUNNING && !source->stopped) { const char *fname; if (temp_pool) { switch_core_destroy_memory_pool(&temp_pool); } if (switch_core_new_memory_pool(&temp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error creating pool"); goto done; } if (switch_dir_open(&source->dir_handle, source->location, temp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't open directory: %s\n", source->location); goto done; } if (fd > -1) { dir_count = 0; while (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) { dir_count++; } lseek(fd, 0, SEEK_SET); } else { dir_count = switch_dir_count(source->dir_handle); } if (do_shuffle) { skip = do_rand(dir_count); do_shuffle = 0; } switch_yield(1000000); while (RUNNING && !source->stopped) { switch_size_t olen; uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }; const char *artist = NULL, *title = NULL; if (fd > -1) { char *pb; if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) { if ((pb = strchr(path_buf, '\r')) || (pb = strchr(path_buf, '\n'))) { *pb = '\0'; } } else { close(fd); fd = -1; continue; } } else { if (!(fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) { break; } switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname); if (switch_stristr(".loc", path_buf)) { if ((fd = open(path_buf, O_RDONLY)) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname); switch_yield(1000000); } continue; } } if (dir_count > 1 && !strcmp(last_path, path_buf)) { continue; } if (skip > 0) { skip--; continue; } switch_set_string(last_path, path_buf); fname = path_buf; fh.prebuf = source->prebuf; fh.pre_buffer_datalen = source->prebuf; if (switch_core_file_open(&fh, (char *) fname, source->channels, source->rate, SWITCH_FILE_FLAG_VIDEO | SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname); switch_yield(1000000); continue; } if (switch_core_file_has_video(&fh)) { flush_video_queue(source->video_q); } if (switch_core_timer_init(&timer, source->timer_name, source->interval, (int)source->samples, temp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n"); switch_dir_close(source->dir_handle); source->dir_handle = NULL; goto done; } switch_img_free(&source->cover_art); switch_set_string(tmp_buf, path_buf); if ((p = strrchr(tmp_buf, '/'))) { *p++ = '\0'; switch_snprintf(png_buf, sizeof(png_buf), "%s/art/%s.png", tmp_buf, p); if (switch_file_exists(png_buf, source->pool) == SWITCH_STATUS_SUCCESS) { source->cover_art = switch_img_read_png(png_buf, SWITCH_IMG_FMT_I420); } } source->serno++; switch_safe_free(source->banner_txt); title = artist = NULL; switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, &artist); switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_TITLE, &title); if (title && (source->cover_art || switch_core_file_has_video(&fh))) { const char *format = "#cccccc:#333333:FreeSans.ttf:3%:"; if (artist) { source->banner_txt = switch_mprintf("%s%s (%s)", format, title, artist); } else { source->banner_txt = switch_mprintf("%s%s", format, title); } } while (RUNNING && !source->stopped) { int is_open; switch_file_handle_t *use_fh = &fh; switch_core_timer_next(&timer); olen = source->samples; if (source->chime_total) { if (source->chime_counter > 0) { source->chime_counter -= (int32_t)source->samples; } if (!switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN) && source->chime_counter <= 0) { char *val; val = source->chime_list[source->chime_cur++]; if (source->chime_cur >= source->chime_total) { source->chime_cur = 0; } if (switch_core_file_open(&source->chime_fh, (char *) val, source->channels, source->rate, SWITCH_FILE_FLAG_VIDEO | SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", val); } if (switch_core_file_has_video(&source->chime_fh)) { flush_video_queue(source->video_q); } } if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) { use_fh = &source->chime_fh; } } retry: source->has_video = switch_core_file_has_video(use_fh) || source->cover_art || source->banner_txt; is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN); if (source->hup) { source->hup = 0; if (is_open) { is_open = 0; switch_core_file_close(use_fh); flush_video_queue(source->video_q); if (use_fh == &source->chime_fh) { source->chime_counter = source->rate * source->chime_freq; switch_core_file_close(&fh); use_fh = &fh; } goto retry; } } if (is_open) { if (switch_core_has_video() && switch_core_file_has_video(use_fh)) { switch_frame_t vid_frame = { 0 }; if (use_fh == &source->chime_fh && switch_core_file_has_video(&fh)) { if (switch_core_file_read_video(&fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) { switch_img_free(&vid_frame.img); } } if (switch_core_file_read_video(use_fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) { if (vid_frame.img) { int flush = 1; source->has_video = 1; if (source->total) { if (switch_queue_trypush(source->video_q, vid_frame.img) == SWITCH_STATUS_SUCCESS) { flush = 0; } } if (flush) { switch_img_free(&vid_frame.img); flush_video_queue(source->video_q); } } } } else { source->has_video = 0; } if (use_fh == &source->chime_fh) { olen = source->samples; switch_core_file_read(&fh, abuf, &olen); olen = source->samples; } if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { switch_core_file_close(use_fh); flush_video_queue(source->video_q); if (use_fh == &source->chime_fh) { source->chime_counter = source->rate * source->chime_freq; use_fh = &fh; } else { is_open = 0; } } else { if (use_fh == &source->chime_fh && source->chime_max) { source->chime_max_counter += (int32_t)source->samples; if (source->chime_max_counter >= source->chime_max) { source->chime_max_counter = 0; switch_core_file_close(use_fh); flush_video_queue(source->video_q); source->chime_counter = source->rate * source->chime_freq; use_fh = &fh; goto retry; } } if (source->total) { switch_buffer_write(audio_buffer, abuf, olen * 2 * source->channels); } else { switch_buffer_zero(audio_buffer); } } } used = switch_buffer_inuse(audio_buffer); if (!used && !is_open) { break; } if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) { void *pop; used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels); if (!source->total) { flush_video_queue(source->video_q); } else { uint32_t bused = 0; switch_mutex_lock(source->mutex); for (cp = source->context_list; cp && RUNNING; cp = cp->next) { if (source->has_video) { switch_set_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO); } else { switch_clear_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO); } if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) { continue; } switch_mutex_lock(cp->audio_mutex); bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer); if (bused > source->samples * 768) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", cp->func, cp->file, cp->line, bused, (long)source->samples); switch_buffer_zero(cp->audio_buffer); } else { switch_buffer_write(cp->audio_buffer, dist_buf, used); } switch_mutex_unlock(cp->audio_mutex); } switch_mutex_unlock(source->mutex); while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) { switch_image_t *img = (switch_image_t *) pop; switch_image_t *imgcp = NULL; if (source->total == 1) { switch_queue_push(source->context_list->video_q, img); } else { if (source->context_list) { switch_mutex_lock(source->mutex); for (cp = source->context_list; cp && RUNNING; cp = cp->next) { if (cp->video_q) { imgcp = NULL; switch_img_copy(img, &imgcp); if (imgcp) { if (switch_queue_trypush(cp->video_q, imgcp) != SWITCH_STATUS_SUCCESS) { flush_video_queue(cp->video_q); } } } } switch_mutex_unlock(source->mutex); } switch_img_free(&img); } } } } } switch_core_timer_destroy(&timer); if (RUNNING && source->shuffle) { skip = do_rand(dir_count); } } switch_dir_close(source->dir_handle); source->dir_handle = NULL; if (source->full_reload) { if (source->rwlock && switch_thread_rwlock_trywrlock(source->rwlock) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot stop local_stream://%s because it is in use.\n",source->name); if (source->part_reload) { switch_xml_t cfg, xml, directory, param; if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); } if ((directory = switch_xml_find_child(cfg, "directory", "name", source->name))) { for (param = switch_xml_child(directory, "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, "shuffle")) { source->shuffle = switch_true(val); } else if (!strcasecmp(var, "chime-freq")) { int tmp = atoi(val); if (tmp > 1) { source->chime_freq = tmp; } } else if (!strcasecmp(var, "chime-max")) { int tmp = atoi(val); if (tmp > 1) { source->chime_max = tmp; } } else if (!strcasecmp(var, "chime-list")) { char *list_dup = switch_core_strdup(source->pool, val); source->chime_total = switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0]))); } else if (!strcasecmp(var, "interval")) { int tmp = atoi(val); if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) { source->interval = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL); } } if (source->chime_max) { source->chime_max *= source->rate; } if (source->chime_total) { source->chime_counter = source->rate * source->chime_freq; } } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name); source->part_reload = 0; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name); launch_streams(source->name); goto done; } } } done: switch_safe_free(source->banner_txt); if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) { switch_core_file_close(&fh); } if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) { switch_core_file_close(&source->chime_fh); } source->ready = 0; switch_mutex_lock(globals.mutex); switch_core_hash_delete(globals.source_hash, source->name); switch_mutex_unlock(globals.mutex); switch_thread_rwlock_wrlock(source->rwlock); switch_thread_rwlock_unlock(source->rwlock); switch_buffer_destroy(&audio_buffer); flush_video_queue(source->video_q); if (fd > -1) { close(fd); } if (temp_pool) { switch_core_destroy_memory_pool(&temp_pool); } switch_core_destroy_memory_pool(&source->pool); switch_mutex_lock(globals.mutex); THREADS--; switch_mutex_unlock(globals.mutex); return NULL; }