int sent_png;
int last_w;
int last_h;
+ int newres;
int serno;
int pop_count;
+ switch_size_t blank;
switch_image_t *banner_img;
switch_time_t banner_timeout;
+ switch_memory_pool_t *pool;
struct local_stream_context *next;
};
int serno;
switch_size_t abuflen;
switch_byte_t *abuf;
+ switch_timer_t timer;
};
typedef struct local_stream_source local_stream_source_t;
static int do_rand(uint32_t count)
{
- double r;
- int index;
-
- if (count < 3) return 0;
+ int r = 0;
- r = ((double) rand() / ((double) (RAND_MAX) + (double) (1)));
- index = (int) (r * count) + 1;
+ switch_mutex_lock(globals.mutex);
+ r = (rand() % count) + 1;
+ switch_mutex_unlock(globals.mutex);
- return index;
+ return r;
}
static void flush_video_queue(switch_queue_t *q)
{
- void *pop;
+ void *pop = NULL;
if (switch_queue_size(q) == 0) {
return;
}
while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_image_t *img = (switch_image_t *) pop;
- switch_img_free(&img);
+ if (pop) {
+ switch_image_t *img = (switch_image_t *) pop;
+ switch_img_free(&img);
+ } else {
+ break;
+ }
}
}
volatile local_stream_source_t *s = (local_stream_source_t *) obj;
local_stream_source_t *source = (local_stream_source_t *) s;
switch_file_handle_t fh = { 0 };
- char file_buf[128] = "", path_buf[512] = "", last_path[512], png_buf[512] = "", tmp_buf[512] = "";
- switch_timer_t timer = { 0 };
+ char file_buf[128] = "", path_buf[512] = "", last_path[512] = "", png_buf[512] = "", tmp_buf[512] = "";
int fd = -1;
switch_buffer_t *audio_buffer;
switch_byte_t *dist_buf;
do_shuffle = 1;
}
+ if (source->prebuf < source->abuflen) {
+ source->prebuf = source->abuflen;
+ }
+
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 (switch_core_timer_init(&source->timer, source->timer_name, source->interval, (int)source->samples, source->pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
+ RUNNING = 0;
+ }
+
if (RUNNING) {
source->ready = 1;
switch_mutex_lock(globals.mutex);
while (RUNNING && !source->stopped && source->ready) {
const char *fname;
+
+ if (source->dir_handle) {
+ switch_dir_close(source->dir_handle);
+ source->dir_handle = NULL;
+ }
if (temp_pool) {
switch_core_destroy_memory_pool(&temp_pool);
while (RUNNING && !source->stopped) {
switch_size_t olen;
const char *artist = NULL, *title = NULL;
+ char tmp_space[128] = "";
if (fd > -1) {
char *pb;
}
}
+
if (dir_count > 1 && !strcmp(last_path, path_buf)) {
continue;
}
continue;
}
+ switch_buffer_zero(audio_buffer);
+
if (switch_core_file_has_video(&fh)) {
flush_video_queue(source->video_q);
}
- switch_buffer_zero(audio_buffer);
-
- 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) {
+ if (switch_file_exists(png_buf, temp_pool) == SWITCH_STATUS_SUCCESS) {
source->cover_art = switch_img_read_png(png_buf, SWITCH_IMG_FMT_I420);
}
}
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 && !artist) {
+ char *e, *p, *args[3];
+ int argc;
+
+ switch_set_string(tmp_space, path_buf);
+ p = tmp_space;
+
+ while((e = strchr(p, '/'))) {
+ *e = '\0';
+ p = e+1;
+ }
+
+ argc = switch_split(p, '-', args);
+
+ if (argc > 0) {
+ while(*args[0] == ' ') {
+ args[0]++;
+ }
+
+ while(end_of(args[0]) == ' ') {
+ end_of(args[0]) = '\0';
+ }
+
+ artist = args[0];
+
+ if (argc > 1) {
+ while(*args[1] == ' ') {
+ args[1]++;
+ }
+ while(end_of(args[1]) == ' ') {
+ end_of(args[1]) = '\0';
+ }
+ title = args[1];
+ }
+
+ if (!title) {
+ title = artist;
+ artist = NULL;
+ }
+ } else {
+ title = p;
+ artist = NULL;
+ }
+ }
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);
+ switch_core_timer_next(&source->timer);
olen = source->samples;
if (source->chime_total) {
source->hup = 0;
if (is_open) {
is_open = 0;
-
+
switch_core_file_close(use_fh);
flush_video_queue(source->video_q);
+ switch_buffer_zero(audio_buffer);
if (use_fh == &source->chime_fh) {
source->chime_counter = source->rate * source->chime_freq;
switch_core_file_close(&fh);
}
}
- if (!is_open) {
- switch_buffer_zero(audio_buffer);
- break;
- } else {
+ if (is_open) {
int svr = 0;
if (switch_core_has_video() && switch_core_file_has_video(use_fh)) {
olen = source->samples;
}
+ switch_assert(source->abuflen >= olen * 2 * source->channels);
+
if (switch_core_file_read(use_fh, source->abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
switch_core_file_close(use_fh);
flush_video_queue(source->video_q);
break;
}
- source->prebuf = (uint32_t)(source->samples * 2 * source->channels);
-
if (!source->total) {
flush_video_queue(source->video_q);
switch_buffer_zero(audio_buffer);
- } else if (used > source->samples * 2 * source->channels) {
- //if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
+ } else if (used && (!is_open || used >= source->abuflen)) {
void *pop;
- uint32_t bused;
+ uint32_t bused = 0;
local_stream_context_t *cp = NULL;
+
+ switch_assert(source->abuflen <= source->prebuf);
+ used = switch_buffer_read(audio_buffer, dist_buf, source->abuflen);
- used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);
-
- 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)) {
+
+ if (!cp->ready) {
continue;
}
-
+
switch_mutex_lock(cp->audio_mutex);
+
+ if (switch_test_flag(cp->handle, SWITCH_FILE_OPEN)) {
+ 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)) {
+ switch_mutex_unlock(cp->audio_mutex);
+ continue;
+ }
+ }
+
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);
while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_image_t *img = (switch_image_t *) pop;
+ switch_image_t *img;
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);
+ if (!pop) break;
+
+ img = (switch_image_t *) pop;
+
+ switch_mutex_lock(source->mutex);
+ if (source->context_list) {
+ if (source->total == 1) {
+ switch_queue_push(source->context_list->video_q, img);
+ } else {
for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
+
+ if (!cp->ready) {
+ continue;
+ }
+
if (cp->video_q) {
imgcp = NULL;
switch_img_copy(img, &imgcp);
}
}
}
- }
- switch_mutex_unlock(source->mutex);
+ }
+ switch_img_free(&img);
}
- switch_img_free(&img);
}
+ switch_mutex_unlock(source->mutex);
}
}
}
- 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);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name);
source->part_reload = 0;
+ if (source->timer.interval) {
+ switch_core_timer_destroy(&source->timer);
+ }
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name);
done:
+ if (source->dir_handle) {
+ switch_dir_close(source->dir_handle);
+ source->dir_handle = NULL;
+ }
+
+ if (source->timer.interval) {
+ switch_core_timer_destroy(&source->timer);
+ }
+
switch_safe_free(source->banner_txt);
if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) {
local_stream_source_t *source;
char *alt_path = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_memory_pool_t *pool;
/* already buffering a step back, so always disable it */
handle->pre_buffer_datalen = 0;
goto end;
}
- if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
+ //if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+ // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
+ // abort();
+ //}
+
+ pool = handle->memory_pool;
+
+ if ((context = switch_core_alloc(pool, sizeof(*context))) == 0) {
abort();
}
- switch_queue_create(&context->video_q, 500, handle->memory_pool);
+ context->pool = pool;
+
+ switch_queue_create(&context->video_q, 500, context->pool);
handle->samples = 0;
handle->samplerate = source->rate;
handle->interval = source->interval;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opening Stream [%s] %dhz\n", path, handle->samplerate);
- switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
+ switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
if (switch_buffer_create_dynamic(&context->audio_buffer, 512, 1024, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
status = SWITCH_STATUS_MEMERR;
static switch_status_t local_stream_file_close(switch_file_handle_t *handle)
{
- local_stream_context_t *cp, *last = NULL, *context = handle->private_info;
+ local_stream_context_t *context = NULL, *last = NULL, *cp = NULL;
+ local_stream_source_t *source;
+
+ context = handle->private_info;
+ switch_assert(context);
+ //pool = context->pool;
+ source = context->source;
context->ready = 0;
- switch_mutex_lock(context->source->mutex);
- for (cp = context->source->context_list; cp; cp = cp->next) {
+ switch_mutex_lock(source->mutex);
+ for (cp = source->context_list; cp; cp = cp->next) {
if (cp == context) {
if (last) {
last->next = cp->next;
} else {
- context->source->context_list = cp->next;
- }
+ source->context_list = cp->next;
+ }
break;
}
last = cp;
}
+
+ switch_mutex_lock(context->audio_mutex);
- if (context->source->has_video) {
+ if (source->has_video) {
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);
}
+
+ source->total--;
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);
+ switch_mutex_unlock(context->audio_mutex);
+ //switch_core_destroy_memory_pool(&pool);
+
+ context->handle = NULL;
+ handle->private_info = NULL;
+ switch_mutex_unlock(source->mutex);
+
+ switch_thread_rwlock_unlock(source->rwlock);
return SWITCH_STATUS_SUCCESS;
}
frame->img = (switch_image_t *) pop;
context->sent_png = 0;
+ if (frame->img->d_w != context->last_w || frame->img->d_h != context->last_h) {
+ context->newres = 1;
+ }
context->last_w = frame->img->d_w;
context->last_h = frame->img->d_h;
goto got_img;
if (context->source->banner_txt) {
if ((!context->banner_timeout || context->banner_timeout >= now)) {
+ if (context->newres) {
+ switch_img_free(&context->banner_img);
+ context->newres = 0;
+ }
if (!context->banner_img) {
context->banner_img = switch_img_write_text_img(context->last_w, context->last_h, SWITCH_TRUE, context->source->banner_txt);
context->banner_timeout = now + 5000000;
if (frame->img && context->banner_img && frame->img->d_w >= context->banner_img->d_w) {
//switch_img_overlay(frame->img, context->banner_img, 0, frame->img->d_h - context->banner_img->d_h, 100);
switch_img_patch(frame->img, context->banner_img, 0, frame->img->d_h - context->banner_img->d_h);
+ //switch_img_patch(frame->img, context->banner_img, 0, 0);
}
return SWITCH_STATUS_SUCCESS;
{
local_stream_context_t *context = handle->private_info;
switch_size_t bytes = 0;
- size_t need = *len * 2 * handle->real_channels;
+ size_t need;
- if (!context->source->ready) {
+ if (!(context->ready && context->source->ready)) {
*len = 0;
return SWITCH_STATUS_FALSE;
}
switch_mutex_lock(context->audio_mutex);
+ need = *len * 2 * context->source->channels;
+
if ((bytes = switch_buffer_read(context->audio_buffer, data, need))) {
- *len = bytes / 2 / handle->real_channels;
+ *len = bytes / 2 / context->source->channels;
} else {
- size_t blank = (handle->samplerate / 20) * 2 * handle->real_channels;
+ size_t blank;
+
+ switch_assert(handle->samplerate <= 48000);
+ switch_assert(handle->real_channels <= 2);
+
+ blank = (handle->samplerate / 4) * 2 * handle->real_channels;
if (need > blank) {
need = blank;
}
+
memset(data, 0, need);
- *len = need / 2 / handle->real_channels;
+ *len = need / 2 / context->source->channels;
}
-
-
switch_mutex_unlock(context->audio_mutex);
handle->sample_count += *len;
+
return SWITCH_STATUS_SUCCESS;
}
}
source->samples = switch_samples_per_packet(source->rate, source->interval);
- source->abuflen = (source->samples * 2 * source->channels) + 1024;
- source->abuf = switch_core_alloc(source->pool, source->abuflen);
+ source->abuflen = (source->samples * 2 * source->channels);
+ source->abuf = switch_core_alloc(source->pool, source->abuflen + 1024);
switch_mutex_init(&source->mutex, SWITCH_MUTEX_NESTED, source->pool);
switch_threadattr_create(&thd_attr, source->pool);
switch_threadattr_detach_set(thd_attr, 1);