/** * Close file. * @param handle * @return SWITCH_STATUS_SUCCESS */ static switch_status_t fileman_file_close(switch_file_handle_t *handle) { struct fileman_file_context *context = (struct fileman_file_context *)handle->private_info; switch_file_handle_t *fh = &context->fh; if (context->id) { switch_mutex_lock(fileman_globals.mutex); switch_core_hash_delete(fileman_globals.hash, context->id); switch_mutex_unlock(fileman_globals.mutex); } if (switch_test_flag(fh, SWITCH_FILE_OPEN)) { free(context->abuf); if (fh->audio_buffer) { switch_buffer_destroy(&fh->audio_buffer); } if (fh->sp_audio_buffer) { switch_buffer_destroy(&fh->sp_audio_buffer); } return switch_core_file_close(fh); } return SWITCH_STATUS_SUCCESS; }
static switch_status_t local_stream_file_close(switch_file_handle_t *handle) { local_stream_context_t *cp, *last = NULL, *context = handle->private_info; context->ready = 0; switch_mutex_lock(context->source->mutex); for (cp = context->source->context_list; cp; cp = cp->next) { if (cp == context) { if (last) { last->next = cp->next; } else { context->source->context_list = cp->next; } break; } last = cp; } if (context->video_q) { flush_video_queue(context->video_q); switch_queue_trypush(context->video_q, NULL); switch_queue_interrupt_all(context->video_q); flush_video_queue(context->video_q); } switch_img_free(&context->banner_img); context->source->total--; switch_mutex_unlock(context->source->mutex); switch_buffer_destroy(&context->audio_buffer); switch_thread_rwlock_unlock(context->source->rwlock); return SWITCH_STATUS_SUCCESS; }
static switch_status_t tone_stream_file_close(switch_file_handle_t *handle) { switch_buffer_t *audio_buffer = handle->private_info; switch_buffer_destroy(&audio_buffer); return SWITCH_STATUS_SUCCESS; }
static void switch_core_media_bug_destroy(switch_media_bug_t *bug) { switch_event_t *event = NULL; if (bug->raw_read_buffer) { switch_buffer_destroy(&bug->raw_read_buffer); } if (bug->raw_write_buffer) { switch_buffer_destroy(&bug->raw_write_buffer); } if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_STOP) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target); if (bug->session) switch_channel_event_set_data(bug->session->channel, event); switch_event_fire(&event); } }
static switch_status_t webm_file_close(switch_file_handle_t *handle) { webm_file_context_t *context = (webm_file_context_t *)handle->private_info; context->segment->Finalize(); delete context->segment; delete context->writer; if (switch_core_codec_ready(&context->audio_codec)) switch_core_codec_destroy(&context->audio_codec); if (switch_core_codec_ready(&context->video_codec)) switch_core_codec_destroy(&context->video_codec); if (context->timer.interval) { switch_core_timer_destroy(&context->timer); } switch_buffer_destroy(&context->buf); switch_buffer_destroy(&context->audio_buffer); return SWITCH_STATUS_SUCCESS; }
static switch_status_t flite_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags) { flite_t *flite = (flite_t *) sh->private_info; if (flite->audio_buffer) { switch_buffer_destroy(&flite->audio_buffer); } free_wave(flite->w); return SWITCH_STATUS_SUCCESS; }
void WSClientParser::DestroyChannel(WSChannel* wsChannel) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::DestroyChannel( " "this : %p, " "wsChannel : %p " ") \n", this, mpChannel ); if( wsChannel ) { // Audio if (switch_core_codec_ready(&wsChannel->read_codec)) { switch_core_codec_destroy(&wsChannel->read_codec); } if (switch_core_codec_ready(&wsChannel->write_codec)) { switch_core_codec_destroy(&wsChannel->write_codec); } // Video if (switch_core_codec_ready(&wsChannel->video_read_codec)) { switch_core_codec_destroy(&wsChannel->video_read_codec); } if (switch_core_codec_ready(&wsChannel->video_write_codec)) { switch_core_codec_destroy(&wsChannel->video_write_codec); } if( wsChannel->video_readbuf_mutex ) { switch_mutex_destroy(wsChannel->video_readbuf_mutex); wsChannel->video_readbuf_mutex = NULL; } if( wsChannel->session ) { switch_media_handle_destroy(wsChannel->session); wsChannel->session = NULL; } if( wsChannel->video_readbuf ) { switch_buffer_destroy(&wsChannel->video_readbuf); wsChannel->video_readbuf = NULL; } } }
static void teletone_destroy(JSContext * cx, JSObject * obj) { struct teletone_obj *tto = JS_GetPrivate(cx, obj); switch_memory_pool_t *pool; if (tto) { if (tto->timer) { switch_core_timer_destroy(tto->timer); } teletone_destroy_session(&tto->ts); switch_buffer_destroy(&tto->audio_buffer); switch_core_codec_destroy(&tto->codec); pool = tto->pool; tto->pool = NULL; if (pool) { switch_core_destroy_memory_pool(&pool); } } }
static switch_bool_t capture_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_core_session_t *session = switch_core_media_bug_get_session(bug); switch_channel_t *channel = switch_core_session_get_channel(session); struct cap_cb *cb = (struct cap_cb *) user_data; switch (type) { case SWITCH_ABC_TYPE_INIT: break; case SWITCH_ABC_TYPE_CLOSE: { if (cb->buffer) { switch_buffer_destroy(&cb->buffer); } switch_channel_set_private(channel, "snapshot", NULL); } break; case SWITCH_ABC_TYPE_READ: if (cb->buffer) { uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_frame_t frame = { 0 }; frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; if (switch_mutex_trylock(cb->mutex) == SWITCH_STATUS_SUCCESS) { while (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && !switch_test_flag((&frame), SFF_CNG)) { if (frame.datalen) switch_buffer_slide_write(cb->buffer, frame.data, frame.datalen); } switch_mutex_unlock(cb->mutex); } } break; case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }
static switch_status_t rtmp_tcp_close(rtmp_session_t *rsession) { rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io; rtmp_tcp_io_private_t *io_pvt = rsession->io_private; if (io_pvt->socket) { switch_mutex_lock(io->mutex); switch_pollset_remove(io->pollset, io_pvt->pollfd); switch_mutex_unlock(io->mutex); switch_socket_close(io_pvt->socket); io_pvt->socket = NULL; } if ( io_pvt->sendq ) { switch_buffer_destroy(&(io_pvt->sendq)); } return SWITCH_STATUS_SUCCESS; }
static switch_status_t mp4_file_close(switch_file_handle_t *handle) { mp4_file_context_t *context = handle->private_info; if (context->fd) { MP4Close(context->fd, 0); context->fd = NULL; } if (switch_core_codec_ready(&context->audio_codec)) switch_core_codec_destroy(&context->audio_codec); if (switch_core_codec_ready(&context->video_codec)) switch_core_codec_destroy(&context->video_codec); if (context->timer.interval) { switch_core_timer_destroy(&context->timer); } switch_img_free(&context->last_img); switch_buffer_destroy(&context->buf); return SWITCH_STATUS_SUCCESS; }
static switch_status_t local_stream_file_close(switch_file_handle_t *handle) { local_stream_context_t *cp, *last = NULL, *context = handle->private_info; switch_mutex_lock(context->source->mutex); for (cp = context->source->context_list; cp; cp = cp->next) { if (cp == context) { if (last) { last->next = cp->next; } else { context->source->context_list = cp->next; } break; } last = cp; } context->source->total--; switch_mutex_unlock(context->source->mutex); switch_buffer_destroy(&context->audio_buffer); switch_thread_rwlock_unlock(context->source->rwlock); return SWITCH_STATUS_SUCCESS; }
static switch_status_t cepstral_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags) { cepstral_t *cepstral; assert(sh != NULL); cepstral = sh->private_info; assert(cepstral != NULL); cepstral->done = 1; cepstral->done_gen = 1; swift_port_stop(cepstral->port, SWIFT_ASYNC_ANY, SWIFT_EVENT_NOW); /* Close the Swift Port and Engine */ if (NULL != cepstral->port) swift_port_close(cepstral->port); //if (NULL != cepstral->engine) swift_engine_close(cepstral->engine); cepstral->port = NULL; //cepstral->engine = NULL; switch_buffer_destroy(&cepstral->audio_buffer); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags) { switch_status_t status = sh->speech_interface->speech_close(sh, flags); if (!switch_test_flag(sh, SWITCH_SPEECH_FLAG_OPEN)) { return SWITCH_STATUS_FALSE; } if (sh->buffer) { switch_buffer_destroy(&sh->buffer); } switch_resample_destroy(&sh->resampler); UNPROTECT_INTERFACE(sh->speech_interface); if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&sh->memory_pool); } switch_clear_flag(sh, SWITCH_SPEECH_FLAG_OPEN); return status; }
static switch_status_t switch_vpx_destroy(switch_codec_t *codec) { vpx_context_t *context = (vpx_context_t *)codec->private_info; if (context) { if ((codec->flags & SWITCH_CODEC_FLAG_ENCODE)) { vpx_codec_destroy(&context->encoder); } if ((codec->flags & SWITCH_CODEC_FLAG_DECODE)) { vpx_codec_destroy(&context->decoder); } if (context->pic) { vpx_img_free(context->pic); context->pic = NULL; } if (context->vpx_packet_buffer) { switch_buffer_destroy(&context->vpx_packet_buffer); context->vpx_packet_buffer = NULL; } } return SWITCH_STATUS_SUCCESS; }
static inline void free_context(shout_context_t *context) { int ret; if (context) { switch_mutex_lock(context->audio_mutex); context->err++; switch_mutex_unlock(context->audio_mutex); if (context->stream_url) { int sanity = 0; while (context->thread_running) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for stream to terminate: %s\n", context->stream_url); switch_yield(500000); if (++sanity > 10) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for stream to terminate: %s\n", context->stream_url); break; } } } switch_thread_rwlock_wrlock(context->rwlock); if (context->mh) { mpg123_close(context->mh); mpg123_delete(context->mh); } if (context->fp) { unsigned char mp3buffer[8192]; int len; int16_t blank[2048] = { 0 }, *r = NULL; if (context->channels == 2) { r = blank; } len = lame_encode_buffer(context->gfp, blank, r, sizeof(blank) / 2, mp3buffer, sizeof(mp3buffer)); if (len) { ret = fwrite(mp3buffer, 1, len, context->fp); } while ((len = lame_encode_flush(context->gfp, mp3buffer, sizeof(mp3buffer))) > 0) { ret = fwrite(mp3buffer, 1, len, context->fp); if (ret < 0) { break; } } lame_mp3_tags_fid(context->gfp, context->fp); fclose(context->fp); context->fp = NULL; } if (context->shout) { shout_close(context->shout); context->shout = NULL; } if (context->gfp) { lame_close(context->gfp); context->gfp = NULL; } if (context->audio_buffer) { switch_buffer_destroy(&context->audio_buffer); } switch_mutex_destroy(context->audio_mutex); switch_thread_rwlock_unlock(context->rwlock); switch_thread_rwlock_destroy(context->rwlock); } }
void do_telecast(switch_stream_handle_t *stream) { char *path_info = switch_event_get_header(stream->param_event, "http-path-info"); char *uuid = strdup(path_info + 4); switch_core_session_t *tsession; char *fname = "stream.mp3"; if ((fname = strchr(uuid, '/'))) { *fname++ = '\0'; } if (!(tsession = switch_core_session_locate(uuid))) { char *ref = switch_event_get_header(stream->param_event, "http-referer"); stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>Not Found!</h2>\n" "<META http-equiv=\"refresh\" content=\"1;URL=%s\">", ref); } else { switch_media_bug_t *bug = NULL; switch_buffer_t *buffer = NULL; switch_mutex_t *mutex; switch_channel_t *channel = switch_core_session_get_channel(tsession); lame_global_flags *gfp = NULL; switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(tsession, &read_impl); if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stepping into media path so this will work!\n"); switch_ivr_media(uuid, SMF_REBRIDGE); } if (!(gfp = lame_init())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n"); goto end; } lame_set_num_channels(gfp, read_impl.number_of_channels); lame_set_in_samplerate(gfp, read_impl.actual_samples_per_second); lame_set_brate(gfp, 16 * (read_impl.actual_samples_per_second / 8000) * read_impl.number_of_channels); lame_set_mode(gfp, 3); lame_set_quality(gfp, 2); lame_set_errorf(gfp, log_error); lame_set_debugf(gfp, log_debug); lame_set_msgf(gfp, log_msg); lame_set_bWriteVbrTag(gfp, 0); lame_mp3_tags_fid(gfp, NULL); lame_init_params(gfp); lame_print_config(gfp); switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); switch_buffer_create_dynamic(&buffer, 1024, 2048, 0); switch_buffer_add_mutex(buffer, mutex); if (switch_core_media_bug_add(tsession, "telecast", NULL, telecast_callback, buffer, 0, SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING, &bug) != SWITCH_STATUS_SUCCESS) { goto end; } stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s\"\r\n\r\n", fname); while (switch_channel_ready(channel)) { unsigned char mp3buf[TC_BUFFER_SIZE] = ""; int rlen; uint8_t buf[1024]; switch_size_t bytes = 0; if (switch_buffer_inuse(buffer) >= 1024) { switch_buffer_lock(buffer); bytes = switch_buffer_read(buffer, buf, sizeof(buf)); switch_buffer_unlock(buffer); } else { if (!bytes) { switch_cond_next(); continue; } memset(buf, 0, bytes); } if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, bytes / 2, mp3buf, sizeof(mp3buf))) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); goto end; } if (rlen) { if (stream->raw_write_function(stream, mp3buf, rlen)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n"); goto end; } } } end: switch_safe_free(uuid); if (gfp) { lame_close(gfp); gfp = NULL; } if (bug) { switch_core_media_bug_remove(tsession, &bug); } if (buffer) { switch_buffer_destroy(&buffer); } switch_core_session_rwunlock(tsession); } }
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; }
SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) { switch_status_t status; switch_assert(fh != NULL); switch_assert(fh->file_interface != NULL); if (!switch_test_flag(fh, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (fh->params) { switch_event_destroy(&fh->params); } fh->samples_in = 0; fh->max_samples = 0; if (fh->buffer) { switch_buffer_destroy(&fh->buffer); } if (fh->pre_buffer) { if (switch_test_flag(fh, SWITCH_FILE_FLAG_WRITE)) { switch_size_t rlen, blen; int asis = switch_test_flag(fh, SWITCH_FILE_NATIVE); while ((rlen = switch_buffer_inuse(fh->pre_buffer))) { if ((blen = switch_buffer_read(fh->pre_buffer, fh->pre_buffer_data, fh->pre_buffer_datalen))) { if (!asis) blen /= 2; if (fh->channels > 1) blen /= fh->channels; if (fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen) != SWITCH_STATUS_SUCCESS) { break; } } } } switch_buffer_destroy(&fh->pre_buffer); } switch_clear_flag(fh, SWITCH_FILE_OPEN); status = fh->file_interface->file_close(fh); switch_resample_destroy(&fh->resampler); if (fh->spool_path) { char *command; #ifdef _MSC_VER command = switch_mprintf("move %s %s", fh->spool_path, fh->file_path); #else command = switch_mprintf("/bin/mv %s %s", fh->spool_path, fh->file_path); #endif if (system(command) == -1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to copy spooled file [%s] to [%s] because of a command error : %s\n", fh->spool_path, fh->file_path, command); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Copy spooled file [%s] to [%s]\n", fh->spool_path, fh->file_path); } free(command); } UNPROTECT_INTERFACE(fh->file_interface); if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&fh->memory_pool); } switch_safe_free(fh->dbuf); return status; }
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] = ""; 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; switch_mutex_lock(globals.mutex); THREADS++; switch_mutex_unlock(globals.mutex); if (!source->prebuf) { source->prebuf = DEFAULT_PREBUFFER_SIZE; } switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0); dist_buf = switch_core_alloc(source->pool, source->prebuf + 10); if (source->shuffle) { skip = do_rand(); } 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; } switch_yield(1000000); while (RUNNING && !source->stopped) { switch_size_t olen; uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }; if (fd > -1) { char *p; if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) { if ((p = strchr(path_buf, '\r')) || (p = strchr(path_buf, '\n'))) { *p = '\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 (skip > 0) { skip--; continue; } 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_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_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; } 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_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_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) { use_fh = &source->chime_fh; } } retry: 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); if (use_fh == &source->chime_fh) { source->chime_counter = source->rate * source->chime_freq; use_fh = &fh; goto retry; //switch_core_file_close(&fh); } } } if (is_open) { if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { switch_core_file_close(use_fh); if (use_fh == &source->chime_fh) { source->chime_counter = source->rate * source->chime_freq; } 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); source->chime_counter = source->rate * source->chime_freq; use_fh = &fh; goto retry; } } switch_buffer_write(audio_buffer, abuf, olen * 2); } } used = switch_buffer_inuse(audio_buffer); if (!used && !is_open) { break; } if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) { used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2); if (source->total) { uint32_t bused = 0; switch_mutex_lock(source->mutex); for (cp = source->context_list; cp && RUNNING; cp = cp->next) { 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); } } } switch_core_timer_destroy(&timer); if (RUNNING && source->shuffle) { skip = do_rand(); } } 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: 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); 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; }
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] = ""; 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; switch_mutex_lock(globals.mutex); THREADS++; switch_mutex_unlock(globals.mutex); if (!source->prebuf) { source->prebuf = DEFAULT_PREBUFFER_SIZE; } switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0); dist_buf = switch_core_alloc(source->pool, source->prebuf + 10); if (source->shuffle) { skip = do_rand(); } 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; } switch_yield(1000000); while (RUNNING) { switch_size_t olen; uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }; if (fd > -1) { char *p; if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) { if ((p = strchr(path_buf, '\r')) || (p = strchr(path_buf, '\n'))) { *p = '\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 (skip > 0) { skip--; continue; } 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_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_timer_init(&timer, source->timer_name, source->interval, 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; } while (RUNNING) { 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 -= 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_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_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) { use_fh = &source->chime_fh; } } retry: is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN); if (is_open) { if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { switch_core_file_close(use_fh); if (use_fh == &source->chime_fh) { source->chime_counter = source->rate * source->chime_freq; } is_open = 0; } else { if (use_fh == &source->chime_fh && source->chime_max) { source->chime_max_counter += source->samples; if (source->chime_max_counter >= source->chime_max) { source->chime_max_counter = 0; switch_core_file_close(use_fh); source->chime_counter = source->rate * source->chime_freq; use_fh = &fh; goto retry; } } switch_buffer_write(audio_buffer, abuf, olen * 2); } } used = switch_buffer_inuse(audio_buffer); if (!used && !is_open) { break; } if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) { used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2); if (source->total) { switch_mutex_lock(source->mutex); for (cp = source->context_list; cp && RUNNING; cp = cp->next) { if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) { continue; } switch_mutex_lock(cp->audio_mutex); if (switch_buffer_inuse(cp->audio_buffer) > source->samples * 768) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Leaking stream handle! [%s() %s:%d]\n", cp->func, cp->file, cp->line); 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); } } } switch_core_timer_destroy(&timer); if (RUNNING && source->shuffle) { skip = do_rand(); } } switch_dir_close(source->dir_handle); source->dir_handle = NULL; } done: 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); 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; }