Changes of Revision 33
[-] | Changed | nginx.spec |
x 1
2 %define nginx_datadir %{_datadir}/nginx 3 %define nginx_webroot %{nginx_datadir}/html 4 %define rtmp_ext nginx-rtmp-module 5 -%define rtmp_ext_version 0.9.11 6 +%define rtmp_ext_version 0.9.14 7 %define rtmp %{rtmp_ext}-%{rtmp_ext_version} 8 %define rtmp_nover %{rtmp_ext} 9 %define with_rtmp_ext 1 10 11 Name: nginx 12 -version: 1.2.7 13 -Release: 3 14 +version: 1.2.8 15 +Release: 1 16 Summary: Robust, small and high performance http and reverse proxy server 17 Group: System Environment/Daemons 18 19
20 21 22 %changelog 23 +* Sun Apr 14 2013 Carsten Schoene <cs@linux-administrator.com> - 1.2.8-1 24 +- update nginx to 1.2.8 25 +- update rtmp module to 0.9.14 26 + 27 * Mon Mar 04 2013 Carsten Schoene <cs@linux-administrator.com> - 1.2.7-3 28 - update rtmp module to 0.9.11 29 30 |
||
[+] | Changed | nginx-1.2.8.tar.gz/CHANGES ^ |
@@ -1,4 +1,21 @@ +Changes with nginx 1.2.8 02 Apr 2013 + + *) Bugfix: new sessions were not always stored if the "ssl_session_cache + shared" directive was used and there was no free space in shared + memory. + Thanks to Piotr Sikora. + + *) Bugfix: responses might hang if subrequests were used and a DNS error + happened during subrequest processing. + Thanks to Lanshun Zhou. + + *) Bugfix: in the ngx_http_mp4_module. + Thanks to Gernot Vormayr. + + *) Bugfix: in backend usage accounting. + + Changes with nginx 1.2.7 12 Feb 2013 *) Change: now if the "include" directive with mask is used on Unix | ||
[+] | Changed | nginx-1.2.8.tar.gz/CHANGES.ru ^ |
@@ -1,4 +1,21 @@ +Изменения в nginx 1.2.8 02.04.2013 + + *) Исправление: при использовании директивы "ssl_session_cache shared" + новые сессии могли не сохраняться, если заканчивалось место в + разделяемой памяти. + Спасибо Piotr Sikora. + + *) Исправление: ответы могли зависать, если использовались подзапросы и + при обработке подзапроса происходила DNS-ошибка. + Спасибо Lanshun Zhou. + + *) Исправление: в модуле ngx_http_mp4_module. + Спасибо Gernot Vormayr. + + *) Исправление: в процедуре учёта использования бэкендов. + + Изменения в nginx 1.2.7 12.02.2013 *) Изменение: теперь при использовании директивы include с маской на | ||
[+] | Changed | nginx-1.2.8.tar.gz/auto/lib/perl/make ^ |
@@ -6,11 +6,12 @@ cat << END >> $NGX_MAKEFILE $NGX_OBJS/src/http/modules/perl/blib/arch/auto/nginx/nginx.so: \ + \$(CORE_DEPS) \$(HTTP_DEPS) \ src/http/modules/perl/nginx.pm \ src/http/modules/perl/nginx.xs \ src/http/modules/perl/ngx_http_perl_module.h \ $NGX_OBJS/src/http/modules/perl/Makefile - cp -p src/http/modules/perl/nginx.* $NGX_OBJS/src/http/modules/perl/ + cp src/http/modules/perl/nginx.* $NGX_OBJS/src/http/modules/perl/ cd $NGX_OBJS/src/http/modules/perl && \$(MAKE) | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/core/nginx.c ^ |
@@ -594,6 +594,10 @@ var = ngx_alloc(sizeof(NGINX_VAR) + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2, cycle->log); + if (var == NULL) { + ngx_free(env); + return NGX_INVALID_PID; + } p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR)); @@ -633,7 +637,7 @@ ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); - if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) != NGX_OK) { + if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s to %s failed " "before executing new binary process \"%s\"", @@ -648,7 +652,9 @@ pid = ngx_execute(cycle, &ctx); if (pid == NGX_INVALID_PID) { - if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) != NGX_OK) { + if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) + == NGX_FILE_ERROR) + { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s back to %s failed after " "an attempt to execute new binary process \"%s\"", | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/core/nginx.h ^ |
@@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1002007 -#define NGINX_VERSION "1.2.7" +#define nginx_version 1002008 +#define NGINX_VERSION "1.2.8" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/core/ngx_conf_file.c ^ |
@@ -133,7 +133,7 @@ cf->conf_file = &conf_file; - if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) { + if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", filename->data); } | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/core/ngx_connection.c ^ |
@@ -412,7 +412,7 @@ } if (ngx_test_config) { - if (ngx_delete_file(name) == -1) { + if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_delete_file_n " %s failed", name); } @@ -739,7 +739,7 @@ { u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1; - if (ngx_delete_file(name) == -1) { + if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/core/ngx_cycle.c ^ |
@@ -679,7 +679,7 @@ ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); - if (ngx_delete_file(name) == -1) { + if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/event/ngx_event_openssl.c ^ |
@@ -1716,8 +1716,18 @@ } sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t)); + if (sess_id == NULL) { - goto failed; + + /* drop the oldest non-expired session and try once more */ + + ngx_ssl_expire_sessions(cache, shpool, 0); + + sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t)); + + if (sess_id == NULL) { + goto failed; + } } #if (NGX_PTR_SIZE == 8) @@ -1727,8 +1737,18 @@ #else id = ngx_slab_alloc_locked(shpool, sess->session_id_length); + if (id == NULL) { - goto failed; + + /* drop the oldest non-expired session and try once more */ + + ngx_ssl_expire_sessions(cache, shpool, 0); + + id = ngx_slab_alloc_locked(shpool, sess->session_id_length); + + if (id == NULL) { + goto failed; + } } #endif | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/ngx_http_autoindex_module.c ^ |
@@ -489,8 +489,11 @@ } b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1); - ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len); - b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len; + + if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { + ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len); + b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len; + } } *b->last++ = ' '; | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/ngx_http_index_module.c ^ |
@@ -85,12 +85,12 @@ /* * Try to open/test the first index file before the test of directory - * existence because valid requests should be much more than invalid ones. - * If the file open()/stat() would fail, then the directory stat() should - * be more quickly because some data is already cached in the kernel. + * existence because valid requests should prevail over invalid ones. + * If open()/stat() of a file will fail then stat() of a directory + * should be faster because kernel may have already cached some data. * Besides, Win32 may return ERROR_PATH_NOT_FOUND (NGX_ENOTDIR) at once. - * Unix has ENOTDIR error, however, it's less helpful than Win32's one: - * it only indicates that path contains an usual file in place of directory. + * Unix has ENOTDIR error; however, it's less helpful than Win32's one: + * it only indicates that path points to a regular file, not a directory. */ static ngx_int_t | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/ngx_http_mp4_module.c ^ |
@@ -750,6 +750,13 @@ *prev = &mp4->mdat_atom; + if (start_offset > mp4->mdat_data.buf->file_last) { + ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, + "start time is out mp4 mdat atom in \"%s\"", + mp4->file.name.data); + return NGX_ERROR; + } + adjustment = mp4->ftyp_size + mp4->moov_size + ngx_http_mp4_update_mdat_atom(mp4, start_offset) - start_offset; | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/ngx_http_split_clients_module.c ^ |
@@ -218,7 +218,7 @@ part->percent = 0; } else { - if (value[0].data[value[0].len - 1] != '%') { + if (value[0].len == 0 || value[0].data[value[0].len - 1] != '%') { goto invalid; } | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/ngx_http_ssl_module.c ^ |
@@ -593,7 +593,6 @@ for (j = sizeof("shared:") - 1; j < value[i].len; j++) { if (value[i].data[j] == ':') { - value[i].data[j] = '\0'; break; } | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/ngx_http_upstream_keepalive_module.c ^ |
@@ -37,8 +37,6 @@ ngx_event_save_peer_session_pt original_save_session; #endif - ngx_uint_t failed; /* unsigned:1 */ - } ngx_http_upstream_keepalive_peer_data_t; @@ -220,8 +218,6 @@ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get keepalive peer"); - kp->failed = 0; - /* ask balancer */ rc = kp->original_get_peer(pc, kp->data); @@ -282,18 +278,12 @@ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "free keepalive peer"); - /* remember failed state - peer.free() may be called more than once */ - - if (state & NGX_PEER_FAILED) { - kp->failed = 1; - } - /* cache valid connections */ u = kp->upstream; c = pc->connection; - if (kp->failed + if (state & NGX_PEER_FAILED || c == NULL || c->read->eof || c->read->error | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/ngx_http_upstream_least_conn_module.c ^ |
@@ -353,10 +353,6 @@ return; } - if (state == 0 && pc->tries == 0) { - return; - } - lcp->conns[lcp->rrp.current]--; lcp->free_rr_peer(pc, &lcp->rrp, state); | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/modules/perl/nginx.pm ^ |
@@ -50,7 +50,7 @@ HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '1.2.7'; +our $VERSION = '1.2.8'; require XSLoader; XSLoader::load('nginx', $VERSION); | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/ngx_http.h ^ |
@@ -94,7 +94,6 @@ ngx_str_t *args); -ngx_int_t ngx_http_find_server_conf(ngx_http_request_t *r); void ngx_http_update_location_config(ngx_http_request_t *r); void ngx_http_handler(ngx_http_request_t *r); void ngx_http_run_posted_requests(ngx_connection_t *c); | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/ngx_http_file_cache.c ^ |
@@ -1674,8 +1674,6 @@ p = (u_char *) ngx_strchr(name.data, ':'); if (p) { - *p = '\0'; - name.len = p - name.data; p++; | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/ngx_http_request.c ^ |
@@ -2743,6 +2743,7 @@ if (n == NGX_AGAIN) { if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_close_connection(c); + return; } /* | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/ngx_http_upstream.c ^ |
@@ -865,11 +865,13 @@ static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx) { + ngx_connection_t *c; ngx_http_request_t *r; ngx_http_upstream_t *u; ngx_http_upstream_resolved_t *ur; r = ctx->data; + c = r->connection; u = r->upstream; ur = u->resolved; @@ -881,7 +883,7 @@ ngx_resolver_strerror(ctx->state)); ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); - return; + goto failed; } ur->naddrs = ctx->naddrs; @@ -906,13 +908,17 @@ if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; + goto failed; } ngx_resolve_name_done(ctx); ur->ctx = NULL; ngx_http_upstream_connect(r, u); + +failed: + + ngx_http_run_posted_requests(c); } @@ -2840,14 +2846,16 @@ ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); #endif - if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) { - state = NGX_PEER_NEXT; - } else { - state = NGX_PEER_FAILED; - } + if (u->peer.sockaddr) { + + if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) { + state = NGX_PEER_NEXT; + } else { + state = NGX_PEER_FAILED; + } - if (ft_type != NGX_HTTP_UPSTREAM_FT_NOLIVE) { u->peer.free(&u->peer, u->peer.data, state); + u->peer.sockaddr = NULL; } if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) { @@ -3007,8 +3015,9 @@ u->finalize_request(r, rc); - if (u->peer.free) { + if (u->peer.free && u->peer.sockaddr) { u->peer.free(&u->peer, u->peer.data, 0); + u->peer.sockaddr = NULL; } if (u->peer.connection) { | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/ngx_http_upstream_round_robin.c ^ |
@@ -584,10 +584,6 @@ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "free rr peer %ui %ui", pc->tries, state); - if (state == 0 && pc->tries == 0) { - return; - } - /* TODO: NGX_PEER_KEEPALIVE */ if (rrp->peers->single) { | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/http/ngx_http_variables.h ^ |
@@ -57,9 +57,6 @@ ngx_str_t *var, ngx_list_part_t *part, size_t prefix); -#define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL; - - #if (NGX_PCRE) typedef struct { | ||
[+] | Changed | nginx-1.2.8.tar.gz/src/os/unix/ngx_process_cycle.c ^ |
@@ -647,7 +647,7 @@ if (ngx_rename_file((char *) ccf->oldpid.data, (char *) ccf->pid.data) - != NGX_OK) + == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s back to %s failed " | ||
[+] | Deleted | nginx-rtmp-module-0.9.11.tar.bz2/hls/config ^ |
@@ -1,13 +0,0 @@ -ngx_addon_name="ngx_rtmp_hls_module" - -CORE_MODULES="$CORE_MODULES - ngx_rtmp_hls_module \ - " - - -NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ - $ngx_addon_dir/ngx_rtmp_hls_module.c \ - " - -CORE_LIBS="$CORE_LIBS -lavformat -lavcodec -lavutil" - | ||
Deleted | nginx-rtmp-module-0.9.11.tar.bz2/test/www/jwplayer/player.swf ^ | |
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/README.md ^ |
@@ -39,9 +39,7 @@ * Online transcoding with FFmpeg -* HLS (HTTP Live Streaming) support; - requires recent libavformat - (>= 53.31.100) from ffmpeg (ffmpeg.org) +* HLS (HTTP Live Streaming) support * HTTP callbacks (publish/play/record/update etc) @@ -236,10 +234,6 @@ # HLS - # HLS requires libavformat & should be configured as a separate - # NGINX module in addition to nginx-rtmp-module: - # ./configure ... --add-module=/path/to/nginx-rtmp-module/hls ... - # For HLS to work please create a directory in tmpfs (/tmp/app here) # for the fragments. The directory contents is served via HTTP (see # http{} section in config) | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/config ^ |
@@ -19,6 +19,7 @@ ngx_rtmp_notify_module \ ngx_rtmp_log_module \ ngx_rtmp_limit_module \ + ngx_rtmp_hls_module \ " @@ -41,6 +42,7 @@ $ngx_addon_dir/ngx_rtmp_record_module.h \ $ngx_addon_dir/ngx_rtmp_relay_module.h \ $ngx_addon_dir/ngx_rtmp_streams.h \ + $ngx_addon_dir/hls/ngx_rtmp_mpegts.h \ " @@ -74,6 +76,8 @@ $ngx_addon_dir/ngx_rtmp_notify_module.c \ $ngx_addon_dir/ngx_rtmp_log_module.c \ $ngx_addon_dir/ngx_rtmp_limit_module.c \ + $ngx_addon_dir/hls/ngx_rtmp_hls_module.c \ + $ngx_addon_dir/hls/ngx_rtmp_mpegts.c \ " CFLAGS="$CFLAGS -I$ngx_addon_dir" | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/hls/README.md ^ |
@@ -1,9 +1 @@ -# HLS (HTTP Live Streaming) module - -This module should be added explicitly when building NGINX: - - ./configure ... --add-module=/path/to/nginx-rtmp-module/hls ... - -## Requirement - -The module requires ffmpeg version>= 53.31.100 from ffmpeg (ffmpeg.org) +HLS is now a part of rtmp module | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/hls/ngx_rtmp_hls_module.c ^ |
@@ -1,16 +1,12 @@ /* - * Copyright (c) 2012 Roman Arutyunyan + * Copyright (c) 2013 Roman Arutyunyan */ #include <ngx_rtmp.h> #include <ngx_rtmp_cmd_module.h> #include <ngx_rtmp_codec_module.h> - - -#include <libavcodec/avcodec.h> -#include <libavformat/avformat.h> -#include <libavutil/log.h> +#include "ngx_rtmp_mpegts.h" static ngx_rtmp_publish_pt next_publish; @@ -20,37 +16,7 @@ static ngx_int_t ngx_rtmp_hls_postconfiguration(ngx_conf_t *cf); static void * ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf); static char * ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); - - -static ngx_log_t *ngx_rtmp_hls_log; - -static void -ngx_rtmp_hls_av_log_callback(void* avcl, int level, const char* fmt, - va_list args) -{ - char *p; - static char buf[1024]; - int n; - - - n = vsnprintf(buf, sizeof(buf), fmt, args); - buf[n] = 0; - - for (p = buf; *p; ++p) { - if (*p == (u_char)'\n' || *p == (u_char)'\r') { - *p = ' '; - } - } - - if (level <= AV_LOG_ERROR) { - ngx_log_error_core(NGX_LOG_ERR, ngx_rtmp_hls_log, 0, "hls: av: %s", - buf); - return; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_rtmp_hls_log, 0, "hls: av: %s", buf); -} + void *parent, void *child); #define NGX_RTMP_HLS_BUFSIZE (1024*1024) @@ -59,31 +25,25 @@ typedef struct { - ngx_uint_t flags; - ngx_msec_t frag_start; - unsigned publishing:1; unsigned opened:1; - unsigned audio:1; - unsigned video:1; - unsigned header_sent:1; + + ngx_file_t file; ngx_str_t playlist; ngx_str_t playlist_bak; ngx_str_t stream; ngx_str_t name; - ngx_int_t frag; - - ngx_int_t out_vstream; - ngx_int_t out_astream; - int8_t nal_bytes; + uint64_t frag; - int64_t aframe_base; - int64_t aframe_num; + ngx_uint_t audio_cc; + ngx_uint_t video_cc; - AVFormatContext *out_format; + uint64_t aframe_base; + uint64_t aframe_num; + uint64_t offset; } ngx_rtmp_hls_ctx_t; @@ -93,10 +53,11 @@ ngx_msec_t muxdelay; ngx_msec_t sync; ngx_msec_t playlen; - size_t nfrags; + ngx_int_t factor; + ngx_uint_t winfrags; + ngx_uint_t nfrags; ngx_flag_t continuous; - ngx_rtmp_hls_ctx_t **ctx; - ngx_uint_t nbuckets; + ngx_flag_t nodelete; ngx_str_t path; } ngx_rtmp_hls_app_conf_t; @@ -152,6 +113,20 @@ offsetof(ngx_rtmp_hls_app_conf_t, continuous), NULL }, + { ngx_string("hls_nodelete"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_hls_app_conf_t, nodelete), + NULL }, + + { ngx_string("hls_playlist_factor"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_hls_app_conf_t, factor), + NULL }, + ngx_null_command }; @@ -187,201 +162,48 @@ }; -/* convert Flash codec id to FFmpeg codec id */ -#if 0 -static enum CodecID -ngx_rtmp_hls_get_video_codec(ngx_int_t cid) -{ - switch (cid) { - case 1: - return CODEC_ID_JPEG2000; /* JPEG */ - case 2: - return CODEC_ID_FLV1; /* Sorensen H.263 */ - case 3: - return CODEC_ID_FLASHSV; /* Screen video */ - case 4: - return CODEC_ID_VP6F; /* On2 VP6 */ - case 5: - return CODEC_ID_VP6A; /* On2 VP6 Alpha */ - case 6: - return CODEC_ID_FLASHSV2; /* Screen Video 2 */ - case 7: - return CODEC_ID_H264; /* H264 / MPEG4-AVC */ - default: - return CODEC_ID_NONE; - } -} -#endif - -static enum CodecID -ngx_rtmp_hls_get_audio_codec(ngx_int_t cid) -{ - switch (cid) { - case 0: - return CODEC_ID_NONE; /* Uncompressed */ - case 1: - return CODEC_ID_ADPCM_SWF; /* ADPCM */ - case 2: - case 14: - return CODEC_ID_MP3; /* Mp3 */ - case 4: - case 5: - case 6: - return CODEC_ID_NELLYMOSER; /* Nellymoser */ - case 7: - return CODEC_ID_PCM_ALAW; /* G711 */ - case 8: - return CODEC_ID_PCM_MULAW; /* G711Mu */ - case 10: - return CODEC_ID_AAC; /* AAC */ - case 11: - return CODEC_ID_SPEEX; /* Speex */ - default: - return CODEC_ID_NONE; - } -} +#define ngx_rtmp_hls_frag(hacf, f) (hacf->nfrags ? (f) % hacf->nfrags : (f)) -static size_t -ngx_rtmp_hls_chain2buffer(u_char *buffer, size_t size, ngx_chain_t *in, - size_t skip) +static void +ngx_rtmp_hls_chain2buffer(ngx_buf_t *out, ngx_chain_t *in, size_t skip) { - ngx_buf_t out; - - out.pos = buffer; - out.last = buffer + size - FF_INPUT_BUFFER_PADDING_SIZE; + size_t size; for (; in; in = in->next) { + size = in->buf->last - in->buf->pos; if (size < skip) { skip -= size; continue; } - out.pos = ngx_cpymem(out.pos, in->buf->pos + skip, ngx_min( - size - skip, (size_t)(out.last - out.pos))); + + out->last = ngx_cpymem(out->last, in->buf->pos + skip, + ngx_min(size - skip, + (size_t) (out->end - out->last))); skip = 0; } - - return out.pos - buffer; } static ngx_int_t -ngx_rtmp_hls_init_video(ngx_rtmp_session_t *s) +ngx_rtmp_hls_create_parent_dir(ngx_rtmp_session_t *s) { - AVStream *stream; - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (codec_ctx == NULL - || codec_ctx->video_codec_id != NGX_RTMP_VIDEO_H264 - || ctx->video == 1 - || ctx->out_format == NULL) - { - return NGX_OK; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: adding video stream"); - - stream = avformat_new_stream(ctx->out_format, NULL); - if (stream == NULL) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_new_stream failed (video)"); - return NGX_ERROR; - } - - stream->codec->codec_id = CODEC_ID_H264; - stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; - stream->codec->pix_fmt = PIX_FMT_YUV420P; - stream->codec->time_base.den = 25; - stream->codec->time_base.num = 1; - stream->codec->width = 100; - stream->codec->height = 100; + ngx_rtmp_hls_app_conf_t *hacf; - if (ctx->out_format->oformat->flags & AVFMT_GLOBALHEADER) { - stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; - } - - ctx->out_vstream = stream->index; - ctx->video = 1; + hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: video stream: %i", ctx->out_vstream); - - /*if (ctx->header_sent) { - if (av_write_trailer(ctx->out_format) < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_write_trailer failed"); - } - ctx->header_sent = 0; - }*/ - - return NGX_OK; -} - + "hls: creating target folder: '%V'", &hacf->path); -static ngx_int_t -ngx_rtmp_hls_init_audio(ngx_rtmp_session_t *s) -{ - AVStream *stream; - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - enum CodecID cid; - - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (codec_ctx == NULL || ctx->audio == 1 || ctx->out_format == NULL) { + if (ngx_create_dir(hacf->path.data, NGX_RTMP_HLS_DIR_ACCESS) == NGX_OK) { return NGX_OK; } - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: adding audio stream"); + ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, + "hls: error creating target folder: '%V'", &hacf->path); - cid = ngx_rtmp_hls_get_audio_codec(codec_ctx->audio_codec_id); - if (cid == CODEC_ID_NONE) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: no audio"); - return NGX_OK; - } - - stream = avformat_new_stream(ctx->out_format, NULL); - if (stream == NULL) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_new_stream failed (audio)"); - return NGX_ERROR; - } - - stream->codec->codec_id = cid; - stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; - stream->codec->sample_fmt = (codec_ctx->sample_size == 1 ? - AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16); - stream->codec->sample_rate = 48000;/*codec_ctx->sample_rate;*/ - stream->codec->bit_rate = 2000000; - stream->codec->channels = codec_ctx->audio_channels; - - ctx->out_astream = stream->index; - ctx->audio = 1; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: audio stream: %i %iHz", - ctx->out_astream, codec_ctx->sample_rate); -/* - if (ctx->header_sent) { - if (av_write_trailer(ctx->out_format) < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_write_trailer failed"); - } - ctx->header_sent = 0; - } -*/ - return NGX_OK; + return NGX_ERROR; } @@ -393,67 +215,64 @@ u_char *p; ngx_rtmp_hls_ctx_t *ctx; ssize_t n; - ngx_int_t ffrag; + uint64_t ffrag; ngx_rtmp_hls_app_conf_t *hacf; ngx_int_t nretry; hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - nretry = 0; retry: + fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "hls: open failed: '%V'", - &ctx->playlist_bak); - /* try to create parent folder */ - if (nretry == 0 && - ngx_create_dir(hacf->path.data, NGX_RTMP_HLS_DIR_ACCESS) != - NGX_INVALID_FILE) + + if (ngx_errno == NGX_ENOENT && nretry == 0 && + ngx_rtmp_hls_create_parent_dir(s) == NGX_OK) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: creating target folder: '%V'", &hacf->path); - ++nretry; + nretry++; goto retry; } + + ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, + "hls: open failed: '%V'", &ctx->playlist_bak); + return NGX_ERROR; } - ffrag = ctx->frag - hacf->nfrags; - if (ffrag < 1) { - ffrag = 1; - } + ffrag = ctx->frag > hacf->winfrags ? + ctx->frag - (uint64_t) hacf->winfrags : 1; p = ngx_snprintf(buffer, sizeof(buffer), - "#EXTM3U\r\n" - "#EXT-X-TARGETDURATION:%i\r\n" - "#EXT-X-ALLOW-CACHE:NO\r\n" - "#EXT-X-MEDIA-SEQUENCE:%i\r\n\r\n", - /*TODO: float*/(ngx_int_t)(hacf->fraglen / 1000), ffrag); + "#EXTM3U\r\n" + "#EXT-X-MEDIA-SEQUENCE:%uL\r\n" + "#EXT-X-TARGETDURATION:%ui\r\n" + "#EXT-X-ALLOW-CACHE:NO\r\n\r\n", + ctx->frag, (ngx_uint_t) (hacf->fraglen / 1000)); + n = write(fd, buffer, p - buffer); if (n < 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "hls: write failed: '%V'", - &ctx->playlist_bak); + "hls: write failed: '%V'", &ctx->playlist_bak); ngx_close_file(fd); return NGX_ERROR; } for (; ffrag < ctx->frag; ++ffrag) { p = ngx_snprintf(buffer, sizeof(buffer), - "#EXTINF:%i,\r\n" - "%V-%i.ts\r\n", - /*TODO:float*/(ngx_int_t)(hacf->fraglen / 1000), - &ctx->name, ffrag); + "#EXTINF:%i,\r\n" + "%V-%uL.ts\r\n", + (ngx_int_t) (hacf->fraglen / 1000), &ctx->name, + ngx_rtmp_hls_frag(hacf, ffrag)); + n = write(fd, buffer, p - buffer); if (n < 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "hls: write failed: '%V'", - &ctx->playlist_bak); + "hls: write failed '%V'", &ctx->playlist_bak); ngx_close_file(fd); return NGX_ERROR; } @@ -463,8 +282,8 @@ if (ngx_rename_file(ctx->playlist_bak.data, ctx->playlist.data)) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "hls: rename failed: '%V'->'%V'", - &ctx->playlist_bak, &ctx->playlist); + "hls: rename failed: '%V'->'%V'", + &ctx->playlist_bak, &ctx->playlist); return NGX_ERROR; } @@ -473,112 +292,11 @@ static ngx_int_t -ngx_rtmp_hls_initialize(ngx_rtmp_session_t *s) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_app_conf_t *hacf; - AVOutputFormat *format; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - if (ctx == NULL || ctx->out_format || ctx->publishing == 0) { - return NGX_OK; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: initialize stream"); - - /* create output format */ - format = av_guess_format("mpegts", NULL, NULL); - if (format == NULL) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_guess_format failed"); - return NGX_ERROR; - } - ctx->out_format = avformat_alloc_context(); - if (ctx->out_format == NULL) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: avformat_alloc_context failed"); - return NGX_ERROR; - } - ctx->out_format->oformat = format; - ctx->out_format->max_delay = (int64_t)hacf->muxdelay * AV_TIME_BASE / 1000; - - return NGX_ERROR; -} - - -static ngx_int_t -ngx_rtmp_hls_open_file(ngx_rtmp_session_t *s, u_char *fpath) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - AVStream *astream; - static u_char buffer[NGX_RTMP_HLS_BUFSIZE]; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (ctx == NULL || ctx->out_format == NULL) { - return NGX_OK; - } - - if (!ctx->video && !ctx->audio) { - return NGX_OK; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: open stream file '%s'", fpath); - - /* open file */ - if (avio_open(&ctx->out_format->pb, (char *)fpath, AVIO_FLAG_WRITE) < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: avio_open failed"); - return NGX_ERROR; - } - - astream = NULL; - if (codec_ctx && codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC - && codec_ctx->aac_header && codec_ctx->aac_header->buf->last - - codec_ctx->aac_header->buf->pos > 2 - && ctx->audio) - { - astream = ctx->out_format->streams[ctx->out_astream]; - astream->codec->extradata = buffer; - astream->codec->extradata_size = ngx_rtmp_hls_chain2buffer(buffer, - sizeof(buffer), codec_ctx->aac_header, 2); - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: setting AAC extradata %i bytes", - (ngx_int_t)astream->codec->extradata_size); - } - - /* write header */ - if (!ctx->header_sent && - avformat_write_header(ctx->out_format, NULL) < 0) - { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: avformat_write_header failed"); - return NGX_ERROR; - } - ctx->header_sent = 1; - - if (astream) { - astream->codec->extradata = NULL; - astream->codec->extradata_size = 0; - } - - ctx->opened = 1; - ctx->nal_bytes = -1; - - return NGX_OK; -} - - -static ngx_int_t ngx_rtmp_hls_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n, - ngx_chain_t **in) + ngx_chain_t **in) { - u_char *last; - size_t pn; + u_char *last; + size_t pn; if (*in == NULL) { return NGX_ERROR; @@ -586,39 +304,62 @@ for ( ;; ) { last = (*in)->buf->last; + if ((size_t)(last - *src) >= n) { if (dst) { ngx_memcpy(dst, *src, n); } + *src += n; + while (*in && *src == (*in)->buf->last) { *in = (*in)->next; if (*in) { *src = (*in)->buf->pos; } } + return NGX_OK; } pn = last - *src; + if (dst) { ngx_memcpy(dst, *src, pn); dst = (u_char *)dst + pn; } + n -= pn; *in = (*in)->next; + if (*in == NULL) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: failed to read %uz byte(s)", n); + "hls: failed to read %uz byte(s)", n); return NGX_ERROR; } + *src = (*in)->buf->pos; } } static ngx_int_t -ngx_rtmp_hls_append_avc_header(ngx_rtmp_session_t *s, ngx_buf_t *out) +ngx_rtmp_hls_append_aud(ngx_rtmp_session_t *s, ngx_buf_t *out) +{ + static u_char aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; + + if (out->last + sizeof(aud_nal) > out->end) { + return NGX_ERROR; + } + + out->last = ngx_cpymem(out->last, aud_nal, sizeof(aud_nal)); + + return NGX_OK; +} + + +static ngx_int_t +ngx_rtmp_hls_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) { ngx_rtmp_codec_ctx_t *codec_ctx; u_char *p; @@ -629,20 +370,22 @@ ngx_int_t n; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); + codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); + if (ctx == NULL || codec_ctx == NULL) { return NGX_ERROR; } - in = codec_ctx->avc_header; - if (in == NULL) { return NGX_ERROR; } + p = in->buf->pos; - /* skip bytes: + /* + * Skip bytes: * - flv fmt * - H264 CONF/PICT (0x00) * - 0 @@ -651,60 +394,62 @@ * - version * - profile * - compatibility - * - level */ - if (ngx_rtmp_hls_copy(s, NULL, &p, 9, &in) != NGX_OK) { - return NGX_ERROR; - } + * - level + * - nal bytes + */ - /* NAL size length (1,2,4) */ - if (ngx_rtmp_hls_copy(s, &ctx->nal_bytes, &p, 1, &in) != NGX_OK) { + if (ngx_rtmp_hls_copy(s, NULL, &p, 10, &in) != NGX_OK) { return NGX_ERROR; } - ctx->nal_bytes &= 0x03; /* 2 lsb */ - ++ctx->nal_bytes; - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: NAL size bytes: %uz", ctx->nal_bytes); /* number of SPS NALs */ if (ngx_rtmp_hls_copy(s, &nnals, &p, 1, &in) != NGX_OK) { return NGX_ERROR; } + nnals &= 0x1f; /* 5lsb */ + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: SPS number: %uz", nnals); + "h264: SPS number: %uz", nnals); /* SPS */ for (n = 0; ; ++n) { for (; nnals; --nnals) { + /* NAL length */ if (ngx_rtmp_hls_copy(s, &rlen, &p, 2, &in) != NGX_OK) { return NGX_ERROR; } + ngx_rtmp_rmemcpy(&len, &rlen, 2); + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: header NAL length: %uz", (size_t)len); + "h264: header NAL length: %uz", (size_t) len); /* AnnexB prefix */ - if (out->last - out->pos < 4) { + if (out->end - out->last < 4) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: too small buffer for header NAL length"); + "h264: too small buffer for header NAL size"); return NGX_ERROR; } - *out->pos++ = 0; - *out->pos++ = 0; - *out->pos++ = 0; - *out->pos++ = 1; + + *out->last++ = 0; + *out->last++ = 0; + *out->last++ = 0; + *out->last++ = 1; /* NAL body */ - if (out->last - out->pos < len) { + if (out->end - out->last < len) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: too small buffer for header NAL"); + "h264: too small buffer for header NAL"); return NGX_ERROR; } - if (ngx_rtmp_hls_copy(s, out->pos, &p, len, &in) != NGX_OK) { + + if (ngx_rtmp_hls_copy(s, out->last, &p, len, &in) != NGX_OK) { return NGX_ERROR; } - out->pos += len; + + out->last += len; } if (n == 1) { @@ -715,113 +460,109 @@ if (ngx_rtmp_hls_copy(s, &nnals, &p, 1, &in) != NGX_OK) { return NGX_ERROR; } + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: PPS number: %uz", nnals); + "h264: PPS number: %uz", nnals); } return NGX_OK; } -static ngx_int_t -ngx_rtmp_hls_close_file(ngx_rtmp_session_t *s) +static void +ngx_rtmp_hls_next_frag(ngx_rtmp_session_t *s) { - ngx_rtmp_hls_ctx_t *ctx; - + ngx_rtmp_hls_app_conf_t *hacf; + ngx_rtmp_hls_ctx_t *ctx; + ngx_int_t nretry; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - if (av_write_trailer(ctx->out_format) < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_write_trailer failed"); - } - ctx->header_sent = 0; + hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - avio_flush(ctx->out_format->pb); + if (ctx == NULL || hacf == NULL) { + return; + } - if (avio_close(ctx->out_format->pb) < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: avio_close failed"); + if (ctx->opened) { + ngx_close_file(ctx->file.fd); + ctx->opened = 0; } - ctx->opened = 0; + if (hacf->nfrags == 0 && ctx->frag > 2 * hacf->winfrags && + !hacf->nodelete) + { + *ngx_sprintf(ctx->stream.data + ctx->stream.len, "-%uL.ts", + ngx_rtmp_hls_frag(hacf, ctx->frag - 2 * hacf->winfrags)) + = 0; - return NGX_OK; -} + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: delete frag '%s'", ctx->stream.data); + ngx_delete_file(ctx->stream.data); -static void -ngx_rtmp_hls_restart(ngx_rtmp_session_t *s) -{ - ngx_rtmp_hls_app_conf_t *hacf; - ngx_rtmp_hls_ctx_t *ctx; + } + ctx->frag++; - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - if (ctx == NULL || hacf == NULL) { - return; - } + *ngx_sprintf(ctx->stream.data + ctx->stream.len, "-%uL.ts", + ngx_rtmp_hls_frag(hacf, ctx->frag)) = 0; - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: restart frag=%i", ctx->frag); + ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: open frag '%s', frag=%uL", + ctx->stream.data, ctx->frag); - if (ctx->opened) { - ngx_rtmp_hls_close_file(s); - } + ngx_memzero(&ctx->file, sizeof(ctx->file)); - if (ngx_rtmp_hls_initialize(s) != NGX_OK) { - return; - } + ctx->file.log = s->connection->log; - if (ngx_rtmp_hls_init_video(s) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: video init failed"); - } + ngx_str_set(&ctx->file.name, "hls"); - if (ngx_rtmp_hls_init_audio(s) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: audio init failed"); - } + nretry = 0; - /* remember we have preallocated memory in ctx->stream */ +retry: - /* erase old file; - * we should keep old fragments available - * whole next cycle */ - if (ctx->frag > (ngx_int_t)hacf->nfrags * 2) { - *ngx_sprintf(ctx->stream.data + ctx->stream.len, "-%i.ts", - ctx->frag - hacf->nfrags * 2) = 0; - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: delete stream file '%s'", ctx->stream.data); - ngx_delete_file(ctx->stream.data); + ctx->file.fd = ngx_open_file(ctx->stream.data, NGX_FILE_WRONLY, + NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + + if (ctx->file.fd == NGX_INVALID_FILE) { + + if (ngx_errno == NGX_ENOENT && nretry == 0 && + ngx_rtmp_hls_create_parent_dir(s) == NGX_OK) + { + nretry++; + goto retry; + } + + ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, + "hls: error creating fragment file"); + return; } - ++ctx->frag; - ctx->frag_start = ngx_current_msec; + if (ngx_rtmp_mpegts_write_header(&ctx->file) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, + "hls: error writing fragment header"); + ngx_close_file(ctx->file.fd); + return; + } - /* create new one */ - *ngx_sprintf(ctx->stream.data + ctx->stream.len, "-%i.ts", - ctx->frag) = 0; - ngx_rtmp_hls_open_file(s, ctx->stream.data); + ctx->opened = 1; - /* update playlist */ ngx_rtmp_hls_update_playlist(s); } +#define NGX_RTMP_HLS_RESTORE_PREFIX "#EXTM3U\r\n#EXT-X-MEDIA-SEQUENCE:" + + static void -ngx_rtmp_hls_restore_frag(ngx_rtmp_session_t *s) +ngx_rtmp_hls_restore_stream(ngx_rtmp_session_t *s) { ngx_rtmp_hls_ctx_t *ctx; ngx_file_t file; - ngx_file_info_t fi; ssize_t ret; - u_char *p, *last; - u_char buffer[sizeof("-.ts\r\n") + - NGX_OFF_T_LEN]; - - /* try to restore frag from previously stored playlist */ + u_char buffer[sizeof(NGX_RTMP_HLS_RESTORE_PREFIX) - + 1 + NGX_INT64_LEN]; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); @@ -829,46 +570,38 @@ file.log = s->connection->log; + ngx_str_set(&file.name, "m3u8"); + file.fd = ngx_open_file(ctx->playlist.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (file.fd == NGX_INVALID_FILE) { return; } - if (ngx_fd_info(file.fd, &fi)) { - goto done; - } - - ret = ngx_read_file(&file, buffer, sizeof(buffer), - fi.st_size > (off_t) sizeof(buffer) ? - fi.st_size - sizeof(buffer) : 0); + ret = ngx_read_file(&file, buffer, sizeof(buffer), 0); if (ret <= 0) { goto done; } - /* last line example: - * mystream-14.ts\r\n */ - - if (ret < (ssize_t) sizeof(".ts\r\n")) { + if ((size_t) ret < sizeof(NGX_RTMP_HLS_RESTORE_PREFIX)) { goto done; } - ret -= (sizeof(".ts\r\n") - 1); - - last = buffer + ret; - p = last; - while (p > buffer && *(p - 1) != '-') { - --p; - } - - if (p == buffer) { + if (ngx_strncmp(buffer, NGX_RTMP_HLS_RESTORE_PREFIX, + sizeof(NGX_RTMP_HLS_RESTORE_PREFIX) - 1)) + { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "hls: failed to restore stream"); goto done; } - ctx->frag = ngx_atoi(p, (size_t) (last - p)) + 1; + buffer[ret] = 0; + + ctx->frag = strtod((const char *) + &buffer[sizeof(NGX_RTMP_HLS_RESTORE_PREFIX) - 1], NULL); ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: restored frag=%i", ctx->frag); + "hls: restored frag=%uL", ctx->frag); done: ngx_close_file(file.fd); @@ -893,65 +626,74 @@ } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: publish: name='%s' type='%s'", - v->name, v->type); + "hls: publish: name='%s' type='%s'", + v->name, v->type); - /* create context */ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); if (ctx == NULL) { ctx = ngx_palloc(s->connection->pool, sizeof(ngx_rtmp_hls_ctx_t)); ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_hls_module); } + ngx_memzero(ctx, sizeof(ngx_rtmp_hls_ctx_t)); - /* init names & paths */ + /*TODO: escaping does not solve the problem*/ + len = ngx_strlen(v->name); - ctx->name.len = len + (ngx_uint_t)ngx_escape_uri(NULL, v->name, len, - NGX_ESCAPE_URI_COMPONENT); - ctx->name.data = ngx_palloc(s->connection->pool, - ctx->name.len); + ctx->name.len = len + (ngx_uint_t) ngx_escape_uri(NULL, v->name, len, + NGX_ESCAPE_URI_COMPONENT); + ctx->name.data = ngx_palloc(s->connection->pool, ctx->name.len); + ngx_escape_uri(ctx->name.data, v->name, len, NGX_ESCAPE_URI_COMPONENT); + ctx->playlist.data = ngx_palloc(s->connection->pool, - hacf->path.len + 1 + ctx->name.len + sizeof(".m3u8")); + hacf->path.len + 1 + ctx->name.len + + sizeof(".m3u8")); p = ngx_cpymem(ctx->playlist.data, hacf->path.data, hacf->path.len); + if (p[-1] != '/') { *p++ = '/'; } + p = ngx_cpymem(p, ctx->name.data, ctx->name.len); /* ctx->stream_path holds initial part of stream file path * however the space for the whole stream path * is allocated */ + ctx->stream.len = p - ctx->playlist.data; ctx->stream.data = ngx_palloc(s->connection->pool, - ctx->stream.len + 1 + NGX_OFF_T_LEN + sizeof(".ts")); + ctx->stream.len + 1 + NGX_INT64_LEN + sizeof(".ts")); + ngx_memcpy(ctx->stream.data, ctx->playlist.data, ctx->stream.len); /* playlist path */ + p = ngx_cpymem(p, ".m3u8", sizeof(".m3u8") - 1); ctx->playlist.len = p - ctx->playlist.data; *p = 0; /* playlist bak (new playlist) path */ + ctx->playlist_bak.data = ngx_palloc(s->connection->pool, - ctx->playlist.len + sizeof(".bak")); + ctx->playlist.len + sizeof(".bak")); p = ngx_cpymem(ctx->playlist_bak.data, ctx->playlist.data, - ctx->playlist.len); + ctx->playlist.len); p = ngx_cpymem(p, ".bak", sizeof(".bak") - 1); + ctx->playlist_bak.len = p - ctx->playlist_bak.data; + *p = 0; ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: playlist='%V' playlist_bak='%V' stream_pattern='%V'", - &ctx->playlist, &ctx->playlist_bak, &ctx->stream); + "hls: playlist='%V' playlist_bak='%V' stream_pattern='%V'", + &ctx->playlist, &ctx->playlist_bak, &ctx->stream); if (hacf->continuous) { - ngx_rtmp_hls_restore_frag(s); + ngx_rtmp_hls_restore_stream(s); } - /* schedule restart event */ ctx->publishing = 1; - ctx->frag_start = ngx_current_msec - hacf->fraglen - 1; next: return next_publish(s, v); @@ -965,83 +707,185 @@ ngx_rtmp_hls_ctx_t *ctx; hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - if (hacf == NULL || !hacf->hls || ctx == NULL - || ctx->publishing == 0) - { + + if (hacf == NULL || !hacf->hls || ctx == NULL || !ctx->publishing) { goto next; } ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: delete"); + "hls: delete"); ctx->publishing = 0; - if (ctx->out_format == NULL) { - goto next; + if (ctx->opened) { + ngx_close_file(ctx->file.fd); + ctx->opened = 0; } - if (ctx->opened) { - ngx_rtmp_hls_close_file(s); +next: + return next_delete_stream(s, v); +} + + +static ngx_int_t +ngx_rtmp_hls_parse_aac_header(ngx_rtmp_session_t *s, ngx_uint_t *objtype, + ngx_uint_t *srindex, ngx_uint_t *chconf) +{ + ngx_rtmp_codec_ctx_t *codec_ctx; + ngx_chain_t *cl; + u_char *p, b0, b1; + + codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); + + cl = codec_ctx->aac_header; + + p = cl->buf->pos; + + if (ngx_rtmp_hls_copy(s, NULL, &p, 2, &cl) != NGX_OK) { + return NGX_ERROR; } - if (ctx->out_format) { - avformat_free_context(ctx->out_format); - ctx->out_format = NULL; + if (ngx_rtmp_hls_copy(s, &b0, &p, 1, &cl) != NGX_OK) { + return NGX_ERROR; } -next: - return next_delete_stream(s, v); + if (ngx_rtmp_hls_copy(s, &b1, &p, 1, &cl) != NGX_OK) { + return NGX_ERROR; + } + + *objtype = b0 >> 3; + if (*objtype == 0 || *objtype == 0x1f) { + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: unsupported adts object type:%ui", *objtype); + return NGX_ERROR; + } + + (*objtype)--; + + *srindex = ((b0 << 1) & 0x0f) | ((b1 & 0x80) >> 7); + if (*srindex == 0x0f) { + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: unsupported adts sample rate:%ui", *srindex); + return NGX_ERROR; + } + + *chconf = (b1 >> 3) & 0x0f; + + ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: aac object_type:%ui, sample_rate_index:%ui, " + "channel_config:%ui", *objtype, *srindex, *chconf); + + return NGX_OK; +} + + +static void +ngx_rtmp_hls_set_frag(ngx_rtmp_session_t *s, uint64_t ts) +{ + ngx_rtmp_hls_app_conf_t *hacf; + ngx_rtmp_hls_ctx_t *ctx; + uint64_t frag; + + hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); + + frag = ts / hacf->fraglen / 90; + + if (frag == ctx->frag && ctx->opened) { + return; + } + + if (frag != ctx->frag + 1) { + ctx->offset += (ctx->frag + 1) * (uint64_t) hacf->fraglen * 90 - ts; + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: time gap offset=%uL", ctx->offset); + } + + ngx_rtmp_hls_next_frag(s); } static ngx_int_t ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) + ngx_chain_t *in) { ngx_rtmp_hls_app_conf_t *hacf; ngx_rtmp_hls_ctx_t *ctx; ngx_rtmp_codec_ctx_t *codec_ctx; - AVPacket packet; - int64_t dts, ddts; + uint64_t dts; + int64_t ddts; + ngx_rtmp_mpegts_frame_t frame; + ngx_buf_t out; + u_char *p; + ngx_uint_t objtype, srindex, chconf, size; static u_char buffer[NGX_RTMP_HLS_BUFSIZE]; hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); + codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (hacf == NULL || !hacf->hls || ctx == NULL || codec_ctx == NULL || - h->mlen < 1) + + if (hacf == NULL || !hacf->hls || ctx == NULL || + codec_ctx == NULL || h->mlen < 2) { return NGX_OK; } - /* fragment is restarted in video handler; - * however if video stream is missing then do it here */ - if (ctx->video == 0 - && ngx_current_msec - ctx->frag_start > hacf->fraglen) + if (codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_AAC || + codec_ctx->aac_header == NULL) { - ngx_rtmp_hls_restart(s); + return NGX_OK; } - if (!ctx->opened || !ctx->audio) { + ngx_memzero(&frame, sizeof(frame)); + + frame.dts = (uint64_t) h->timestamp * 90 + ctx->offset; + frame.cc = ctx->audio_cc; + frame.pid = 0x101; + frame.sid = 0xc0; + + ngx_memzero(&out, sizeof(out)); + + out.start = buffer; + out.end = buffer + sizeof(buffer); + out.pos = out.start; + out.last = out.pos; + + p = out.last; + out.last += 7; + + if (ngx_rtmp_hls_parse_aac_header(s, &objtype, &srindex, &chconf) + != NGX_OK) + { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "hls: aac header error"); return NGX_OK; } - /* write to file */ - av_init_packet(&packet); - packet.dts = h->timestamp * 90L; - packet.stream_index = ctx->out_astream; - packet.data = buffer; - packet.size = ngx_rtmp_hls_chain2buffer(buffer, sizeof(buffer), in, 1); + size = h->mlen - 2 + 7; + + p[0] = 0xff; + p[1] = 0xf1; + p[2] = (objtype << 6) | (srindex << 2) | (chconf & 0x04); + p[3] = ((chconf & 0x03) << 6) | ((size >> 11) & 0x03); + p[4] = (size >> 3); + p[5] = (size << 5) | 0x1f; + p[6] = 0xfc; + + ngx_rtmp_hls_chain2buffer(&out, in, 2); if (hacf->sync && codec_ctx->sample_rate) { - + /* TODO: We assume here AAC frame size is 1024 * Need to handle AAC frames with frame size of 960 */ dts = ctx->aframe_base + ctx->aframe_num * 90000 * 1024 / codec_ctx->sample_rate; - ddts = dts - packet.dts; + ddts = (int64_t) (dts - frame.dts); ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "hls: sync stat ddts=%L (%.5fs)", @@ -1050,63 +894,105 @@ if (ddts > (int64_t) hacf->sync * 90 || ddts < (int64_t) hacf->sync * -90) { - ctx->aframe_base = packet.dts; + ctx->aframe_base = frame.dts; ctx->aframe_num = 0; ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "hls: sync breakup ddts=%L (%.5fs)", ddts, ddts / 90000.); } else { - packet.dts = dts; + frame.dts = dts; } ctx->aframe_num++; } - packet.pts = packet.dts; + frame.pts = frame.dts; - if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) { - if (packet.size == 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: malformed AAC packet"); - return NGX_OK; - } - ++packet.data; - --packet.size; + /* Fragment is restarted in video handler. + * However if video stream is missing then do it here */ + + if (codec_ctx->avc_header == NULL) { + ngx_rtmp_hls_set_frag(s, frame.dts); } - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: audio dts=%L timestamp=%uD", (int64_t)packet.dts, - h->timestamp); + if (!ctx->opened) { + return NGX_OK; + } - if (av_interleaved_write_frame(ctx->out_format, &packet) < 0) { + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: audio dts=%uL", frame.dts); + + if (ngx_rtmp_mpegts_write_frame(&ctx->file, &frame, &out) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_interleaved_write_frame failed"); + "hls: audio frame failed"); } + + ctx->audio_cc = frame.cc; + return NGX_OK; } static ngx_int_t +ngx_rtmp_hls_get_nal_bytes(ngx_rtmp_session_t *s) +{ + ngx_rtmp_codec_ctx_t *codec_ctx; + ngx_chain_t *cl; + u_char *p; + uint8_t nal_bytes; + + codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); + + cl = codec_ctx->avc_header; + + p = cl->buf->pos; + + if (ngx_rtmp_hls_copy(s, NULL, &p, 9, &cl) != NGX_OK) { + return NGX_ERROR; + } + + /* NAL size length (1,2,4) */ + if (ngx_rtmp_hls_copy(s, &nal_bytes, &p, 1, &cl) != NGX_OK) { + return NGX_ERROR; + } + + nal_bytes &= 0x03; /* 2 lsb */ + + ++nal_bytes; + + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: NAL bytes: %ui", (ngx_uint_t) nal_bytes); + + return nal_bytes; +} + + +static ngx_int_t ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) + ngx_chain_t *in) { ngx_rtmp_hls_app_conf_t *hacf; ngx_rtmp_hls_ctx_t *ctx; ngx_rtmp_codec_ctx_t *codec_ctx; - AVPacket packet; u_char *p; - uint8_t fmt, ftype, htype, llen; + uint8_t fmt, ftype, htype, nal_type, src_nal_type; uint32_t len, rlen; ngx_buf_t out; + uint32_t cts; + ngx_rtmp_mpegts_frame_t frame; + ngx_uint_t nal_bytes; + ngx_int_t aud_sent, sps_pps_sent, rc; static u_char buffer[NGX_RTMP_HLS_BUFSIZE]; - int32_t cts; hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); + codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (hacf == NULL || !hacf->hls || ctx == NULL || codec_ctx == NULL - || h->mlen < 1) + + if (hacf == NULL || !hacf->hls || ctx == NULL || codec_ctx == NULL || + codec_ctx->avc_header == NULL || h->mlen < 1) { return NGX_OK; } @@ -1124,110 +1010,161 @@ /* 1: keyframe (IDR) * 2: inter frame * 3: disposable inter frame */ + ftype = (fmt & 0xf0) >> 4; /* H264 HDR/PICT */ + if (ngx_rtmp_hls_copy(s, &htype, &p, 1, &in) != NGX_OK) { return NGX_ERROR; } + /* proceed only with PICT */ + if (htype != 1) { return NGX_OK; } /* 3 bytes: decoder delay */ + if (ngx_rtmp_hls_copy(s, &cts, &p, 3, &in) != NGX_OK) { return NGX_ERROR; } - cts = ((cts & 0x00FF0000) >> 16) | ((cts & 0x000000FF) << 16) - | (cts & 0x0000FF00); - out.pos = buffer; - out.last = buffer + sizeof(buffer) - FF_INPUT_BUFFER_PADDING_SIZE; - - /* keyframe? */ - if (ftype == 1) { - if (ngx_current_msec - ctx->frag_start > hacf->fraglen) { - ngx_rtmp_hls_restart(s); - } + cts = ((cts & 0x00FF0000) >> 16) | ((cts & 0x000000FF) << 16) | + (cts & 0x0000FF00); - /* Prepend IDR frame with H264 header for random seeks */ - if (ngx_rtmp_hls_append_avc_header(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: error appenging H264 header"); - } - } - - if (!ctx->opened || !ctx->video) { - return NGX_OK; - } + ngx_memzero(&out, sizeof(out)); - if (ctx->nal_bytes == -1) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: nal length size is unknown, " - "waiting for IDR to parse header"); + out.start = buffer; + out.end = buffer + sizeof(buffer); + out.pos = out.start; + out.last = out.pos; + + rc = ngx_rtmp_hls_get_nal_bytes(s); + if (rc < 0) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "hls: failed to parse NAL bytes"); return NGX_OK; } - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: parsing NALs"); + nal_bytes = rc; + aud_sent = 0; + sps_pps_sent = 0; while (in) { - llen = ctx->nal_bytes; - if (ngx_rtmp_hls_copy(s, &rlen, &p, llen, &in) != NGX_OK) { + if (ngx_rtmp_hls_copy(s, &rlen, &p, nal_bytes, &in) != NGX_OK) { return NGX_OK; } + len = 0; - ngx_rtmp_rmemcpy(&len, &rlen, llen); + ngx_rtmp_rmemcpy(&len, &rlen, nal_bytes); + + if (len == 0) { + continue; + } + + if (ngx_rtmp_hls_copy(s, &src_nal_type, &p, 1, &in) != NGX_OK) { + return NGX_OK; + } + + nal_type = src_nal_type & 0x1f; + + ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: h264 NAL type=%ui, len=%uD", + (ngx_uint_t) nal_type, len); + + if (!aud_sent) { + switch (nal_type) { + case 1: + case 5: + if (ngx_rtmp_hls_append_aud(s, &out) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "hls: error appending AUD NAL"); + } + case 9: + aud_sent = 1; + break; + } + } - ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: NAL type=%i llen=%i len=%uD unit_type=%i", - (ngx_int_t)ftype, (ngx_int_t)llen, len, (ngx_int_t)(*p & 0x1f)); + switch (nal_type) { + case 1: + sps_pps_sent = 0; + break; + case 5: + if (sps_pps_sent) { + break; + } + if (ngx_rtmp_hls_append_sps_pps(s, &out) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "hls: error appenging SPS/PPS NALs"); + } + sps_pps_sent = 1; + break; + } /* AnnexB prefix */ - if (out.last - out.pos < 4) { + + if (out.end - out.last < 5) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: not enough buffer for AnnexB prefix"); + "hls: not enough buffer for AnnexB prefix"); return NGX_OK; } /* first AnnexB prefix is long (4 bytes) */ - if (out.pos == buffer) { - *out.pos++ = 0; + + if (out.last == out.pos) { + *out.last++ = 0; } - *out.pos++ = 0; - *out.pos++ = 0; - *out.pos++ = 1; + + *out.last++ = 0; + *out.last++ = 0; + *out.last++ = 1; + *out.last++ = src_nal_type; /* NAL body */ - if (out.last - out.pos < (ngx_int_t) len) { + + if (out.end - out.last < (ngx_int_t) len) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: not enough buffer for NAL"); + "hls: not enough buffer for NAL"); return NGX_OK; } - if (ngx_rtmp_hls_copy(s, out.pos, &p, len, &in) != NGX_OK) { + + if (ngx_rtmp_hls_copy(s, out.last, &p, len - 1, &in) != NGX_OK) { return NGX_ERROR; } - out.pos += len; + + out.last += (len - 1); } - av_init_packet(&packet); - packet.dts = h->timestamp * 90L; - packet.pts = packet.dts + cts * 90; - packet.stream_index = ctx->out_vstream; + ngx_memzero(&frame, sizeof(frame)); - if (ftype == 1) { - packet.flags |= AV_PKT_FLAG_KEY; + frame.cc = ctx->video_cc; + frame.dts = (uint64_t) h->timestamp * 90 + ctx->offset; + frame.pts = frame.dts + cts * 90; + frame.pid = 0x100; + frame.sid = 0xe0; + frame.key = (ftype == 1); + + if (frame.key) { + ngx_rtmp_hls_set_frag(s, frame.dts); } - packet.data = buffer; - packet.size = out.pos - buffer; + if (!ctx->opened) { + return NGX_OK; + } + + ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "hls: video pts=%uL, dts=%uL", frame.pts, frame.dts); - if (av_interleaved_write_frame(ctx->out_format, &packet) < 0) { + if (ngx_rtmp_mpegts_write_frame(&ctx->file, &frame, &out) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: av_interleaved_write_frame failed"); + "hls: video frame failed"); } + ctx->video_cc = frame.cc; + return NGX_OK; } @@ -1235,12 +1172,12 @@ static void * ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf) { - ngx_rtmp_hls_app_conf_t *conf; + ngx_rtmp_hls_app_conf_t *conf; - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_hls_app_conf_t)); - if (conf == NULL) { - return NULL; - } + conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_hls_app_conf_t)); + if (conf == NULL) { + return NULL; + } conf->hls = NGX_CONF_UNSET; conf->fraglen = NGX_CONF_UNSET; @@ -1248,7 +1185,8 @@ conf->sync = NGX_CONF_UNSET; conf->playlen = NGX_CONF_UNSET; conf->continuous = NGX_CONF_UNSET; - conf->nbuckets = 1024; + conf->nodelete = NGX_CONF_UNSET; + conf->factor = NGX_CONF_UNSET; return conf; } @@ -1257,8 +1195,8 @@ static char * ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) { - ngx_rtmp_hls_app_conf_t *prev = parent; - ngx_rtmp_hls_app_conf_t *conf = child; + ngx_rtmp_hls_app_conf_t *prev = parent; + ngx_rtmp_hls_app_conf_t *conf = child; ngx_conf_merge_value(conf->hls, prev->hls, 0); ngx_conf_merge_msec_value(conf->fraglen, prev->fraglen, 5000); @@ -1266,14 +1204,13 @@ ngx_conf_merge_msec_value(conf->sync, prev->sync, 300); ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000); ngx_conf_merge_str_value(conf->path, prev->path, ""); - ngx_conf_merge_value(conf->continuous, prev->continuous, 0); - conf->ctx = ngx_pcalloc(cf->pool, - sizeof(ngx_rtmp_hls_ctx_t *) * conf->nbuckets); - if (conf->ctx == NULL) { - return NGX_CONF_ERROR; - } + ngx_conf_merge_value(conf->continuous, prev->continuous, 1); + ngx_conf_merge_value(conf->nodelete, prev->nodelete, 0); + ngx_conf_merge_value(conf->factor, prev->factor, 2); + if (conf->fraglen) { - conf->nfrags = conf->playlen / conf->fraglen; + conf->winfrags = conf->playlen / conf->fraglen; + conf->nfrags = conf->winfrags * conf->factor; } return NGX_CONF_OK; @@ -1283,10 +1220,9 @@ static ngx_int_t ngx_rtmp_hls_postconfiguration(ngx_conf_t *cf) { - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; + ngx_rtmp_core_main_conf_t *cmcf; + ngx_rtmp_handler_pt *h; - /* av handler */ cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); @@ -1295,18 +1231,11 @@ h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); *h = ngx_rtmp_hls_audio; - /* chain handlers */ next_publish = ngx_rtmp_publish; ngx_rtmp_publish = ngx_rtmp_hls_publish; next_delete_stream = ngx_rtmp_delete_stream; ngx_rtmp_delete_stream = ngx_rtmp_hls_delete_stream; - /* register all ffmpeg stuff */ - av_register_all(); - ngx_rtmp_hls_log = &cf->cycle->new_log; - av_log_set_callback(ngx_rtmp_hls_av_log_callback); - return NGX_OK; } - | ||
[+] | Added | nginx-rtmp-module-0.9.14.tar.bz2/hls/ngx_rtmp_mpegts.c ^ |
@@ -0,0 +1,245 @@ +/* + * Copyright (c) 2013 Roman Arutyunyan + */ + + +#include "ngx_rtmp_mpegts.h" + + +static u_char ngx_rtmp_mpegts_header[] = { + + /* TS */ + 0x47, 0x40, 0x00, 0x10, 0x00, + /* PSI */ + 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00, + /* PAT */ + 0x00, 0x01, 0xf0, 0x01, + /* CRC */ + 0x2e, 0x70, 0x19, 0x05, + /* stuffing 167 bytes */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + + /* TS */ + 0x47, 0x50, 0x01, 0x10, 0x00, + /* PSI */ + 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00, + /* PMT */ + 0xe1, 0x00, + 0xf0, 0x00, + 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264 */ + 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac */ + /*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */ + /* CRC */ + 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */ + /*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */ + /* stuffing 157 bytes */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + + +/* 700 ms PCR delay */ +#define NGX_RTMP_HLS_DELAY 63000 + + +ngx_int_t +ngx_rtmp_mpegts_write_header(ngx_file_t *file) +{ + ssize_t rc; + + rc = ngx_write_file(file, ngx_rtmp_mpegts_header, + sizeof(ngx_rtmp_mpegts_header), 0); + + return rc > 0 ? NGX_OK : rc; +} + + +static u_char * +ngx_rtmp_mpegts_write_pcr(u_char *p, uint64_t pcr) +{ + *p++ = pcr >> 25; + *p++ = pcr >> 17; + *p++ = pcr >> 9; + *p++ = pcr >> 1; + *p++ = pcr << 7 | 0x7e; + *p++ = 0; + + return p; +} + + +static u_char * +ngx_rtmp_mpegts_write_pts(u_char *p, ngx_uint_t fb, uint64_t pts) +{ + ngx_uint_t val; + + val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1; + *p++ = val; + + val = (((pts >> 15) & 0x7fff) << 1) | 1; + *p++ = val >> 8; + *p++ = val; + + val = (((pts) & 0x7fff) << 1) | 1; + *p++ = val >> 8; + *p++ = val; + + return p; +} + + +ngx_int_t +ngx_rtmp_mpegts_write_frame(ngx_file_t *file, ngx_rtmp_mpegts_frame_t *f, + ngx_buf_t *b) +{ + ngx_uint_t pes_size, header_size, body_size, in_size, stuff_size, flags; + u_char packet[188], *p, *base; + ngx_int_t first, rc; + + ngx_log_debug6(NGX_LOG_DEBUG_HTTP, file->log, 0, + "mpegts: pid=%ui, sid=%ui, pts=%uL, " + "dts=%uL, key=%ui, size=%ui", + f->pid, f->sid, f->pts, f->dts, + (ngx_uint_t) f->key, (size_t) (b->last - b->pos)); + + first = 1; + + while (b->pos < b->last) { + p = packet; + + f->cc++; + + *p++ = 0x47; + *p++ = (f->pid >> 8); + + if (first) { + p[-1] |= 0x40; + } + + *p++ = f->pid; + *p++ = 0x10 | (f->cc & 0x0f); /* payload */ + + if (first) { + + if (f->key) { + packet[3] |= 0x20; /* adaptation */ + + *p++ = 7; /* size */ + *p++ = 0x50; /* random access + PCR */ + + p = ngx_rtmp_mpegts_write_pcr(p, f->dts - NGX_RTMP_HLS_DELAY); + } + + /* PES header */ + + *p++ = 0x00; + *p++ = 0x00; + *p++ = 0x01; + *p++ = f->sid; + + header_size = 5; + flags = 0x80; /* PTS */ + + if (f->dts != f->pts) { + header_size += 5; + flags |= 0x40; /* DTS */ + } + + pes_size = (b->last - b->pos) + header_size + 3; + if (pes_size > 0xffff) { + pes_size = 0; + } + + *p++ = (pes_size >> 8); + *p++ = pes_size; + *p++ = 0x80; /* H222 */ + *p++ = flags; + *p++ = header_size; + + p = ngx_rtmp_mpegts_write_pts(p, flags >> 6, f->pts + + NGX_RTMP_HLS_DELAY); + + if (f->dts != f->pts) { + p = ngx_rtmp_mpegts_write_pts(p, 1, f->dts + + NGX_RTMP_HLS_DELAY); + } + + first = 0; + } + + body_size = (ngx_uint_t) (packet + sizeof(packet) - p); + in_size = (ngx_uint_t) (b->last - b->pos); + + if (body_size <= in_size) { + ngx_memcpy(p, b->pos, body_size); + b->pos += body_size; + + } else { + stuff_size = (body_size - in_size); + + if (packet[3] & 0x20) { + + /* has adaptation */ + + base = &packet[5] + packet[4]; + p = ngx_movemem(base + stuff_size, base, p - base); + ngx_memset(base, 0xff, stuff_size); + packet[4] += stuff_size; + + } else { + + /* no adaptation */ + + packet[3] |= 0x20; + p = ngx_movemem(&packet[4] + stuff_size, &packet[4], + p - &packet[4]); + + packet[4] = stuff_size - 1; + if (stuff_size >= 2) { + packet[5] = 0; + ngx_memset(&packet[6], 0xff, stuff_size - 2); + } + } + + ngx_memcpy(p, b->pos, in_size); + b->pos = b->last; + } + + rc = ngx_write_file(file, packet, sizeof(packet), file->offset); + if (rc < 0) { + return rc; + } + } + + return NGX_OK; +} | ||
[+] | Added | nginx-rtmp-module-0.9.14.tar.bz2/hls/ngx_rtmp_mpegts.h ^ |
@@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Roman Arutyunyan + */ + + +#ifndef _NGX_RTMP_MPEGTS_H_INCLUDED_ +#define _NGX_RTMP_MPEGTS_H_INCLUDED_ + + +#include <ngx_core.h> + + +typedef struct { + uint64_t pts; + uint64_t dts; + ngx_uint_t pid; + ngx_uint_t sid; + ngx_uint_t cc; + unsigned key:1; +} ngx_rtmp_mpegts_frame_t; + + +ngx_int_t ngx_rtmp_mpegts_write_header(ngx_file_t *file); +ngx_int_t ngx_rtmp_mpegts_write_frame(ngx_file_t *file, + ngx_rtmp_mpegts_frame_t *f, ngx_buf_t *b); + + +#endif /* _NGX_RTMP_MPEGTS_H_INCLUDED_ */ | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/ngx_rtmp_cmd_module.c ^ |
@@ -41,22 +41,22 @@ ngx_rtmp_set_buflen_t *v); -ngx_rtmp_connect_pt ngx_rtmp_connect = ngx_rtmp_cmd_connect; -ngx_rtmp_disconnect_pt ngx_rtmp_disconnect = ngx_rtmp_cmd_disconnect; -ngx_rtmp_create_stream_pt ngx_rtmp_create_stream = ngx_rtmp_cmd_create_stream; -ngx_rtmp_close_stream_pt ngx_rtmp_close_stream = ngx_rtmp_cmd_close_stream; -ngx_rtmp_delete_stream_pt ngx_rtmp_delete_stream = ngx_rtmp_cmd_delete_stream; -ngx_rtmp_publish_pt ngx_rtmp_publish = ngx_rtmp_cmd_publish; -ngx_rtmp_play_pt ngx_rtmp_play = ngx_rtmp_cmd_play; -ngx_rtmp_seek_pt ngx_rtmp_seek = ngx_rtmp_cmd_seek; -ngx_rtmp_pause_pt ngx_rtmp_pause = ngx_rtmp_cmd_pause; - - -ngx_rtmp_stream_begin_pt ngx_rtmp_stream_begin = ngx_rtmp_cmd_stream_begin; -ngx_rtmp_stream_eof_pt ngx_rtmp_stream_eof = ngx_rtmp_cmd_stream_eof; -ngx_rtmp_stream_dry_pt ngx_rtmp_stream_dry = ngx_rtmp_cmd_stream_dry; -ngx_rtmp_recorded_pt ngx_rtmp_recorded = ngx_rtmp_cmd_recorded; -ngx_rtmp_set_buflen_pt ngx_rtmp_set_buflen = ngx_rtmp_cmd_set_buflen; +ngx_rtmp_connect_pt ngx_rtmp_connect; +ngx_rtmp_disconnect_pt ngx_rtmp_disconnect; +ngx_rtmp_create_stream_pt ngx_rtmp_create_stream; +ngx_rtmp_close_stream_pt ngx_rtmp_close_stream; +ngx_rtmp_delete_stream_pt ngx_rtmp_delete_stream; +ngx_rtmp_publish_pt ngx_rtmp_publish; +ngx_rtmp_play_pt ngx_rtmp_play; +ngx_rtmp_seek_pt ngx_rtmp_seek; +ngx_rtmp_pause_pt ngx_rtmp_pause; + + +ngx_rtmp_stream_begin_pt ngx_rtmp_stream_begin; +ngx_rtmp_stream_eof_pt ngx_rtmp_stream_eof; +ngx_rtmp_stream_dry_pt ngx_rtmp_stream_dry; +ngx_rtmp_recorded_pt ngx_rtmp_recorded; +ngx_rtmp_set_buflen_pt ngx_rtmp_set_buflen; static ngx_int_t ngx_rtmp_cmd_postconfiguration(ngx_conf_t *cf); @@ -766,5 +766,21 @@ *ch = *bh; } + ngx_rtmp_connect = ngx_rtmp_cmd_connect; + ngx_rtmp_disconnect = ngx_rtmp_cmd_disconnect; + ngx_rtmp_create_stream = ngx_rtmp_cmd_create_stream; + ngx_rtmp_close_stream = ngx_rtmp_cmd_close_stream; + ngx_rtmp_delete_stream = ngx_rtmp_cmd_delete_stream; + ngx_rtmp_publish = ngx_rtmp_cmd_publish; + ngx_rtmp_play = ngx_rtmp_cmd_play; + ngx_rtmp_seek = ngx_rtmp_cmd_seek; + ngx_rtmp_pause = ngx_rtmp_cmd_pause; + + ngx_rtmp_stream_begin = ngx_rtmp_cmd_stream_begin; + ngx_rtmp_stream_eof = ngx_rtmp_cmd_stream_eof; + ngx_rtmp_stream_dry = ngx_rtmp_cmd_stream_dry; + ngx_rtmp_recorded = ngx_rtmp_cmd_recorded; + ngx_rtmp_set_buflen = ngx_rtmp_cmd_set_buflen; + return NGX_OK; } | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/ngx_rtmp_limit_module.c ^ |
@@ -99,14 +99,14 @@ n = ++*nconn; ngx_shmtx_unlock(&shpool->mutex); - rc = n > lmcf->max_conn ? NGX_ERROR : NGX_OK; + rc = n > (ngx_uint_t) lmcf->max_conn ? NGX_ERROR : NGX_OK; ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "limit: inc conection counter: %uD", n); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "limit: too many connections: %uD > %ui", + "limit: too many connections: %uD > %i", n, lmcf->max_conn); } | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/ngx_rtmp_notify_module.c ^ |
@@ -788,7 +788,14 @@ if (c >= (u_char)'0' && c <= (u_char)'9') { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "notify: HTTP retcode: %dxx", (int)(c - '0')); - return c == (u_char)'2' ? NGX_OK : NGX_ERROR; + switch (c) { + case (u_char) '2': + return NGX_OK; + case (u_char) '3': + return NGX_AGAIN; + default: + return NGX_ERROR; + } } ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, @@ -814,14 +821,129 @@ static ngx_int_t +ngx_rtmp_notify_parse_http_header(ngx_rtmp_session_t *s, + ngx_chain_t *in, ngx_str_t *name, u_char *data, size_t len) +{ + ngx_buf_t *b; + ngx_int_t matched; + u_char *p, c; + ngx_uint_t n; + + enum { + parse_name, + parse_space, + parse_value, + parse_value_newline + } state = parse_name; + + n = 0; + matched = 0; + + while (in) { + b = in->buf; + + for (p = b->pos; p != b->last; ++p) { + c = *p; + + if (c == '\r') { + continue; + } + + switch (state) { + case parse_value_newline: + if (c == ' ' || c == '\t') { + state = parse_space; + break; + } + + if (matched) { + return n; + } + + if (c == '\n') { + return NGX_OK; + } + + n = 0; + state = parse_name; + + case parse_name: + switch (c) { + case ':': + matched = (n == name->len); + n = 0; + state = parse_space; + break; + case '\n': + n = 0; + break; + default: + if (n < name->len && + ngx_tolower(c) == ngx_tolower(name->data[n])) + { + ++n; + break; + } + n = name->len + 1; + } + break; + + case parse_space: + if (c == ' ' || c == '\t') { + break; + } + state = parse_value; + + case parse_value: + if (c == '\n') { + state = parse_value_newline; + break; + } + + if (matched && n + 1 < len) { + data[n++] = c; + } + + break; + } + } + + in = in->next; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_rtmp_notify_connect_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) { - if (ngx_rtmp_notify_parse_http_retcode(s, in) != NGX_OK) { + ngx_rtmp_connect_t *v = arg; + ngx_int_t rc; + u_char app[NGX_RTMP_MAX_NAME]; + + static ngx_str_t location = ngx_string("location"); + + rc = ngx_rtmp_notify_parse_http_retcode(s, in); + if (rc == NGX_ERROR) { return NGX_ERROR; } - return next_connect(s, (ngx_rtmp_connect_t *)arg); + if (rc == NGX_AGAIN) { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "notify: connect redirect received"); + + rc = ngx_rtmp_notify_parse_http_header(s, in, &location, app, + sizeof(app) - 1); + if (rc > 0) { + *ngx_cpymem(v->app, app, rc) = 0; + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: connect redirect to '%s'", v->app); + } + } + + return next_connect(s, v); } @@ -829,11 +951,31 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) { - if (ngx_rtmp_notify_parse_http_retcode(s, in) != NGX_OK) { + ngx_rtmp_publish_t *v = arg; + ngx_int_t rc; + u_char name[NGX_RTMP_MAX_NAME]; + + static ngx_str_t location = ngx_string("location"); + + rc = ngx_rtmp_notify_parse_http_retcode(s, in); + if (rc == NGX_ERROR) { return NGX_ERROR; } - return next_publish(s, (ngx_rtmp_publish_t *)arg); + if (rc == NGX_AGAIN) { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "notify: publish redirect received"); + + rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, + sizeof(name) - 1); + if (rc > 0) { + *ngx_cpymem(v->name, name, rc) = 0; + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: publish redirect to '%s'", v->name); + } + } + + return next_publish(s, v); } @@ -841,11 +983,31 @@ ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) { - if (ngx_rtmp_notify_parse_http_retcode(s, in) != NGX_OK) { + ngx_rtmp_play_t *v = arg; + ngx_int_t rc; + u_char name[NGX_RTMP_MAX_NAME]; + + static ngx_str_t location = ngx_string("location"); + + rc = ngx_rtmp_notify_parse_http_retcode(s, in); + if (rc == NGX_ERROR) { return NGX_ERROR; } - return next_play(s, (ngx_rtmp_play_t *)arg); + if (rc == NGX_AGAIN) { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "notify: play redirect received"); + + rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, + sizeof(name) - 1); + if (rc > 0) { + *ngx_cpymem(v->name, name, rc) = 0; + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: play redirect to '%s'", v->name); + } + } + + return next_play(s, v); } | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/ngx_rtmp_play_module.c ^ |
@@ -490,6 +490,13 @@ goto next; } + if (!ctx->opened) { + ctx->post_seek = v->offset; + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "play: post seek=%ui", ctx->post_seek); + goto next; + } + if (ngx_rtmp_send_stream_eof(s, NGX_RTMP_MSID) != NGX_OK) { return NGX_ERROR; } @@ -522,6 +529,12 @@ goto next; } + if (!ctx->opened) { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "play: pause ignored"); + goto next; + } + ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: pause=%i timestamp=%f", (ngx_int_t) v->pause, v->position); @@ -676,6 +689,7 @@ ctx->file.fd = NGX_INVALID_FILE; ctx->nentry = NGX_CONF_UNSET_UINT; + ctx->post_seek = NGX_CONF_UNSET_UINT; sfx = &ctx->fmt->sfx; @@ -780,6 +794,7 @@ { ngx_rtmp_play_ctx_t *ctx; ngx_event_t *e; + ngx_uint_t timestamp; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); @@ -809,7 +824,10 @@ return NGX_ERROR; } - if (ngx_rtmp_play_do_seek(s, start < 0 ? 0 : start) != NGX_OK) { + timestamp = ctx->post_seek != NGX_CONF_UNSET_UINT ? ctx->post_seek : + (start < 0 ? 0 : (ngx_uint_t) start); + + if (ngx_rtmp_play_do_seek(s, timestamp) != NGX_OK) { return NGX_ERROR; } @@ -817,6 +835,8 @@ return NGX_ERROR; } + ctx->opened = 1; + return NGX_OK; } | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/ngx_rtmp_play_module.h ^ |
@@ -43,6 +43,7 @@ ngx_rtmp_play_fmt_t *fmt; ngx_event_t send_evt; unsigned playing:1; + unsigned opened:1; ngx_uint_t ncrs; ngx_uint_t nheader; ngx_uint_t nbody; @@ -51,6 +52,7 @@ ngx_uint_t file_id; ngx_int_t aindex, vindex; ngx_uint_t nentry; + ngx_uint_t post_seek; } ngx_rtmp_play_ctx_t; | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/ngx_rtmp_stat_module.c ^ |
@@ -519,7 +519,6 @@ static u_char tbuf[NGX_TIME_T_LEN + 1]; static u_char nbuf[NGX_OFF_T_LEN + 1]; - r->keepalive = 0; slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); if (slcf->stat == 0) { return NGX_DECLINED; | ||
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/test/www/index.html ^ |
@@ -5,16 +5,14 @@ <div id="container">Loading the player ...</div> <script type="text/javascript"> jwplayer("container").setup({ - modes: [ - { type: "flash", - src: "/jwplayer/player.swf", - config: { - bufferlength: 1, - file: "mystream", - streamer: "rtmp://localhost/myapp", - provider: "rtmp", - } + sources: [ + { + file: "rtmp://localhost/myapp?carg=1/mystream?sarg=2" } - ] + ], + autostart: true, + width: 640, + height: 480, + primary: "flash" }); </script> | ||
Added | nginx-rtmp-module-0.9.14.tar.bz2/test/www/jwplayer/jwplayer.flash.swf ^ | |
[+] | Changed | nginx-rtmp-module-0.9.14.tar.bz2/test/www/jwplayer/jwplayer.js ^ |
@@ -1 +1,71 @@ -if(typeof jwplayer=="undefined"){var jwplayer=function(a){if(jwplayer.api){return jwplayer.api.selectPlayer(a)}};var $jw=jwplayer;jwplayer.version="5.9.2156";jwplayer.vid=document.createElement("video");jwplayer.audio=document.createElement("audio");jwplayer.source=document.createElement("source");(function(b){b.utils=function(){};b.utils.typeOf=function(d){var c=typeof d;if(c==="object"){if(d){if(d instanceof Array){c="array"}}else{c="null"}}return c};b.utils.extend=function(){var c=b.utils.extend["arguments"];if(c.length>1){for(var e=1;e<c.length;e++){for(var d in c[e]){c[0][d]=c[e][d]}}return c[0]}return null};b.utils.clone=function(f){var c;var d=b.utils.clone["arguments"];if(d.length==1){switch(b.utils.typeOf(d[0])){case"object":c={};for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;case"array":c=[];for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;default:return d[0];break}}return c};b.utils.extension=function(c){if(!c){return""}c=c.substring(c.lastIndexOf("/")+1,c.length);c=c.split("?")[0];if(c.lastIndexOf(".")>-1){return c.substr(c.lastIndexOf(".")+1,c.length).toLowerCase()}return};b.utils.html=function(c,d){c.innerHTML=d};b.utils.wrap=function(c,d){if(c.parentNode){c.parentNode.replaceChild(d,c)}d.appendChild(c)};b.utils.ajax=function(g,f,c){var e;if(window.XMLHttpRequest){e=new XMLHttpRequest()}else{e=new ActiveXObject("Microsoft.XMLHTTP")}e.onreadystatechange=function(){if(e.readyState===4){if(e.status===200){if(f){if(!b.utils.exists(e.responseXML)){try{if(window.DOMParser){var h=(new DOMParser()).parseFromString(e.responseText,"text/xml");if(h){e=b.utils.extend({},e,{responseXML:h})}}else{h=new ActiveXObject("Microsoft.XMLDOM");h.async="false";h.loadXML(e.responseText);e=b.utils.extend({},e,{responseXML:h})}}catch(j){if(c){c(g)}}}f(e)}}else{if(c){c(g)}}}};try{e.open("GET",g,true);e.send(null)}catch(d){if(c){c(g)}}return e};b.utils.load=function(d,e,c){d.onreadystatechange=function(){if(d.readyState===4){if(d.status===200){if(e){e()}}else{if(c){c()}}}}};b.utils.find=function(d,c){return d.getElementsByTagName(c)};b.utils.append=function(c,d){c.appendChild(d)};b.utils.isIE=function(){return((!+"\v1")||(typeof window.ActiveXObject!="undefined"))};b.utils.userAgentMatch=function(d){var c=navigator.userAgent.toLowerCase();return(c.match(d)!==null)};b.utils.isIOS=function(){return b.utils.userAgentMatch(/iP(hone|ad|od)/i)};b.utils.isIPad=function(){return b.utils.userAgentMatch(/iPad/i)};b.utils.isIPod=function(){return b.utils.userAgentMatch(/iP(hone|od)/i)};b.utils.isAndroid=function(){return b.utils.userAgentMatch(/android/i)};b.utils.isLegacyAndroid=function(){return b.utils.userAgentMatch(/android 2.[012]/i)};b.utils.isBlackberry=function(){return b.utils.userAgentMatch(/blackberry/i)};b.utils.isMobile=function(){return b.utils.userAgentMatch(/(iP(hone|ad|od))|android/i)};b.utils.getFirstPlaylistItemFromConfig=function(c){var d={};var e;if(c.playlist&&c.playlist.length){e=c.playlist[0]}else{e=c}d.file=e.file;d.levels=e.levels;d.streamer=e.streamer;d.playlistfile=e.playlistfile;d.provider=e.provider;if(!d.provider){if(d.file&&(d.file.toLowerCase().indexOf("youtube.com")>-1||d.file.toLowerCase().indexOf("youtu.be")>-1)){d.provider="youtube"}if(d.streamer&&d.streamer.toLowerCase().indexOf("rtmp://")==0){d.provider="rtmp"}if(e.type){d.provider=e.type.toLowerCase()}}if(d.provider=="audio"){d.provider="sound"}return d};b.utils.getOuterHTML=function(c){if(c.outerHTML){return c.outerHTML}else{try{return new XMLSerializer().serializeToString(c)}catch(d){return""}}};b.utils.setOuterHTML=function(f,e){if(f.outerHTML){f.outerHTML=e}else{var g=document.createElement("div");g.innerHTML=e;var c=document.createRange();c.selectNodeContents(g);var d=c.extractContents();f.parentNode.insertBefore(d,f);f.parentNode.removeChild(f)}};b.utils.hasFlash=function(){if(typeof navigator.plugins!="undefined"&&typeof navigator.plugins["Shockwave Flash"]!="undefined"){return true}if(typeof window.ActiveXObject!="undefined"){try{new ActiveXObject("ShockwaveFlash.ShockwaveFlash");return true}catch(c){}}return false};b.utils.getPluginName=function(c){if(c.lastIndexOf("/")>=0){c=c.substring(c.lastIndexOf("/")+1,c.length)}if(c.lastIndexOf("-")>=0){c=c.substring(0,c.lastIndexOf("-"))}if(c.lastIndexOf(".swf")>=0){c=c.substring(0,c.lastIndexOf(".swf"))}if(c.lastIndexOf(".js")>=0){c=c.substring(0,c.lastIndexOf(".js"))}return c};b.utils.getPluginVersion=function(c){if(c.lastIndexOf("-")>=0){if(c.lastIndexOf(".js")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".js"))}else{if(c.lastIndexOf(".swf")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".swf"))}else{return c.substring(c.lastIndexOf("-")+1)}}}return""};b.utils.getAbsolutePath=function(j,h){if(!b.utils.exists(h)){h=document.location.href}if(!b.utils.exists(j)){return undefined}if(a(j)){return j}var k=h.substring(0,h.indexOf("://")+3);var g=h.substring(k.length,h.indexOf("/",k.length+1));var d;if(j.indexOf("/")===0){d=j.split("/")}else{var e=h.split("?")[0];e=e.substring(k.length+g.length+1,e.lastIndexOf("/"));d=e.split("/").concat(j.split("/"))}var c=[];for(var f=0;f<d.length;f++){if(!d[f]||!b.utils.exists(d[f])||d[f]=="."){continue}else{if(d[f]==".."){c.pop()}else{c.push(d[f])}}}return k+g+"/"+c.join("/")};function a(d){if(!b.utils.exists(d)){return}var e=d.indexOf("://");var c=d.indexOf("?");return(e>0&&(c<0||(c>e)))}b.utils.pluginPathType={ABSOLUTE:"ABSOLUTE",RELATIVE:"RELATIVE",CDN:"CDN"};b.utils.getPluginPathType=function(d){if(typeof d!="string"){return}d=d.split("?")[0];var e=d.indexOf("://");if(e>0){return b.utils.pluginPathType.ABSOLUTE}var c=d.indexOf("/");var f=b.utils.extension(d);if(e<0&&c<0&&(!f||!isNaN(f))){return b.utils.pluginPathType.CDN}return b.utils.pluginPathType.RELATIVE};b.utils.mapEmpty=function(c){for(var d in c){return false}return true};b.utils.mapLength=function(d){var c=0;for(var e in d){c++}return c};b.utils.log=function(d,c){if(typeof console!="undefined"&&typeof console.log!="undefined"){if(c){console.log(d,c)}else{console.log(d)}}};b.utils.css=function(d,g,c){if(b.utils.exists(d)){for(var e in g){try{if(typeof g[e]==="undefined"){continue}else{if(typeof g[e]=="number"&&!(e=="zIndex"||e=="opacity")){if(isNaN(g[e])){continue}if(e.match(/color/i)){g[e]="#"+b.utils.strings.pad(g[e].toString(16),6)}else{g[e]=Math.ceil(g[e])+"px"}}}d.style[e]=g[e]}catch(f){}}}};b.utils.isYouTube=function(c){return(c.indexOf("youtube.com")>-1||c.indexOf("youtu.be")>-1)};b.utils.transform=function(e,d,c,g,h){if(!b.utils.exists(d)){d=1}if(!b.utils.exists(c)){c=1}if(!b.utils.exists(g)){g=0}if(!b.utils.exists(h)){h=0}if(d==1&&c==1&&g==0&&h==0){e.style.webkitTransform="";e.style.MozTransform="";e.style.OTransform=""}else{var f="scale("+d+","+c+") translate("+g+"px,"+h+"px)";e.style.webkitTransform=f;e.style.MozTransform=f;e.style.OTransform=f}};b.utils.stretch=function(k,q,p,g,n,h){if(typeof p=="undefined"||typeof g=="undefined"||typeof n=="undefined"||typeof h=="undefined"){return}var d=p/n;var f=g/h;var m=0;var l=0;var e=false;var c={};if(q.parentElement){q.parentElement.style.overflow="hidden"}b.utils.transform(q);switch(k.toUpperCase()){case b.utils.stretching.NONE:c.width=n;c.height=h;c.top=(g-c.height)/2;c.left=(p-c.width)/2;break;case b.utils.stretching.UNIFORM:if(d>f){c.width=n*f;c.height=h*f;if(c.width/p>0.95){e=true;d=Math.ceil(100*p/c.width)/100;f=1;c.width=p}}else{c.width=n*d;c.height=h*d;if(c.height/g>0.95){e=true;d=1;f=Math.ceil(100*g/c.height)/100;c.height=g}}c.top=(g-c.height)/2;c.left=(p-c.width)/2;break;case b.utils.stretching.FILL:if(d>f){c.width=n*d;c.height=h*d}else{c.width=n*f;c.height=h*f}c.top=(g-c.height)/2;c.left=(p-c.width)/2;break;case b.utils.stretching.EXACTFIT:c.width=n;c.height=h;var o=Math.round((n/2)*(1-1/d));var j=Math.round((h/2)*(1-1/f));e=true;c.top=c.left=0;break;default:break}if(e){b.utils.transform(q,d,f,o,j)}b.utils.css(q,c)};b.utils.stretching={NONE:"NONE",FILL:"FILL",UNIFORM:"UNIFORM",EXACTFIT:"EXACTFIT"};b.utils.deepReplaceKeyName=function(k,e,c){switch(b.utils.typeOf(k)){case"array":for(var g=0;g<k.length;g++){k[g]=b.utils.deepReplaceKeyName(k[g],e,c)}break;case"object":for(var f in k){var j,h;if(e instanceof Array&&c instanceof Array){if(e.length!=c.length){continue}else{j=e;h=c}}else{j=[e];h=[c]}var d=f;for(var g=0;g<j.length;g++){d=d.replace(new RegExp(e[g],"g"),c[g])}k[d]=b.utils.deepReplaceKeyName(k[f],e,c);if(f!=d){delete k[f]}}break}return k};b.utils.isInArray=function(e,d){if(!(e)||!(e instanceof Array)){return false}for(var c=0;c<e.length;c++){if(d===e[c]){return true}}return false};b.utils.exists=function(c){switch(typeof(c)){case"string":return(c.length>0);break;case"object":return(c!==null);case"undefined":return false}return true};b.utils.empty=function(c){if(typeof c.hasChildNodes=="function"){while(c.hasChildNodes()){c.removeChild(c.firstChild)}}};b.utils.parseDimension=function(c){if(typeof c=="string"){if(c===""){return 0}else{if(c.lastIndexOf("%")>-1){return c}else{return parseInt(c.replace("px",""),10)}}}return c};b.utils.getDimensions=function(c){if(c&&c.style){return{x:b.utils.parseDimension(c.style.left),y:b.utils.parseDimension(c.style.top),width:b.utils.parseDimension(c.style.width),height:b.utils.parseDimension(c.style.height)}}else{return{}}};b.utils.getElementWidth=function(c){if(!c){return null}else{if(c==document.body){return b.utils.parentNode(c).clientWidth}else{if(c.clientWidth>0){return c.clientWidth}else{if(c.style){return b.utils.parseDimension(c.style.width)}else{return null}}}}};b.utils.getElementHeight=function(c){if(!c){return null}else{if(c==document.body){return b.utils.parentNode(c).clientHeight}else{if(c.clientHeight>0){return c.clientHeight}else{if(c.style){return b.utils.parseDimension(c.style.height)}else{return null}}}}};b.utils.timeFormat=function(c){str="00:00";if(c>0){str=Math.floor(c/60)<10?"0"+Math.floor(c/60)+":":Math.floor(c/60)+":";str+=Math.floor(c%60)<10?"0"+Math.floor(c%60):Math.floor(c%60)}return str};b.utils.useNativeFullscreen=function(){return(navigator&&navigator.vendor&&navigator.vendor.indexOf("Apple")==0)};b.utils.parentNode=function(c){if(!c){return docuemnt.body}else{if(c.parentNode){return c.parentNode}else{if(c.parentElement){return c.parentElement}else{return c}}}};b.utils.getBoundingClientRect=function(c){if(typeof c.getBoundingClientRect=="function"){return c.getBoundingClientRect()}else{return{left:c.offsetLeft+document.body.scrollLeft,top:c.offsetTop+document.body.scrollTop,width:c.offsetWidth,height:c.offsetHeight}}};b.utils.translateEventResponse=function(e,c){var g=b.utils.extend({},c);if(e==b.api.events.JWPLAYER_FULLSCREEN&&!g.fullscreen){g.fullscreen=g.message=="true"?true:false;delete g.message}else{if(typeof g.data=="object"){g=b.utils.extend(g,g.data);delete g.data}else{if(typeof g.metadata=="object"){b.utils.deepReplaceKeyName(g.metadata,["__dot__","__spc__","__dsh__"],["."," ","-"])}}}var d=["position","duration","offset"];for(var f in d){if(g[d[f]]){g[d[f]]=Math.round(g[d[f]]*1000)/1000}}return g};b.utils.saveCookie=function(c,d){document.cookie="jwplayer."+c+"="+d+"; path=/"};b.utils.getCookies=function(){var f={};var e=document.cookie.split("; ");for(var d=0;d<e.length;d++){var c=e[d].split("=");if(c[0].indexOf("jwplayer.")==0){f[c[0].substring(9,c[0].length)]=c[1]}}return f};b.utils.readCookie=function(c){return b.utils.getCookies()[c]}})(jwplayer);(function(a){a.events=function(){};a.events.COMPLETE="COMPLETE";a.events.ERROR="ERROR"})(jwplayer);(function(jwplayer){jwplayer.events.eventdispatcher=function(debug){var _debug=debug;var _listeners;var _globallisteners;this.resetEventListeners=function(){_listeners={};_globallisteners=[]};this.resetEventListeners();this.addEventListener=function(type,listener,count){try{if(!jwplayer.utils.exists(_listeners[type])){_listeners[type]=[]}if(typeof(listener)=="string"){eval("listener = "+listener)}_listeners[type].push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeEventListener=function(type,listener){if(!_listeners[type]){return}try{for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){if(_listeners[type][listenerIndex].listener.toString()==listener.toString()){_listeners[type].splice(listenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.addGlobalListener=function(listener,count){try{if(typeof(listener)=="string"){eval("listener = "+listener)}_globallisteners.push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeGlobalListener=function(listener){if(!listener){return}try{for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){if(_globallisteners[globalListenerIndex].listener.toString()==listener.toString()){_globallisteners.splice(globalListenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.sendEvent=function(type,data){if(!jwplayer.utils.exists(data)){data={}}if(_debug){jwplayer.utils.log(type,data)}if(typeof _listeners[type]!="undefined"){for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){try{_listeners[type][listenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_listeners[type][listenerIndex].listener)}if(_listeners[type][listenerIndex]){if(_listeners[type][listenerIndex].count===1){delete _listeners[type][listenerIndex]}else{if(_listeners[type][listenerIndex].count>0){_listeners[type][listenerIndex].count=_listeners[type][listenerIndex].count-1}}}}}for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){try{_globallisteners[globalListenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_globallisteners[globalListenerIndex].listener)}if(_globallisteners[globalListenerIndex]){if(_globallisteners[globalListenerIndex].count===1){delete _globallisteners[globalListenerIndex]}else{if(_globallisteners[globalListenerIndex].count>0){_globallisteners[globalListenerIndex].count=_globallisteners[globalListenerIndex].count-1}}}}}}})(jwplayer);(function(a){var b={};a.utils.animations=function(){};a.utils.animations.transform=function(c,d){c.style.webkitTransform=d;c.style.MozTransform=d;c.style.OTransform=d;c.style.msTransform=d};a.utils.animations.transformOrigin=function(c,d){c.style.webkitTransformOrigin=d;c.style.MozTransformOrigin=d;c.style.OTransformOrigin=d;c.style.msTransformOrigin=d};a.utils.animations.rotate=function(c,d){a.utils.animations.transform(c,["rotate(",d,"deg)"].join(""))};a.utils.cancelAnimation=function(c){delete b[c.id]};a.utils.fadeTo=function(m,f,e,j,h,d){if(b[m.id]!=d&&a.utils.exists(d)){return}if(m.style.opacity==f){return}var c=new Date().getTime();if(d>c){setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},d-c)}if(m.style.display=="none"){m.style.display="block"}if(!a.utils.exists(j)){j=m.style.opacity===""?1:m.style.opacity}if(m.style.opacity==f&&m.style.opacity!==""&&a.utils.exists(d)){if(f===0){m.style.display="none"}return}if(!a.utils.exists(d)){d=c;b[m.id]=d}if(!a.utils.exists(h)){h=0}var k=(e>0)?((c-d)/(e*1000)):0;k=k>1?1:k;var l=f-j;var g=j+(k*l);if(g>1){g=1}else{if(g<0){g=0}}m.style.opacity=g;if(h>0){b[m.id]=d+h*1000;a.utils.fadeTo(m,f,e,j,0,b[m.id]);return}setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},10)}})(jwplayer);(function(a){a.utils.arrays=function(){};a.utils.arrays.indexOf=function(c,d){for(var b=0;b<c.length;b++){if(c[b]==d){return b}}return -1};a.utils.arrays.remove=function(c,d){var b=a.utils.arrays.indexOf(c,d);if(b>-1){c.splice(b,1)}}})(jwplayer);(function(a){a.utils.extensionmap={"3gp":{html5:"video/3gpp",flash:"video"},"3gpp":{html5:"video/3gpp"},"3g2":{html5:"video/3gpp2",flash:"video"},"3gpp2":{html5:"video/3gpp2"},flv:{flash:"video"},f4a:{html5:"audio/mp4"},f4b:{html5:"audio/mp4",flash:"video"},f4v:{html5:"video/mp4",flash:"video"},mov:{html5:"video/quicktime",flash:"video"},m4a:{html5:"audio/mp4",flash:"video"},m4b:{html5:"audio/mp4"},m4p:{html5:"audio/mp4"},m4v:{html5:"video/mp4",flash:"video"},mp4:{html5:"video/mp4",flash:"video"},rbs:{flash:"sound"},aac:{html5:"audio/aac",flash:"video"},mp3:{html5:"audio/mp3",flash:"sound"},ogg:{html5:"audio/ogg"},oga:{html5:"audio/ogg"},ogv:{html5:"video/ogg"},webm:{html5:"video/webm"},m3u8:{html5:"audio/x-mpegurl"},gif:{flash:"image"},jpeg:{flash:"image"},jpg:{flash:"image"},swf:{flash:"image"},png:{flash:"image"},wav:{html5:"audio/x-wav"}}})(jwplayer);(function(e){e.utils.mediaparser=function(){};var g={element:{width:"width",height:"height",id:"id","class":"className",name:"name"},media:{src:"file",preload:"preload",autoplay:"autostart",loop:"repeat",controls:"controls"},source:{src:"file",type:"type",media:"media","data-jw-width":"width","data-jw-bitrate":"bitrate"},video:{poster:"image"}};var f={};e.utils.mediaparser.parseMedia=function(j){return d(j)};function c(k,j){if(!e.utils.exists(j)){j=g[k]}else{e.utils.extend(j,g[k])}return j}function d(n,j){if(f[n.tagName.toLowerCase()]&&!e.utils.exists(j)){return f[n.tagName.toLowerCase()](n)}else{j=c("element",j);var o={};for(var k in j){if(k!="length"){var m=n.getAttribute(k);if(e.utils.exists(m)){o[j[k]]=m}}}var l=n.style["#background-color"];if(l&&!(l=="transparent"||l=="rgba(0, 0, 0, 0)")){o.screencolor=l}return o}}function h(n,k){k=c("media",k);var l=[];var j=e.utils.selectors("source",n);for(var m in j){if(!isNaN(m)){l.push(a(j[m]))}}var o=d(n,k);if(e.utils.exists(o.file)){l[0]={file:o.file}}o.levels=l;return o}function a(l,k){k=c("source",k);var j=d(l,k);j.width=j.width?j.width:0;j.bitrate=j.bitrate?j.bitrate:0;return j}function b(l,k){k=c("video",k);var j=h(l,k);return j}f.media=h;f.audio=h;f.source=a;f.video=b})(jwplayer);(function(a){a.utils.loaderstatus={NEW:"NEW",LOADING:"LOADING",ERROR:"ERROR",COMPLETE:"COMPLETE"};a.utils.scriptloader=function(c){var d=a.utils.loaderstatus.NEW;var b=new a.events.eventdispatcher();a.utils.extend(this,b);this.load=function(){if(d==a.utils.loaderstatus.NEW){d=a.utils.loaderstatus.LOADING;var e=document.createElement("script");e.onload=function(f){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)};e.onerror=function(f){d=a.utils.loaderstatus.ERROR;b.sendEvent(a.events.ERROR)};e.onreadystatechange=function(){if(e.readyState=="loaded"||e.readyState=="complete"){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)}};document.getElementsByTagName("head")[0].appendChild(e);e.src=c}};this.getStatus=function(){return d}}})(jwplayer);(function(a){a.utils.selectors=function(b,e){if(!a.utils.exists(e)){e=document}b=a.utils.strings.trim(b);var c=b.charAt(0);if(c=="#"){return e.getElementById(b.substr(1))}else{if(c=="."){if(e.getElementsByClassName){return e.getElementsByClassName(b.substr(1))}else{return a.utils.selectors.getElementsByTagAndClass("*",b.substr(1))}}else{if(b.indexOf(".")>0){var d=b.split(".");return a.utils.selectors.getElementsByTagAndClass(d[0],d[1])}else{return e.getElementsByTagName(b)}}}return null};a.utils.selectors.getElementsByTagAndClass=function(e,h,g){var j=[];if(!a.utils.exists(g)){g=document}var f=g.getElementsByTagName(e);for(var d=0;d<f.length;d++){if(a.utils.exists(f[d].className)){var c=f[d].className.split(" ");for(var b=0;b<c.length;b++){if(c[b]==h){j.push(f[d])}}}}return j}})(jwplayer);(function(a){a.utils.strings=function(){};a.utils.strings.trim=function(b){return b.replace(/^\s*/,"").replace(/\s*$/,"")};a.utils.strings.pad=function(c,d,b){if(!b){b="0"}while(c.length<d){c=b+c}return c};a.utils.strings.serialize=function(b){if(b==null){return null}else{if(b=="true"){return true}else{if(b=="false"){return false}else{if(isNaN(Number(b))||b.length>5||b.length==0){return b}else{return Number(b)}}}}};a.utils.strings.seconds=function(d){d=d.replace(",",".");var b=d.split(":");var c=0;if(d.substr(-1)=="s"){c=Number(d.substr(0,d.length-1))}else{if(d.substr(-1)=="m"){c=Number(d.substr(0,d.length-1))*60}else{if(d.substr(-1)=="h"){c=Number(d.substr(0,d.length-1))*3600}else{if(b.length>1){c=Number(b[b.length-1]);c+=Number(b[b.length-2])*60;if(b.length==3){c+=Number(b[b.length-3])*3600}}else{c=Number(d)}}}}return c};a.utils.strings.xmlAttribute=function(b,c){for(var d=0;d<b.attributes.length;d++){if(b.attributes[d].name&&b.attributes[d].name.toLowerCase()==c.toLowerCase()){return b.attributes[d].value.toString()}}return""};a.utils.strings.jsonToString=function(f){var h=h||{};if(h&&h.stringify){return h.stringify(f)}var c=typeof(f);if(c!="object"||f===null){if(c=="string"){f='"'+f.replace(/"/g,'\\"')+'"'}else{return String(f)}}else{var g=[],b=(f&&f.constructor==Array);for(var d in f){var e=f[d];switch(typeof(e)){case"string":e='"'+e.replace(/"/g,'\\"')+'"';break;case"object":if(a.utils.exists(e)){e=a.utils.strings.jsonToString(e)}break}if(b){if(typeof(e)!="function"){g.push(String(e))}}else{if(typeof(e)!="function"){g.push('"'+d+'":'+String(e))}}}if(b){return"["+String(g)+"]"}else{return"{"+String(g)+"}"}}}})(jwplayer);(function(c){var d=new RegExp(/^(#|0x)[0-9a-fA-F]{3,6}/);c.utils.typechecker=function(g,f){f=!c.utils.exists(f)?b(g):f;return e(g,f)};function b(f){var g=["true","false","t","f"];if(g.toString().indexOf(f.toLowerCase().replace(" ",""))>=0){return"boolean"}else{if(d.test(f)){return"color"}else{if(!isNaN(parseInt(f,10))&&parseInt(f,10).toString().length==f.length){return"integer"}else{if(!isNaN(parseFloat(f))&&parseFloat(f).toString().length==f.length){return"float"}}}}return"string"}function e(g,f){if(!c.utils.exists(f)){return g}switch(f){case"color":if(g.length>0){return a(g)}return null;case"integer":return parseInt(g,10);case"float":return parseFloat(g);case"boolean":if(g.toLowerCase()=="true"){return true}else{if(g=="1"){return true}}return false}return g}function a(f){switch(f.toLowerCase()){case"blue":return parseInt("0000FF",16);case"green":return parseInt("00FF00",16);case"red":return parseInt("FF0000",16);case"cyan":return parseInt("00FFFF",16);case"magenta":return parseInt("FF00FF",16);case"yellow":return parseInt("FFFF00",16);case"black":return parseInt("000000",16);case"white":return parseInt("FFFFFF",16);default:f=f.replace(/(#|0x)?([0-9A-F]{3,6})$/gi,"$2");if(f.length==3){f=f.charAt(0)+f.charAt(0)+f.charAt(1)+f.charAt(1)+f.charAt(2)+f.charAt(2)}return parseInt(f,16)}return parseInt("000000",16)}})(jwplayer);(function(a){a.utils.parsers=function(){};a.utils.parsers.localName=function(b){if(!b){return""}else{if(b.localName){return b.localName}else{if(b.baseName){return b.baseName}else{return""}}}};a.utils.parsers.textContent=function(b){if(!b){return""}else{if(b.textContent){return b.textContent}else{if(b.text){return b.text}else{return""}}}}})(jwplayer);(function(a){a.utils.parsers.jwparser=function(){};a.utils.parsers.jwparser.PREFIX="jwplayer";a.utils.parsers.jwparser.parseEntry=function(c,d){for(var b=0;b<c.childNodes.length;b++){if(c.childNodes[b].prefix==a.utils.parsers.jwparser.PREFIX){d[a.utils.parsers.localName(c.childNodes[b])]=a.utils.strings.serialize(a.utils.parsers.textContent(c.childNodes[b]));if(a.utils.parsers.localName(c.childNodes[b])=="file"&&d.levels){delete d.levels}}if(!d.file&&String(d.link).toLowerCase().indexOf("youtube")>-1){d.file=d.link}}return d};a.utils.parsers.jwparser.getProvider=function(c){if(c.type){return c.type}else{if(c.file.indexOf("youtube.com/w")>-1||c.file.indexOf("youtube.com/v")>-1||c.file.indexOf("youtu.be/")>-1){return"youtube"}else{if(c.streamer&&c.streamer.indexOf("rtmp")==0){return"rtmp"}else{if(c.streamer&&c.streamer.indexOf("http")==0){return"http"}else{var b=a.utils.strings.extension(c.file);if(extensions.hasOwnProperty(b)){return extensions[b]}}}}}return""}})(jwplayer);(function(a){a.utils.parsers.mediaparser=function(){};a.utils.parsers.mediaparser.PREFIX="media";a.utils.parsers.mediaparser.parseGroup=function(d,f){var e=false;for(var c=0;c<d.childNodes.length;c++){if(d.childNodes[c].prefix==a.utils.parsers.mediaparser.PREFIX){if(!a.utils.parsers.localName(d.childNodes[c])){continue}switch(a.utils.parsers.localName(d.childNodes[c]).toLowerCase()){case"content":if(!e){f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}if(a.utils.strings.xmlAttribute(d.childNodes[c],"duration")){f.duration=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"duration"))}if(a.utils.strings.xmlAttribute(d.childNodes[c],"start")){f.start=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"start"))}if(d.childNodes[c].childNodes&&d.childNodes[c].childNodes.length>0){f=a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f)}if(a.utils.strings.xmlAttribute(d.childNodes[c],"width")||a.utils.strings.xmlAttribute(d.childNodes[c],"bitrate")||a.utils.strings.xmlAttribute(d.childNodes[c],"url")){if(!f.levels){f.levels=[]}f.levels.push({width:a.utils.strings.xmlAttribute(d.childNodes[c],"width"),bitrate:a.utils.strings.xmlAttribute(d.childNodes[c],"bitrate"),file:a.utils.strings.xmlAttribute(d.childNodes[c],"url")})}break;case"title":f.title=a.utils.parsers.textContent(d.childNodes[c]);break;case"description":f.description=a.utils.parsers.textContent(d.childNodes[c]);break;case"keywords":f.tags=a.utils.parsers.textContent(d.childNodes[c]);break;case"thumbnail":f.image=a.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"credit":f.author=a.utils.parsers.textContent(d.childNodes[c]);break;case"player":var b=d.childNodes[c].url;if(b.indexOf("youtube.com")>=0||b.indexOf("youtu.be")>=0){e=true;f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}break;case"group":a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f);break}}}return f}})(jwplayer);(function(b){b.utils.parsers.rssparser=function(){};b.utils.parsers.rssparser.parse=function(f){var c=[];for(var e=0;e<f.childNodes.length;e++){if(b.utils.parsers.localName(f.childNodes[e]).toLowerCase()=="channel"){for(var d=0;d<f.childNodes[e].childNodes.length;d++){if(b.utils.parsers.localName(f.childNodes[e].childNodes[d]).toLowerCase()=="item"){c.push(a(f.childNodes[e].childNodes[d]))}}}}return c};function a(d){var e={};for(var c=0;c<d.childNodes.length;c++){if(!b.utils.parsers.localName(d.childNodes[c])){continue}switch(b.utils.parsers.localName(d.childNodes[c]).toLowerCase()){case"enclosure":e.file=b.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"title":e.title=b.utils.parsers.textContent(d.childNodes[c]);break;case"pubdate":e.date=b.utils.parsers.textContent(d.childNodes[c]);break;case"description":e.description=b.utils.parsers.textContent(d.childNodes[c]);break;case"link":e.link=b.utils.parsers.textContent(d.childNodes[c]);break;case"category":if(e.tags){e.tags+=b.utils.parsers.textContent(d.childNodes[c])}else{e.tags=b.utils.parsers.textContent(d.childNodes[c])}break}}e=b.utils.parsers.mediaparser.parseGroup(d,e);e=b.utils.parsers.jwparser.parseEntry(d,e);return new b.html5.playlistitem(e)}})(jwplayer);(function(a){var c={};var b={};a.plugins=function(){};a.plugins.loadPlugins=function(e,d){b[e]=new a.plugins.pluginloader(new a.plugins.model(c),d);return b[e]};a.plugins.registerPlugin=function(h,f,e){var d=a.utils.getPluginName(h);if(c[d]){c[d].registerPlugin(h,f,e)}else{a.utils.log("A plugin ("+h+") was registered with the player that was not loaded. Please check your configuration.");for(var g in b){b[g].pluginFailed()}}}})(jwplayer);(function(a){a.plugins.model=function(b){this.addPlugin=function(c){var d=a.utils.getPluginName(c);if(!b[d]){b[d]=new a.plugins.plugin(c)}return b[d]}}})(jwplayer);(function(a){a.plugins.pluginmodes={FLASH:"FLASH",JAVASCRIPT:"JAVASCRIPT",HYBRID:"HYBRID"};a.plugins.plugin=function(b){var d="http://plugins.longtailvideo.com";var j=a.utils.loaderstatus.NEW;var k;var h;var l;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function e(){switch(a.utils.getPluginPathType(b)){case a.utils.pluginPathType.ABSOLUTE:return b;case a.utils.pluginPathType.RELATIVE:return a.utils.getAbsolutePath(b,window.location.href);case a.utils.pluginPathType.CDN:var o=a.utils.getPluginName(b);var n=a.utils.getPluginVersion(b);var m=(window.location.href.indexOf("https://")==0)?d.replace("http://","https://secure"):d;return m+"/"+a.version.split(".")[0]+"/"+o+"/"+o+(n!==""?("-"+n):"")+".js"}}function g(m){l=setTimeout(function(){j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)},1000)}function f(m){j=a.utils.loaderstatus.ERROR;c.sendEvent(a.events.ERROR)}this.load=function(){if(j==a.utils.loaderstatus.NEW){if(b.lastIndexOf(".swf")>0){k=b;j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE);return}j=a.utils.loaderstatus.LOADING;var m=new a.utils.scriptloader(e());m.addEventListener(a.events.COMPLETE,g);m.addEventListener(a.events.ERROR,f);m.load()}};this.registerPlugin=function(o,n,m){if(l){clearTimeout(l);l=undefined}if(n&&m){k=m;h=n}else{if(typeof n=="string"){k=n}else{if(typeof n=="function"){h=n}else{if(!n&&!m){k=o}}}}j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)};this.getStatus=function(){return j};this.getPluginName=function(){return a.utils.getPluginName(b)};this.getFlashPath=function(){if(k){switch(a.utils.getPluginPathType(k)){case a.utils.pluginPathType.ABSOLUTE:return k;case a.utils.pluginPathType.RELATIVE:if(b.lastIndexOf(".swf")>0){return a.utils.getAbsolutePath(k,window.location.href)}return a.utils.getAbsolutePath(k,e());case a.utils.pluginPathType.CDN:if(k.indexOf("-")>-1){return k+"h"}return k+"-h"}}return null};this.getJS=function(){return h};this.getPluginmode=function(){if(typeof k!="undefined"&&typeof h!="undefined"){return a.plugins.pluginmodes.HYBRID}else{if(typeof k!="undefined"){return a.plugins.pluginmodes.FLASH}else{if(typeof h!="undefined"){return a.plugins.pluginmodes.JAVASCRIPT}}}};this.getNewInstance=function(n,m,o){return new h(n,m,o)};this.getURL=function(){return b}}})(jwplayer);(function(a){a.plugins.pluginloader=function(h,e){var g={};var k=a.utils.loaderstatus.NEW;var d=false;var b=false;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function f(){if(!b){b=true;k=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)}}function j(){if(!b){var m=0;for(plugin in g){var l=g[plugin].getStatus();if(l==a.utils.loaderstatus.LOADING||l==a.utils.loaderstatus.NEW){m++}}if(m==0){f()}}}this.setupPlugins=function(n,l,s){var m={length:0,plugins:{}};var p={length:0,plugins:{}};for(var o in g){var q=g[o].getPluginName();if(g[o].getFlashPath()){m.plugins[g[o].getFlashPath()]=l.plugins[o];m.plugins[g[o].getFlashPath()].pluginmode=g[o].getPluginmode();m.length++}if(g[o].getJS()){var r=document.createElement("div");r.id=n.id+"_"+q;r.style.position="absolute";r.style.zIndex=p.length+10;p.plugins[q]=g[o].getNewInstance(n,l.plugins[o],r);p.length++;if(typeof p.plugins[q].resize!="undefined"){n.onReady(s(p.plugins[q],r,true));n.onResize(s(p.plugins[q],r))}}}n.plugins=p.plugins;return m};this.load=function(){k=a.utils.loaderstatus.LOADING;d=true;for(var l in e){if(a.utils.exists(l)){g[l]=h.addPlugin(l);g[l].addEventListener(a.events.COMPLETE,j);g[l].addEventListener(a.events.ERROR,j)}}for(l in g){g[l].load()}d=false;j()};this.pluginFailed=function(){f()};this.getStatus=function(){return k}}})(jwplayer);(function(b){var a=[];b.api=function(d){this.container=d;this.id=d.id;var m={};var t={};var p={};var c=[];var g=undefined;var k=false;var h=[];var r=undefined;var o=b.utils.getOuterHTML(d);var s={};var j={};this.getBuffer=function(){return this.callInternal("jwGetBuffer")};this.getContainer=function(){return this.container};function e(v,u){return function(A,w,x,y){if(v.renderingMode=="flash"||v.renderingMode=="html5"){var z;if(w){j[A]=w;z="jwplayer('"+v.id+"').callback('"+A+"')"}else{if(!w&&j[A]){delete j[A]}}g.jwDockSetButton(A,z,x,y)}return u}}this.getPlugin=function(u){var w=this;var v={};if(u=="dock"){return b.utils.extend(v,{setButton:e(w,v),show:function(){w.callInternal("jwDockShow");return v},hide:function(){w.callInternal("jwDockHide");return v},onShow:function(x){w.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_SHOW,x);return v},onHide:function(x){w.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_HIDE,x);return v}})}else{if(u=="controlbar"){return b.utils.extend(v,{show:function(){w.callInternal("jwControlbarShow");return v},hide:function(){w.callInternal("jwControlbarHide");return v},onShow:function(x){w.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_SHOW,x);return v},onHide:function(x){w.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_HIDE,x);return v}})}else{if(u=="display"){return b.utils.extend(v,{show:function(){w.callInternal("jwDisplayShow");return v},hide:function(){w.callInternal("jwDisplayHide");return v},onShow:function(x){w.componentListener("display",b.api.events.JWPLAYER_COMPONENT_SHOW,x);return v},onHide:function(x){w.componentListener("display",b.api.events.JWPLAYER_COMPONENT_HIDE,x);return v}})}else{return this.plugins[u]}}}};this.callback=function(u){if(j[u]){return j[u]()}};this.getDuration=function(){return this.callInternal("jwGetDuration")};this.getFullscreen=function(){return this.callInternal("jwGetFullscreen")};this.getHeight=function(){return this.callInternal("jwGetHeight")};this.getLockState=function(){return this.callInternal("jwGetLockState")};this.getMeta=function(){return this.getItemMeta()};this.getMute=function(){return this.callInternal("jwGetMute")};this.getPlaylist=function(){var v=this.callInternal("jwGetPlaylist");if(this.renderingMode=="flash"){b.utils.deepReplaceKeyName(v,["__dot__","__spc__","__dsh__"],["."," ","-"])}for(var u=0;u<v.length;u++){if(!b.utils.exists(v[u].index)){v[u].index=u}}return v};this.getPlaylistItem=function(u){if(!b.utils.exists(u)){u=this.getCurrentItem()}return this.getPlaylist()[u]};this.getPosition=function(){return this.callInternal("jwGetPosition")};this.getRenderingMode=function(){return this.renderingMode};this.getState=function(){return this.callInternal("jwGetState")};this.getVolume=function(){return this.callInternal("jwGetVolume")};this.getWidth=function(){return this.callInternal("jwGetWidth")};this.setFullscreen=function(u){if(!b.utils.exists(u)){this.callInternal("jwSetFullscreen",!this.callInternal("jwGetFullscreen"))}else{this.callInternal("jwSetFullscreen",u)}return this};this.setMute=function(u){if(!b.utils.exists(u)){this.callInternal("jwSetMute",!this.callInternal("jwGetMute"))}else{this.callInternal("jwSetMute",u)}return this};this.lock=function(){return this};this.unlock=function(){return this};this.load=function(u){this.callInternal("jwLoad",u);return this};this.playlistItem=function(u){this.callInternal("jwPlaylistItem",u);return this};this.playlistPrev=function(){this.callInternal("jwPlaylistPrev");return this};this.playlistNext=function(){this.callInternal("jwPlaylistNext");return this};this.resize=function(v,u){if(this.renderingMode=="html5"){g.jwResize(v,u)}else{this.container.width=v;this.container.height=u;var w=document.getElementById(this.id+"_wrapper");if(w){w.style.width=v+"px";w.style.height=u+"px"}}return this};this.play=function(u){if(typeof u=="undefined"){u=this.getState();if(u==b.api.events.state.PLAYING||u==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPlay",u)}return this};this.pause=function(u){if(typeof u=="undefined"){u=this.getState();if(u==b.api.events.state.PLAYING||u==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPause",u)}return this};this.stop=function(){this.callInternal("jwStop");return this};this.seek=function(u){this.callInternal("jwSeek",u);return this};this.setVolume=function(u){this.callInternal("jwSetVolume",u);return this};this.loadInstream=function(v,u){r=new b.api.instream(this,g,v,u);return r};this.onBufferChange=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER,u)};this.onBufferFull=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,u)};this.onError=function(u){return this.eventListener(b.api.events.JWPLAYER_ERROR,u)};this.onFullscreen=function(u){return this.eventListener(b.api.events.JWPLAYER_FULLSCREEN,u)};this.onMeta=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_META,u)};this.onMute=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_MUTE,u)};this.onPlaylist=function(u){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_LOADED,u)};this.onPlaylistItem=function(u){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,u)};this.onReady=function(u){return this.eventListener(b.api.events.API_READY,u)};this.onResize=function(u){return this.eventListener(b.api.events.JWPLAYER_RESIZE,u)};this.onComplete=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,u)};this.onSeek=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_SEEK,u)};this.onTime=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_TIME,u)};this.onVolume=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_VOLUME,u)};this.onBeforePlay=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BEFOREPLAY,u)};this.onBeforeComplete=function(u){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BEFORECOMPLETE,u)};this.onBuffer=function(u){return this.stateListener(b.api.events.state.BUFFERING,u)};this.onPause=function(u){return this.stateListener(b.api.events.state.PAUSED,u)};this.onPlay=function(u){return this.stateListener(b.api.events.state.PLAYING,u)};this.onIdle=function(u){return this.stateListener(b.api.events.state.IDLE,u)};this.remove=function(){if(!k){throw"Cannot call remove() before player is ready";return}q(this)};function q(u){h=[];if(b.utils.getOuterHTML(u.container)!=o){b.api.destroyPlayer(u.id,o)}}this.setup=function(v){if(b.embed){var u=this.id;q(this);var w=b(u);w.config=v;return new b.embed(w)}return this};this.registerPlugin=function(w,v,u){b.plugins.registerPlugin(w,v,u)};this.setPlayer=function(u,v){g=u;this.renderingMode=v};this.stateListener=function(u,v){if(!t[u]){t[u]=[];this.eventListener(b.api.events.JWPLAYER_PLAYER_STATE,f(u))}t[u].push(v);return this};this.detachMedia=function(){if(this.renderingMode=="html5"){return this.callInternal("jwDetachMedia")}};this.attachMedia=function(){if(this.renderingMode=="html5"){return this.callInternal("jwAttachMedia")}};function f(u){return function(w){var v=w.newstate,y=w.oldstate;if(v==u){var x=t[v];if(x){for(var z=0;z<x.length;z++){if(typeof x[z]=="function"){x[z].call(this,{oldstate:y,newstate:v})}}}}}}this.componentListener=function(u,v,w){if(!p[u]){p[u]={}}if(!p[u][v]){p[u][v]=[];this.eventListener(v,l(u,v))}p[u][v].push(w);return this};function l(u,v){return function(x){if(u==x.component){var w=p[u][v];if(w){for(var y=0;y<w.length;y++){if(typeof w[y]=="function"){w[y].call(this,x)}}}}}}this.addInternalListener=function(u,v){try{u.jwAddEventListener(v,'function(dat) { jwplayer("'+this.id+'").dispatchEvent("'+v+'", dat); }')}catch(w){b.utils.log("Could not add internal listener")}};this.eventListener=function(u,v){if(!m[u]){m[u]=[];if(g&&k){this.addInternalListener(g,u)}}m[u].push(v);return this};this.dispatchEvent=function(w){if(m[w]){var v=_utils.translateEventResponse(w,arguments[1]);for(var u=0;u<m[w].length;u++){if(typeof m[w][u]=="function"){m[w][u].call(this,v)}}}};this.dispatchInstreamEvent=function(u){if(r){r.dispatchEvent(u,arguments)}};this.callInternal=function(){if(k){var w=arguments[0],u=[];for(var v=1;v<arguments.length;v++){u.push(arguments[v])}if(typeof g!="undefined"&&typeof g[w]=="function"){if(u.length==2){return(g[w])(u[0],u[1])}else{if(u.length==1){return(g[w])(u[0])}else{return(g[w])()}}}return null}else{h.push(arguments)}};this.playerReady=function(v){k=true;if(!g){this.setPlayer(document.getElementById(v.id))}this.container=document.getElementById(this.id);for(var u in m){this.addInternalListener(g,u)}this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,function(w){s={}});this.eventListener(b.api.events.JWPLAYER_MEDIA_META,function(w){b.utils.extend(s,w.metadata)});this.dispatchEvent(b.api.events.API_READY);while(h.length>0){this.callInternal.apply(this,h.shift())}};this.getItemMeta=function(){return s};this.getCurrentItem=function(){return this.callInternal("jwGetPlaylistIndex")};function n(w,y,x){var u=[];if(!y){y=0}if(!x){x=w.length-1}for(var v=y;v<=x;v++){u.push(w[v])}return u}return this};b.api.selectPlayer=function(d){var c;if(!b.utils.exists(d)){d=0}if(d.nodeType){c=d}else{if(typeof d=="string"){c=document.getElementById(d)}}if(c){var e=b.api.playerById(c.id);if(e){return e}else{return b.api.addPlayer(new b.api(c))}}else{if(typeof d=="number"){return b.getPlayers()[d]}}return null};b.api.events={API_READY:"jwplayerAPIReady",JWPLAYER_READY:"jwplayerReady",JWPLAYER_FULLSCREEN:"jwplayerFullscreen",JWPLAYER_RESIZE:"jwplayerResize",JWPLAYER_ERROR:"jwplayerError",JWPLAYER_MEDIA_BEFOREPLAY:"jwplayerMediaBeforePlay",JWPLAYER_MEDIA_BEFORECOMPLETE:"jwplayerMediaBeforeComplete",JWPLAYER_COMPONENT_SHOW:"jwplayerComponentShow",JWPLAYER_COMPONENT_HIDE:"jwplayerComponentHide",JWPLAYER_MEDIA_BUFFER:"jwplayerMediaBuffer",JWPLAYER_MEDIA_BUFFER_FULL:"jwplayerMediaBufferFull",JWPLAYER_MEDIA_ERROR:"jwplayerMediaError",JWPLAYER_MEDIA_LOADED:"jwplayerMediaLoaded",JWPLAYER_MEDIA_COMPLETE:"jwplayerMediaComplete",JWPLAYER_MEDIA_SEEK:"jwplayerMediaSeek",JWPLAYER_MEDIA_TIME:"jwplayerMediaTime",JWPLAYER_MEDIA_VOLUME:"jwplayerMediaVolume",JWPLAYER_MEDIA_META:"jwplayerMediaMeta",JWPLAYER_MEDIA_MUTE:"jwplayerMediaMute",JWPLAYER_PLAYER_STATE:"jwplayerPlayerState",JWPLAYER_PLAYLIST_LOADED:"jwplayerPlaylistLoaded",JWPLAYER_PLAYLIST_ITEM:"jwplayerPlaylistItem",JWPLAYER_INSTREAM_CLICK:"jwplayerInstreamClicked",JWPLAYER_INSTREAM_DESTROYED:"jwplayerInstreamDestroyed"};b.api.events.state={BUFFERING:"BUFFERING",IDLE:"IDLE",PAUSED:"PAUSED",PLAYING:"PLAYING"};b.api.playerById=function(d){for(var c=0;c<a.length;c++){if(a[c].id==d){return a[c]}}return null};b.api.addPlayer=function(c){for(var d=0;d<a.length;d++){if(a[d]==c){return c}}a.push(c);return c};b.api.destroyPlayer=function(g,d){var f=-1;for(var j=0;j<a.length;j++){if(a[j].id==g){f=j;continue}}if(f>=0){var c=document.getElementById(a[f].id);if(document.getElementById(a[f].id+"_wrapper")){c=document.getElementById(a[f].id+"_wrapper")}if(c){if(d){b.utils.setOuterHTML(c,d)}else{var h=document.createElement("div");var e=c.id;if(c.id.indexOf("_wrapper")==c.id.length-8){newID=c.id.substring(0,c.id.length-8)}h.setAttribute("id",e);c.parentNode.replaceChild(h,c)}}a.splice(f,1)}return null};b.getPlayers=function(){return a.slice(0)}})(jwplayer);var _userPlayerReady=(typeof playerReady=="function")?playerReady:undefined;playerReady=function(b){var a=jwplayer.api.playerById(b.id);if(a){a.playerReady(b)}else{jwplayer.api.selectPlayer(b.id).playerReady(b)}if(_userPlayerReady){_userPlayerReady.call(this,b)}};(function(a){a.api.instream=function(c,j,n,q){var h=c;var b=j;var g=n;var k=q;var e={};var p={};function f(){h.callInternal("jwLoadInstream",n,q)}function m(r,s){b.jwInstreamAddEventListener(s,'function(dat) { jwplayer("'+h.id+'").dispatchInstreamEvent("'+s+'", dat); }')}function d(r,s){if(!e[r]){e[r]=[];m(b,r)}e[r].push(s);return this}function o(r,s){if(!p[r]){p[r]=[];d(a.api.events.JWPLAYER_PLAYER_STATE,l(r))}p[r].push(s);return this}function l(r){return function(t){var s=t.newstate,v=t.oldstate;if(s==r){var u=p[s];if(u){for(var w=0;w<u.length;w++){if(typeof u[w]=="function"){u[w].call(this,{oldstate:v,newstate:s,type:t.type})}}}}}}this.dispatchEvent=function(u,t){if(e[u]){var s=_utils.translateEventResponse(u,t[1]);for(var r=0;r<e[u].length;r++){if(typeof e[u][r]=="function"){e[u][r].call(this,s)}}}};this.onError=function(r){return d(a.api.events.JWPLAYER_ERROR,r)};this.onFullscreen=function(r){return d(a.api.events.JWPLAYER_FULLSCREEN,r)};this.onMeta=function(r){return d(a.api.events.JWPLAYER_MEDIA_META,r)};this.onMute=function(r){return d(a.api.events.JWPLAYER_MEDIA_MUTE,r)};this.onComplete=function(r){return d(a.api.events.JWPLAYER_MEDIA_COMPLETE,r)};this.onSeek=function(r){return d(a.api.events.JWPLAYER_MEDIA_SEEK,r)};this.onTime=function(r){return d(a.api.events.JWPLAYER_MEDIA_TIME,r)};this.onVolume=function(r){return d(a.api.events.JWPLAYER_MEDIA_VOLUME,r)};this.onBuffer=function(r){return o(a.api.events.state.BUFFERING,r)};this.onPause=function(r){return o(a.api.events.state.PAUSED,r)};this.onPlay=function(r){return o(a.api.events.state.PLAYING,r)};this.onIdle=function(r){return o(a.api.events.state.IDLE,r)};this.onInstreamClick=function(r){return d(a.api.events.JWPLAYER_INSTREAM_CLICK,r)};this.onInstreamDestroyed=function(r){return d(a.api.events.JWPLAYER_INSTREAM_DESTROYED,r)};this.play=function(r){b.jwInstreamPlay(r)};this.pause=function(r){b.jwInstreamPause(r)};this.seek=function(r){b.jwInstreamSeek(r)};this.destroy=function(){b.jwInstreamDestroy()};this.getState=function(){return b.jwInstreamGetState()};this.getDuration=function(){return b.jwInstreamGetDuration()};this.getPosition=function(){return b.jwInstreamGetPosition()};f()}})(jwplayer);(function(a){var c=a.utils;a.embed=function(h){var k={width:400,height:300,components:{controlbar:{position:"over"}}};var g=c.mediaparser.parseMedia(h.container);var f=new a.embed.config(c.extend(k,g,h.config),this);var j=a.plugins.loadPlugins(h.id,f.plugins);function d(n,m){for(var l in m){if(typeof n[l]=="function"){(n[l]).call(n,m[l])}}}function e(){if(j.getStatus()==c.loaderstatus.COMPLETE){for(var n=0;n<f.modes.length;n++){if(f.modes[n].type&&a.embed[f.modes[n].type]){var p=f.modes[n].config;var t=f;if(p){t=c.extend(c.clone(f),p);var s=["file","levels","playlist"];for(var m=0;m<s.length;m++){var q=s[m];if(c.exists(p[q])){for(var l=0;l<s.length;l++){if(l!=m){var o=s[l];if(c.exists(t[o])&&!c.exists(p[o])){delete t[o]}}}}}}var r=new a.embed[f.modes[n].type](document.getElementById(h.id),f.modes[n],t,j,h);if(r.supportsConfig()){r.embed();d(h,f.events);return h}}}c.log("No suitable players found");new a.embed.logo(c.extend({hide:true},f.components.logo),"none",h.id)}}j.addEventListener(a.events.COMPLETE,e);j.addEventListener(a.events.ERROR,e);j.load();return h};function b(){if(!document.body){return setTimeout(b,15)}var d=c.selectors.getElementsByTagAndClass("video","jwplayer");for(var e=0;e<d.length;e++){var f=d[e];if(f.id==""){f.id="jwplayer_"+Math.round(Math.random()*100000)}a(f.id).setup({})}}b()})(jwplayer);(function(e){var k=e.utils;function h(m){var l=[{type:"flash",src:m?m:"/jwplayer/player.swf"},{type:"html5"},{type:"download"}];if(k.isAndroid()){l[0]=l.splice(1,1,l[0])[0]}return l}var a={players:"modes",autoplay:"autostart"};function b(o){var n=o.toLowerCase();var m=["left","right","top","bottom"];for(var l=0;l<m.length;l++){if(n==m[l]){return true}}return false}function c(m){var l=false;l=(m instanceof Array)||(typeof m=="object"&&!m.position&&!m.size);return l}function j(l){if(typeof l=="string"){if(parseInt(l).toString()==l||l.toLowerCase().indexOf("px")>-1){return parseInt(l)}}return l}var g=["playlist","dock","controlbar","logo","display"];function f(l){var o={};switch(k.typeOf(l.plugins)){case"object":for(var n in l.plugins){o[k.getPluginName(n)]=n}break;case"string":var p=l.plugins.split(",");for(var m=0;m<p.length;m++){o[k.getPluginName(p[m])]=p[m]}break}return o}function d(p,o,n,l){if(k.typeOf(p[o])!="object"){p[o]={}}var m=p[o][n];if(k.typeOf(m)!="object"){p[o][n]=m={}}if(l){if(o=="plugins"){var q=k.getPluginName(n);m[l]=p[q+"."+l];delete p[q+"."+l]}else{m[l]=p[n+"."+l];delete p[n+"."+l]}}}e.embed.deserialize=function(m){var n=f(m);for(var l in n){d(m,"plugins",n[l])}for(var q in m){if(q.indexOf(".")>-1){var p=q.split(".");var o=p[0];var q=p[1];if(k.isInArray(g,o)){d(m,"components",o,q)}else{if(n[o]){d(m,"plugins",n[o],q)}}}}return m};e.embed.config=function(l,v){var u=k.extend({},l);var s;if(c(u.playlist)){s=u.playlist;delete u.playlist}u=e.embed.deserialize(u);u.height=j(u.height);u.width=j(u.width);if(typeof u.plugins=="string"){var m=u.plugins.split(",");if(typeof u.plugins!="object"){u.plugins={}}for(var q=0;q<m.length;q++){var r=k.getPluginName(m[q]);if(typeof u[r]=="object"){u.plugins[m[q]]=u[r];delete u[r]}else{u.plugins[m[q]]={}}}}for(var t=0;t<g.length;t++){var p=g[t];if(k.exists(u[p])){if(typeof u[p]!="object"){if(!u.components[p]){u.components[p]={}}if(p=="logo"){u.components[p].file=u[p]}else{u.components[p].position=u[p]}delete u[p]}else{if(!u.components[p]){u.components[p]={}}k.extend(u.components[p],u[p]);delete u[p]}}if(typeof u[p+"size"]!="undefined"){if(!u.components[p]){u.components[p]={}}u.components[p].size=u[p+"size"];delete u[p+"size"]}}if(typeof u.icons!="undefined"){if(!u.components.display){u.components.display={}}u.components.display.icons=u.icons;delete u.icons}for(var o in a){if(u[o]){if(!u[a[o]]){u[a[o]]=u[o]}delete u[o]}}var n;if(u.flashplayer&&!u.modes){n=h(u.flashplayer);delete u.flashplayer}else{if(u.modes){if(typeof u.modes=="string"){n=h(u.modes)}else{if(u.modes instanceof Array){n=u.modes}else{if(typeof u.modes=="object"&&u.modes.type){n=[u.modes]}}}delete u.modes}else{n=h()}}u.modes=n;if(s){u.playlist=s}return u}})(jwplayer);(function(a){a.embed.download=function(c,g,b,d,f){this.embed=function(){var k=a.utils.extend({},b);var q={};var j=b.width?b.width:480;if(typeof j!="number"){j=parseInt(j,10)}var m=b.height?b.height:320;if(typeof m!="number"){m=parseInt(m,10)}var u,o,n;var s={};if(b.playlist&&b.playlist.length){s.file=b.playlist[0].file;o=b.playlist[0].image;s.levels=b.playlist[0].levels}else{s.file=b.file;o=b.image;s.levels=b.levels}if(s.file){u=s.file}else{if(s.levels&&s.levels.length){u=s.levels[0].file}}n=u?"pointer":"auto";var l={display:{style:{cursor:n,width:j,height:m,backgroundColor:"#000",position:"relative",textDecoration:"none",border:"none",display:"block"}},display_icon:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:0,left:0,border:0,margin:0,padding:0,zIndex:3,width:50,height:50,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNrs18ENgjAYhmFouDOCcQJGcARHgE10BDcgTOIosAGwQOuPwaQeuFRi2p/3Sb6EC5L3QCxZBgAAAOCorLW1zMn65TrlkH4NcV7QNcUQt7Gn7KIhxA+qNIR81spOGkL8oFJDyLJRdosqKDDkK+iX5+d7huzwM40xptMQMkjIOeRGo+VkEVvIPfTGIpKASfYIfT9iCHkHrBEzf4gcUQ56aEzuGK/mw0rHpy4AAACAf3kJMACBxjAQNRckhwAAAABJRU5ErkJggg==)"}},display_iconBackground:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:((m-50)/2),left:((j-50)/2),border:0,width:50,height:50,margin:0,padding:0,zIndex:2,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNrszwENADAIA7DhX8ENoBMZ5KR10EryckCJiIiIiIiIiIiIiIiIiIiIiIh8GmkRERERERERERERERERERERERGRHSPAAPlXH1phYpYaAAAAAElFTkSuQmCC)"}},display_image:{style:{width:j,height:m,display:o?"block":"none",position:"absolute",cursor:n,left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1,border:"none"}}};var h=function(v,x,y){var w=document.createElement(v);if(y){w.id=y}else{w.id=c.id+"_jwplayer_"+x}a.utils.css(w,l[x].style);return w};q.display=h("a","display",c.id);if(u){q.display.setAttribute("href",a.utils.getAbsolutePath(u))}q.display_image=h("img","display_image");q.display_image.setAttribute("alt","Click to download...");if(o){q.display_image.setAttribute("src",a.utils.getAbsolutePath(o))}if(true){q.display_icon=h("div","display_icon");q.display_iconBackground=h("div","display_iconBackground");q.display.appendChild(q.display_image);q.display_iconBackground.appendChild(q.display_icon);q.display.appendChild(q.display_iconBackground)}_css=a.utils.css;_hide=function(v){_css(v,{display:"none"})};function r(v){_imageWidth=q.display_image.naturalWidth;_imageHeight=q.display_image.naturalHeight;t()}function t(){a.utils.stretch(a.utils.stretching.UNIFORM,q.display_image,j,m,_imageWidth,_imageHeight)}q.display_image.onerror=function(v){_hide(q.display_image)};q.display_image.onload=r;c.parentNode.replaceChild(q.display,c);var p=(b.plugins&&b.plugins.logo)?b.plugins.logo:{};q.display.appendChild(new a.embed.logo(b.components.logo,"download",c.id));f.container=document.getElementById(f.id);f.setPlayer(q.display,"download")};this.supportsConfig=function(){if(b){var j=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof j.file=="undefined"&&typeof j.levels=="undefined"){return true}else{if(j.file){return e(j.file,j.provider,j.playlistfile)}else{if(j.levels&&j.levels.length){for(var h=0;h<j.levels.length;h++){if(j.levels[h].file&&e(j.levels[h].file,j.provider,j.playlistfile)){return true}}}}}}else{return true}};function e(j,l,h){if(h){return false}var k=["image","sound","youtube","http"];if(l&&(k.toString().indexOf(l)>-1)){return true}if(!l||(l&&l=="video")){var m=a.utils.extension(j);if(m&&a.utils.extensionmap[m]){return true}}return false}}})(jwplayer);(function(a){a.embed.flash=function(f,g,l,e,j){function m(o,n,p){var q=document.createElement("param");q.setAttribute("name",n);q.setAttribute("value",p);o.appendChild(q)}function k(o,p,n){return function(q){if(n){document.getElementById(j.id+"_wrapper").appendChild(p)}var s=document.getElementById(j.id).getPluginConfig("display");o.resize(s.width,s.height);var r={left:s.x,top:s.y};a.utils.css(p,r)}}function d(p){if(!p){return{}}var r={};for(var o in p){var n=p[o];for(var q in n){r[o+"."+q]=n[q]}}return r}function h(q,p){if(q[p]){var s=q[p];for(var o in s){var n=s[o];if(typeof n=="string"){if(!q[o]){q[o]=n}}else{for(var r in n){if(!q[o+"."+r]){q[o+"."+r]=n[r]}}}}delete q[p]}}function b(q){if(!q){return{}}var t={},s=[];for(var n in q){var p=a.utils.getPluginName(n);var o=q[n];s.push(n);for(var r in o){t[p+"."+r]=o[r]}}t.plugins=s.join(",");return t}function c(p){var n=p.netstreambasepath?"":"netstreambasepath="+encodeURIComponent(window.location.href.split("#")[0])+"&";for(var o in p){if(typeof(p[o])=="object"){n+=o+"="+encodeURIComponent("[[JSON]]"+a.utils.strings.jsonToString(p[o]))+"&"}else{n+=o+"="+encodeURIComponent(p[o])+"&"}}return n.substring(0,n.length-1)}this.embed=function(){l.id=j.id;var A;var r=a.utils.extend({},l);var o=r.width;var y=r.height;if(f.id+"_wrapper"==f.parentNode.id){A=document.getElementById(f.id+"_wrapper")}else{A=document.createElement("div");A.id=f.id+"_wrapper";a.utils.wrap(f,A);a.utils.css(A,{position:"relative",width:o,height:y})}var p=e.setupPlugins(j,r,k);if(p.length>0){a.utils.extend(r,b(p.plugins))}else{delete r.plugins}var s=["height","width","modes","events"];for(var v=0;v<s.length;v++){delete r[s[v]]}var q="opaque";if(r.wmode){q=r.wmode}h(r,"components");h(r,"providers");if(typeof r["dock.position"]!="undefined"){if(r["dock.position"].toString().toLowerCase()=="false"){r.dock=r["dock.position"];delete r["dock.position"]}}var x=a.utils.getCookies();for(var n in x){if(typeof(r[n])=="undefined"){r[n]=x[n]}}var z="#000000";var u;if(a.utils.isIE()){var w='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" bgcolor="'+z+'" width="100%" height="100%" id="'+f.id+'" name="'+f.id+'" tabindex=0"">';w+='<param name="movie" value="'+g.src+'">';w+='<param name="allowfullscreen" value="true">';w+='<param name="allowscriptaccess" value="always">';w+='<param name="seamlesstabbing" value="true">';w+='<param name="wmode" value="'+q+'">';w+='<param name="flashvars" value="'+c(r)+'">';w+="</object>";a.utils.setOuterHTML(f,w);u=document.getElementById(f.id)}else{var t=document.createElement("object");t.setAttribute("type","application/x-shockwave-flash");t.setAttribute("data",g.src);t.setAttribute("width","100%");t.setAttribute("height","100%");t.setAttribute("bgcolor","#000000");t.setAttribute("id",f.id);t.setAttribute("name",f.id);t.setAttribute("tabindex",0);m(t,"allowfullscreen","true");m(t,"allowscriptaccess","always");m(t,"seamlesstabbing","true");m(t,"wmode",q);m(t,"flashvars",c(r));f.parentNode.replaceChild(t,f);u=t}j.container=u;j.setPlayer(u,"flash")};this.supportsConfig=function(){if(a.utils.hasFlash()){if(l){var o=a.utils.getFirstPlaylistItemFromConfig(l);if(typeof o.file=="undefined"&&typeof o.levels=="undefined"){return true}else{if(o.file){return flashCanPlay(o.file,o.provider)}else{if(o.levels&&o.levels.length){for(var n=0;n<o.levels.length;n++){if(o.levels[n].file&&flashCanPlay(o.levels[n].file,o.provider)){return true}}}}}}else{return true}}return false};flashCanPlay=function(n,p){var o=["video","http","sound","image"];if(p&&(o.toString().indexOf(p)<0)){return true}var q=a.utils.extension(n);if(!q){return true}if(a.utils.exists(a.utils.extensionmap[q])&&!a.utils.exists(a.utils.extensionmap[q].flash)){return false}return true}}})(jwplayer);(function(a){a.embed.html5=function(c,g,b,d,f){function e(j,k,h){return function(l){var m=document.getElementById(c.id+"_displayarea");if(h){m.appendChild(k)}j.resize(m.clientWidth,m.clientHeight);k.left=m.style.left;k.top=m.style.top}}this.embed=function(){if(a.html5){d.setupPlugins(f,b,e);c.innerHTML="";var j=a.utils.extend({screencolor:"0x000000"},b);var h=["plugins","modes","events"];for(var k=0;k<h.length;k++){delete j[h[k]]}if(j.levels&&!j.sources){j.sources=b.levels}if(j.skin&&j.skin.toLowerCase().indexOf(".zip")>0){j.skin=j.skin.replace(/\.zip/i,".xml")}var l=new (a.html5(c)).setup(j);f.container=document.getElementById(f.id);f.setPlayer(l,"html5")}else{return null}};this.supportsConfig=function(){if(!!a.vid.canPlayType){if(b){var j=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof j.file=="undefined"&&typeof j.levels=="undefined"){return true}else{if(j.file){return html5CanPlay(a.vid,j.file,j.provider,j.playlistfile)}else{if(j.levels&&j.levels.length){for(var h=0;h<j.levels.length;h++){if(j.levels[h].file&&html5CanPlay(a.vid,j.levels[h].file,j.provider,j.playlistfile)){return true}}}}}}else{return true}}return false};html5CanPlay=function(k,j,l,h){if(h){return false}if(l&&l=="youtube"){return true}if(l&&l!="video"&&l!="http"&&l!="sound"){return false}if(navigator.userAgent.match(/BlackBerry/i)!==null){return false}var m=a.utils.extension(j);if(!a.utils.exists(m)||!a.utils.exists(a.utils.extensionmap[m])){return true}if(!a.utils.exists(a.utils.extensionmap[m].html5)){return false}if(a.utils.isLegacyAndroid()&&m.match(/m4v|mp4/)){return true}return browserCanPlay(k,a.utils.extensionmap[m].html5)};browserCanPlay=function(j,h){if(!h){return true}if(j.canPlayType(h)){return true}else{if(h=="audio/mp3"&&navigator.userAgent.match(/safari/i)){return j.canPlayType("audio/mpeg")}else{return false}}}}})(jwplayer);(function(a){a.embed.logo=function(m,l,d){var j={prefix:"http://l.longtailvideo.com/"+l+"/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",linktarget:"_top",margin:8,out:0.5,over:1,timeout:5,hide:false,position:"bottom-left"};_css=a.utils.css;var b;var h;k();function k(){o();c();f()}function o(){if(j.prefix){var q=a.version.split(/\W/).splice(0,2).join("/");if(j.prefix.indexOf(q)<0){j.prefix+=q+"/"}}h=a.utils.extend({},j)}function p(){var s={border:"none",textDecoration:"none",position:"absolute",cursor:"pointer",zIndex:10};s.display=h.hide?"none":"block";var r=h.position.toLowerCase().split("-");for(var q in r){s[r[q]]=h.margin}return s}function c(){b=document.createElement("img");b.id=d+"_jwplayer_logo";b.style.display="none";b.onload=function(q){_css(b,p());e()};if(!h.file){return}if(h.file.indexOf("http://")===0){b.src=h.file}else{b.src=h.prefix+h.file}}if(!h.file){return}function f(){if(h.link){b.onmouseover=g;b.onmouseout=e;b.onclick=n}else{this.mouseEnabled=false}}function n(q){if(typeof q!="undefined"){q.preventDefault();q.stopPropagation()}if(h.link){window.open(h.link,h.linktarget)}return}function e(q){if(h.link){b.style.opacity=h.out}return}function g(q){if(h.hide){b.style.opacity=h.over}return}return b}})(jwplayer);(function(a){a.html5=function(b){var c=b;this.setup=function(d){a.utils.extend(this,new a.html5.api(c,d));return this};return this}})(jwplayer);(function(a){var c=a.utils;var b=c.css;a.html5.view=function(l,D,g){var k=l;var v=D;var h=g;var M;var f;var q;var m;var B;var L;var K;var A=false;var u=false;var x,J;var e,N,r;function H(){M=document.createElement("div");M.id=v.id;M.className=v.className;_videowrapper=document.createElement("div");_videowrapper.id=M.id+"_video_wrapper";v.id=M.id+"_video";b(M,{position:"relative",height:h.height,width:h.width,padding:0,backgroundColor:P(),zIndex:0});function P(){if(k.skin.getComponentSettings("display")&&k.skin.getComponentSettings("display").backgroundcolor){return k.skin.getComponentSettings("display").backgroundcolor}return parseInt("000000",16)}b(v,{width:"100%",height:"100%",top:0,left:0,zIndex:1,margin:"auto",display:"block"});b(_videowrapper,{overflow:"hidden",position:"absolute",top:0,left:0,bottom:0,right:0});c.wrap(v,M);c.wrap(v,_videowrapper);m=document.createElement("div");m.id=M.id+"_displayarea";M.appendChild(m);_instreamArea=document.createElement("div");_instreamArea.id=M.id+"_instreamarea";b(_instreamArea,{overflow:"hidden",position:"absolute",top:0,left:0,bottom:0,right:0,zIndex:100,background:"000000",display:"none"});M.appendChild(_instreamArea)}function G(){for(var P=0;P<h.plugins.order.length;P++){var Q=h.plugins.order[P];if(c.exists(h.plugins.object[Q].getDisplayElement)){h.plugins.object[Q].height=c.parseDimension(h.plugins.object[Q].getDisplayElement().style.height);h.plugins.object[Q].width=c.parseDimension(h.plugins.object[Q].getDisplayElement().style.width);h.plugins.config[Q].currentPosition=h.plugins.config[Q].position}}s()}function p(P){u=h.fullscreen}function n(P){if(N){return}if(h.getMedia()&&h.getMedia().hasChrome()){m.style.display="none"}else{switch(P.newstate){case P.newstate==a.api.events.state.PLAYING:m.style.display="none";break;default:m.style.display="block";break}}j()}function s(Q){var S=h.getMedia()?h.getMedia().getDisplayElement():null;if(c.exists(S)){if(K!=S){if(K&&K.parentNode){K.parentNode.replaceChild(S,K)}K=S}for(var P=0;P<h.plugins.order.length;P++){var R=h.plugins.order[P];if(c.exists(h.plugins.object[R].getDisplayElement)){h.plugins.config[R].currentPosition=h.plugins.config[R].position}}}C(h.width,h.height)}this.setup=function(){if(h&&h.getMedia()){v=h.getMedia().getDisplayElement()}H();G();k.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,n);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_LOADED,s);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_BEFOREPLAY,p);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_META,function(Q){j()});var P;if(c.exists(window.onresize)){P=window.onresize}window.onresize=function(Q){if(c.exists(P)){try{P(Q)}catch(S){}}if(k.jwGetFullscreen()){if(!y()){var R=c.getBoundingClientRect(document.body);h.width=Math.abs(R.left)+Math.abs(R.right);h.height=window.innerHeight;C(h.width,h.height)}}else{C(h.width,h.height)}}};function I(P){switch(P.keyCode){case 27:if(k.jwGetFullscreen()){k.jwSetFullscreen(false)}break;case 32:if(k.jwGetState()!=a.api.events.state.IDLE&&k.jwGetState()!=a.api.events.state.PAUSED){k.jwPause()}else{k.jwPlay()}break}}function C(P,Y){if(M.style.display=="none"){return}var S=[].concat(h.plugins.order);S.reverse();B=S.length+2;if(u&&y()){try{if(h.fullscreen&&!h.getMedia().getDisplayElement().webkitDisplayingFullscreen){h.fullscreen=false}}catch(V){}}if(!h.fullscreen){f=P;q=Y;if(typeof P=="string"&&P.indexOf("%")>0){f=c.getElementWidth(c.parentNode(M))*parseInt(P.replace("%"),"")/100}else{f=P}if(typeof Y=="string"&&Y.indexOf("%")>0){q=c.getElementHeight(c.parentNode(M))*parseInt(Y.replace("%"),"")/100}else{q=Y}var T={top:0,bottom:0,left:0,right:0,width:f,height:q,position:"absolute"};b(m,T);var Z={};var W;try{W=h.plugins.object.display.getDisplayElement()}catch(V){}if(W){Z.width=c.parseDimension(W.style.width);Z.height=c.parseDimension(W.style.height)}var X=c.extend({},T,Z,{zIndex:_instreamArea.style.zIndex,display:_instreamArea.style.display});b(_instreamArea,X);b(M,{height:q,width:f});var U=t(E,S);if(U.length>0){B+=U.length;var R=U.indexOf("playlist"),Q=U.indexOf("controlbar");if(R>=0&&Q>=0){U[R]=U.splice(Q,1,U[R])[0]}t(o,U,true)}x=c.getElementWidth(m);J=c.getElementHeight(m)}else{if(!y()){t(d,S,true)}}j()}function t(W,S,T){var U=[];for(var R=0;R<S.length;R++){var V=S[R];if(c.exists(h.plugins.object[V].getDisplayElement)){if(h.plugins.config[V].currentPosition!=a.html5.view.positions.NONE){var P=W(V,B--);if(!P){U.push(V)}else{var Q=P.width;var X=P.height;if(T){delete P.width;delete P.height}b(h.plugins.object[V].getDisplayElement(),P);h.plugins.object[V].resize(Q,X)}}else{b(h.plugins.object[V].getDisplayElement(),{display:"none"})}}}return U}function E(Q,R){if(c.exists(h.plugins.object[Q].getDisplayElement)){if(h.plugins.config[Q].position&&O(h.plugins.config[Q].position)){if(!c.exists(h.plugins.object[Q].getDisplayElement().parentNode)){M.appendChild(h.plugins.object[Q].getDisplayElement())}var P=w(Q);P.zIndex=R;return P}}return false}function o(P,Q){if(!c.exists(h.plugins.object[P].getDisplayElement().parentNode)){m.appendChild(h.plugins.object[P].getDisplayElement())}return{position:"absolute",width:(c.getElementWidth(m)-c.parseDimension(m.style.right)),height:(c.getElementHeight(m)-c.parseDimension(m.style.bottom)),zIndex:Q}}function d(P,Q){return{position:"fixed",width:h.width,height:h.height,zIndex:Q}}var j=this.resizeMedia=function(){m.style.position="absolute";var R=h.getMedia()?h.getMedia().getDisplayElement():r;if(!R){return}if(R&&R.tagName.toLowerCase()=="video"){if(!R.videoWidth||!R.videoHeight){R.style.width=m.style.width;R.style.height=m.style.height;return}R.style.position="absolute";c.fadeTo(R,1,0.25);if(R.parentNode){R.parentNode.style.left=m.style.left;R.parentNode.style.top=m.style.top}if(h.fullscreen&&k.jwGetStretching()==a.utils.stretching.EXACTFIT&&!c.isMobile()){var P=document.createElement("div");c.stretch(a.utils.stretching.UNIFORM,P,c.getElementWidth(m),c.getElementHeight(m),x,J);c.stretch(a.utils.stretching.EXACTFIT,R,c.parseDimension(P.style.width),c.parseDimension(P.style.height),R.videoWidth?R.videoWidth:400,R.videoHeight?R.videoHeight:300);b(R,{left:P.style.left,top:P.style.top})}else{c.stretch(k.jwGetStretching(),R,c.getElementWidth(m),c.getElementHeight(m),R.videoWidth?R.videoWidth:400,R.videoHeight?R.videoHeight:300)}}else{var Q=h.plugins.object.display.getDisplayElement();if(Q){h.getMedia().resize(c.parseDimension(Q.style.width),c.parseDimension(Q.style.height))}else{h.getMedia().resize(c.parseDimension(m.style.width),c.parseDimension(m.style.height))}}};var w=this.getComponentPosition=function(Q){var R={position:"absolute",margin:0,padding:0,top:null};var P=h.plugins.config[Q].currentPosition.toLowerCase();switch(P.toUpperCase()){case a.html5.view.positions.TOP:R.top=c.parseDimension(m.style.top);R.left=c.parseDimension(m.style.left);R.width=c.getElementWidth(m)-c.parseDimension(m.style.left)-c.parseDimension(m.style.right);R.height=h.plugins.object[Q].height;m.style[P]=c.parseDimension(m.style[P])+h.plugins.object[Q].height+"px";m.style.height=c.getElementHeight(m)-R.height+"px";break;case a.html5.view.positions.RIGHT:R.top=c.parseDimension(m.style.top);R.right=c.parseDimension(m.style.right);R.width=h.plugins.object[Q].width;R.height=c.getElementHeight(m)-c.parseDimension(m.style.top)-c.parseDimension(m.style.bottom);m.style.width=c.getElementWidth(m)-R.width+"px";break;case a.html5.view.positions.BOTTOM:R.bottom=c.parseDimension(m.style.bottom);R.left=c.parseDimension(m.style.left);R.width=c.getElementWidth(m)-c.parseDimension(m.style.left)-c.parseDimension(m.style.right);R.height=h.plugins.object[Q].height;m.style.height=c.getElementHeight(m)-R.height+"px";break;case a.html5.view.positions.LEFT:R.top=c.parseDimension(m.style.top);R.left=c.parseDimension(m.style.left);R.width=h.plugins.object[Q].width;R.height=c.getElementHeight(m)-c.parseDimension(m.style.top)-c.parseDimension(m.style.bottom);m.style[P]=c.parseDimension(m.style[P])+h.plugins.object[Q].width+"px";m.style.width=c.getElementWidth(m)-R.width+"px";break;default:break}return R};this.resize=C;var F;this.fullscreen=function(S){var U;try{U=h.getMedia().getDisplayElement()}catch(T){}if(y()&&U&&U.webkitSupportsFullscreen){if(S&&!U.webkitDisplayingFullscreen){try{c.transform(U);F=m.style.display;m.style.display="none";U.webkitEnterFullscreen()}catch(R){}}else{if(!S){j();if(U.webkitDisplayingFullscreen){try{U.webkitExitFullscreen()}catch(R){}}m.style.display=F}}A=false}else{if(S){document.onkeydown=I;clearInterval(L);var Q=c.getBoundingClientRect(document.body);h.width=Math.abs(Q.left)+Math.abs(Q.right);h.height=window.innerHeight;var P={position:"fixed",width:"100%",height:"100%",top:0,left:0,zIndex:2147483000};b(M,P);P.zIndex=1;if(h.getMedia()&&h.getMedia().getDisplayElement()){b(h.getMedia().getDisplayElement(),P)}P.zIndex=2;b(m,P);A=true}else{document.onkeydown="";h.width=f;h.height=q;b(M,{position:"relative",height:h.height,width:h.width,zIndex:0});A=false}C(h.width,h.height)}};function O(P){return([a.html5.view.positions.TOP,a.html5.view.positions.RIGHT,a.html5.view.positions.BOTTOM,a.html5.view.positions.LEFT].toString().indexOf(P.toUpperCase())>-1)}function y(){if(k.jwGetState()!=a.api.events.state.IDLE&&!A&&(h.getMedia()&&h.getMedia().getDisplayElement()&&h.getMedia().getDisplayElement().webkitSupportsFullscreen)&&c.useNativeFullscreen()){return true}return false}this.setupInstream=function(P,Q){c.css(_instreamArea,{display:"block",position:"absolute"});m.style.display="none";_instreamArea.appendChild(P);r=Q;N=true};var z=this.destroyInstream=function(){_instreamArea.style.display="none";_instreamArea.innerHTML="";m.style.display="block";r=null;N=false;C(h.width,h.height)}};a.html5.view.positions={TOP:"TOP",RIGHT:"RIGHT",BOTTOM:"BOTTOM",LEFT:"LEFT",OVER:"OVER",NONE:"NONE"}})(jwplayer);(function(a){var b={backgroundcolor:"",margin:10,font:"Arial,sans-serif",fontsize:10,fontcolor:parseInt("000000",16),fontstyle:"normal",fontweight:"bold",buttoncolor:parseInt("ffffff",16),position:a.html5.view.positions.BOTTOM,idlehide:false,hideplaylistcontrols:false,forcenextprev:false,layout:{left:{position:"left",elements:[{name:"play",type:"button"},{name:"divider",type:"divider"},{name:"prev",type:"button"},{name:"divider",type:"divider"},{name:"next",type:"button"},{name:"divider",type:"divider"},{name:"elapsed",type:"text"}]},center:{position:"center",elements:[{name:"time",type:"slider"}]},right:{position:"right",elements:[{name:"duration",type:"text"},{name:"blank",type:"button"},{name:"divider",type:"divider"},{name:"mute",type:"button"},{name:"volume",type:"slider"},{name:"divider",type:"divider"},{name:"fullscreen",type:"button"}]}}};_utils=a.utils;_css=_utils.css;_hide=function(c){_css(c,{display:"none"})};_show=function(c){_css(c,{display:"block"})};a.html5.controlbar=function(m,X){window.controlbar=this;var l=m;var D=_utils.extend({},b,l.skin.getComponentSettings("controlbar"),X);if(D.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[D.position]=="undefined"){return}if(_utils.mapLength(l.skin.getComponentLayout("controlbar"))>0){D.layout=l.skin.getComponentLayout("controlbar")}var af;var Q;var ae;var E;var w="none";var h;var k;var ag;var g;var f;var z;var R={};var q=false;var c={};var ab;var j=false;var p;var d;var U=false;var G=false;var H;var Z=new a.html5.eventdispatcher();_utils.extend(this,Z);function K(){if(!ab){ab=l.skin.getSkinElement("controlbar","background");if(!ab){ab={width:0,height:0,src:null}}}return ab}function O(){ae=0;E=0;Q=0;if(!q){var ao={height:K().height,backgroundColor:D.backgroundcolor};af=document.createElement("div");af.id=l.id+"_jwplayer_controlbar";_css(af,ao)}var an=(l.skin.getSkinElement("controlbar","capLeft"));var am=(l.skin.getSkinElement("controlbar","capRight"));if(an){y("capLeft","left",false,af)}ac("background",af,{position:"absolute",height:K().height,left:(an?an.width:0),zIndex:0},"img");if(K().src){R.background.src=K().src}ac("elements",af,{position:"relative",height:K().height,zIndex:1});if(am){y("capRight","right",false,af)}}this.getDisplayElement=function(){return af};this.resize=function(ao,am){S();_utils.cancelAnimation(af);f=ao;z=am;if(G!=l.jwGetFullscreen()){G=l.jwGetFullscreen();if(!G){Y()}d=undefined}var an=x();J({id:l.id,duration:ag,position:k});v({id:l.id,bufferPercent:g});return an};this.show=function(){if(j){j=false;_show(af);V()}};this.hide=function(){if(!j){j=true;_hide(af);ad()}};function r(){var an=["timeSlider","volumeSlider","timeSliderRail","volumeSliderRail"];for(var ao in an){var am=an[ao];if(typeof R[am]!="undefined"){c[am]=_utils.getBoundingClientRect(R[am])}}}var e;function Y(am){if(j){return}clearTimeout(p);if(D.position==a.html5.view.positions.OVER||l.jwGetFullscreen()){switch(l.jwGetState()){case a.api.events.state.PAUSED:case a.api.events.state.IDLE:if(af&&af.style.opacity<1&&(!D.idlehide||_utils.exists(am))){e=false;setTimeout(function(){if(!e){W()}},100)}if(D.idlehide){p=setTimeout(function(){A()},2000)}break;default:e=true;if(am){W()}p=setTimeout(function(){A()},2000);break}}else{W()}}function A(){if(!j){ad();if(af.style.opacity==1){_utils.cancelAnimation(af);_utils.fadeTo(af,0,0.1,1,0)}}}function W(){if(!j){V();if(af.style.opacity==0){_utils.cancelAnimation(af);_utils.fadeTo(af,1,0.1,0,0)}}}function I(am){return function(){if(U&&d!=am){d=am;Z.sendEvent(am,{component:"controlbar",boundingRect:P()})}}}var V=I(a.api.events.JWPLAYER_COMPONENT_SHOW);var ad=I(a.api.events.JWPLAYER_COMPONENT_HIDE);function P(){if(D.position==a.html5.view.positions.OVER||l.jwGetFullscreen()){return _utils.getDimensions(af)}else{return{x:0,y:0,width:0,height:0}}}function ac(aq,ap,ao,am){var an;if(!q){if(!am){am="div"}an=document.createElement(am);R[aq]=an;an.id=af.id+"_"+aq;ap.appendChild(an)}else{an=document.getElementById(af.id+"_"+aq)}if(_utils.exists(ao)){_css(an,ao)}return an}function N(){if(l.jwGetHeight()<=40){D.layout=_utils.clone(D.layout);for(var am=0;am<D.layout.left.elements.length;am++){if(D.layout.left.elements[am].name=="fullscreen"){D.layout.left.elements.splice(am,1)}}for(am=0;am<D.layout.right.elements.length;am++){if(D.layout.right.elements[am].name=="fullscreen"){D.layout.right.elements.splice(am,1)}}o()}al(D.layout.left);al(D.layout.center);al(D.layout.right)}function al(ap,am){var aq=ap.position=="right"?"right":"left";var ao=_utils.extend([],ap.elements);if(_utils.exists(am)){ao.reverse()}var ap=ac(ap.position+"Group",R.elements,{"float":"left",styleFloat:"left",cssFloat:"left",height:"100%"});for(var an=0;an<ao.length;an++){C(ao[an],aq,ap)}}function L(){return Q++}function C(aq,at,av){var ap,an,ao,am,aw;if(!av){av=R.elements}if(aq.type=="divider"){y("divider"+L(),at,true,av,undefined,aq.width,aq.element);return}switch(aq.name){case"play":y("playButton",at,false,av);y("pauseButton",at,true,av);T("playButton","jwPlay");T("pauseButton","jwPause");break;case"prev":y("prevButton",at,true,av);T("prevButton","jwPlaylistPrev");break;case"stop":y("stopButton",at,true,av);T("stopButton","jwStop");break;case"next":y("nextButton",at,true,av);T("nextButton","jwPlaylistNext");break;case"elapsed":y("elapsedText",at,true,av,null,null,l.skin.getSkinElement("controlbar","elapsedBackground"));break;case"time":an=!_utils.exists(l.skin.getSkinElement("controlbar","timeSliderCapLeft"))?0:l.skin.getSkinElement("controlbar","timeSliderCapLeft").width;ao=!_utils.exists(l.skin.getSkinElement("controlbar","timeSliderCapRight"))?0:l.skin.getSkinElement("controlbar","timeSliderCapRight").width;ap=at=="left"?an:ao;aw={height:K().height,position:"relative","float":"left",styleFloat:"left",cssFloat:"left"};var ar=ac("timeSlider",av,aw);y("timeSliderCapLeft",at,true,ar,"relative");y("timeSliderRail",at,false,ar,"relative");y("timeSliderBuffer",at,false,ar,"absolute");y("timeSliderProgress",at,false,ar,"absolute");y("timeSliderThumb",at,false,ar,"absolute");y("timeSliderCapRight",at,true,ar,"relative");aa("time");break;case"fullscreen":y("fullscreenButton",at,false,av);y("normalscreenButton",at,true,av);T("fullscreenButton","jwSetFullscreen",true);T("normalscreenButton","jwSetFullscreen",false);break;case"volume":an=!_utils.exists(l.skin.getSkinElement("controlbar","volumeSliderCapLeft"))?0:l.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;ao=!_utils.exists(l.skin.getSkinElement("controlbar","volumeSliderCapRight"))?0:l.skin.getSkinElement("controlbar","volumeSliderCapRight").width;ap=at=="left"?an:ao;am=l.skin.getSkinElement("controlbar","volumeSliderRail").width+an+ao;aw={height:K().height,position:"relative",width:am,"float":"left",styleFloat:"left",cssFloat:"left"};var au=ac("volumeSlider",av,aw);y("volumeSliderCapLeft",at,false,au,"relative");y("volumeSliderRail",at,false,au,"relative");y("volumeSliderProgress",at,false,au,"absolute");y("volumeSliderThumb",at,false,au,"absolute");y("volumeSliderCapRight",at,false,au,"relative");aa("volume");break;case"mute":y("muteButton",at,false,av);y("unmuteButton",at,true,av);T("muteButton","jwSetMute",true);T("unmuteButton","jwSetMute",false);break;case"duration":y("durationText",at,true,av,null,null,l.skin.getSkinElement("controlbar","durationBackground"));break}}function y(ap,at,an,aw,aq,am,ao){if(_utils.exists(l.skin.getSkinElement("controlbar",ap))||ap.indexOf("Text")>0||ap.indexOf("divider")===0){var ar={height:"100%",position:aq?aq:"relative",display:"block","float":"left",styleFloat:"left",cssFloat:"left"};if((ap.indexOf("next")===0||ap.indexOf("prev")===0)&&(l.jwGetPlaylist().length<2||D.hideplaylistcontrols.toString()=="true")){if(D.forcenextprev.toString()!="true"){an=false;ar.display="none"}}var ax;if(ap.indexOf("Text")>0){ap.innerhtml="00:00";ar.font=D.fontsize+"px/"+(K().height+1)+"px "+D.font;ar.color=D.fontcolor;ar.textAlign="center";ar.fontWeight=D.fontweight;ar.fontStyle=D.fontstyle;ar.cursor="default";if(ao){ar.background="url("+ao.src+") no-repeat center";ar.backgroundSize="100% "+K().height+"px"}ar.padding="0 5px"}else{if(ap.indexOf("divider")===0){if(am){if(!isNaN(parseInt(am))){ax=parseInt(am)}}else{if(ao){var au=l.skin.getSkinElement("controlbar",ao);if(au){ar.background="url("+au.src+") repeat-x center left";ax=au.width}}else{ar.background="url("+l.skin.getSkinElement("controlbar","divider").src+") repeat-x center left";ax=l.skin.getSkinElement("controlbar","divider").width}}}else{ar.background="url("+l.skin.getSkinElement("controlbar",ap).src+") repeat-x center left";ax=l.skin.getSkinElement("controlbar",ap).width}}if(at=="left"){if(an){ae+=ax}}else{if(at=="right"){if(an){E+=ax}}}if(_utils.typeOf(aw)=="undefined"){aw=R.elements}ar.width=ax;if(q){_css(R[ap],ar)}else{var av=ac(ap,aw,ar);if(_utils.exists(l.skin.getSkinElement("controlbar",ap+"Over"))){av.onmouseover=function(ay){av.style.backgroundImage=["url(",l.skin.getSkinElement("controlbar",ap+"Over").src,")"].join("")};av.onmouseout=function(ay){av.style.backgroundImage=["url(",l.skin.getSkinElement("controlbar",ap).src,")"].join("")}}if(ap.indexOf("divider")==0){av.setAttribute("class","divider")}av.innerHTML=" "}}}function F(){l.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,B);l.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,t);l.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_BUFFER,v);l.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,s);l.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_TIME,J);l.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,ak);l.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_VOLUME,n);l.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_COMPLETE,M)}function B(){if(!D.hideplaylistcontrols){if(l.jwGetPlaylist().length>1||D.forcenextprev.toString()=="true"){_show(R.nextButton);_show(R.prevButton)}else{_hide(R.nextButton);_hide(R.prevButton)}x();ah()}}function t(am){ag=l.jwGetPlaylist()[am.index].duration;J({id:l.id,duration:ag,position:0});v({id:l.id,bufferProgress:0})}function ah(){J({id:l.id,duration:l.jwGetDuration(),position:0});v({id:l.id,bufferProgress:0});ak({id:l.id,mute:l.jwGetMute()});s({id:l.id,newstate:a.api.events.state.IDLE});n({id:l.id,volume:l.jwGetVolume()})}function T(ao,ap,an){if(q){return}if(_utils.exists(l.skin.getSkinElement("controlbar",ao))){var am=R[ao];if(_utils.exists(am)){_css(am,{cursor:"pointer"});if(ap=="fullscreen"){am.onmouseup=function(aq){aq.stopPropagation();l.jwSetFullscreen(!l.jwGetFullscreen())}}else{am.onmouseup=function(aq){aq.stopPropagation();if(_utils.exists(an)){l[ap](an)}else{l[ap]()}}}}}}function aa(am){if(q){return}var an=R[am+"Slider"];_css(R.elements,{cursor:"pointer"});_css(an,{cursor:"pointer"});an.onmousedown=function(ao){w=am};an.onmouseup=function(ao){ao.stopPropagation();aj(ao.pageX)};an.onmousemove=function(ao){if(w=="time"){h=true;var ap=ao.pageX-c[am+"Slider"].left-window.pageXOffset;_css(R[w+"SliderThumb"],{left:ap})}}}function aj(an){h=false;var am;if(w=="time"){am=an-c.timeSliderRail.left+window.pageXOffset;var ap=am/c.timeSliderRail.width*ag;if(ap<0){ap=0}else{if(ap>ag){ap=ag-3}}if(l.jwGetState()==a.api.events.state.PAUSED||l.jwGetState()==a.api.events.state.IDLE){l.jwPlay()}l.jwSeek(ap)}else{if(w=="volume"){am=an-c.volumeSliderRail.left-window.pageXOffset;var ao=Math.round(am/c.volumeSliderRail.width*100);if(ao<10){ao=0}else{if(ao>100){ao=100}}if(l.jwGetMute()){l.jwSetMute(false)}l.jwSetVolume(ao)}}w="none"}function v(an){if(_utils.exists(an.bufferPercent)){g=an.bufferPercent}if(c.timeSliderRail){var ap=l.skin.getSkinElement("controlbar","timeSliderCapLeft");var ao=c.timeSliderRail.width;var am=isNaN(Math.round(ao*g/100))?0:Math.round(ao*g/100);_css(R.timeSliderBuffer,{width:am,left:ap?ap.width:0})}}function ak(am){if(am.mute){_hide(R.muteButton);_show(R.unmuteButton);_hide(R.volumeSliderProgress)}else{_show(R.muteButton);_hide(R.unmuteButton);_show(R.volumeSliderProgress)}}function s(am){if(am.newstate==a.api.events.state.BUFFERING||am.newstate==a.api.events.state.PLAYING){_show(R.pauseButton);_hide(R.playButton)}else{_hide(R.pauseButton);_show(R.playButton)}Y();if(am.newstate==a.api.events.state.IDLE){_hide(R.timeSliderBuffer);_hide(R.timeSliderProgress);_hide(R.timeSliderThumb);J({id:l.id,duration:l.jwGetDuration(),position:0})}else{_show(R.timeSliderBuffer);if(am.newstate!=a.api.events.state.BUFFERING){_show(R.timeSliderProgress);_show(R.timeSliderThumb)}}}function M(am){v({bufferPercent:0});J(_utils.extend(am,{position:0,duration:ag}))}function J(aq){if(_utils.exists(aq.position)){k=aq.position}var am=false;if(_utils.exists(aq.duration)&&aq.duration!=ag){ag=aq.duration;am=true}var ao=(k===ag===0)?0:k/ag;var at=c.timeSliderRail;if(at){var an=isNaN(Math.round(at.width*ao))?0:Math.round(at.width*ao);var ar=l.skin.getSkinElement("controlbar","timeSliderCapLeft");var ap=an+(ar?ar.width:0);if(R.timeSliderProgress){_css(R.timeSliderProgress,{width:an,left:ar?ar.width:0});if(!h){if(R.timeSliderThumb){R.timeSliderThumb.style.left=ap+"px"}}}}if(R.durationText){R.durationText.innerHTML=_utils.timeFormat(ag)}if(R.elapsedText){R.elapsedText.innerHTML=_utils.timeFormat(k)}if(am){x()}}function o(){var am=R.elements.childNodes;var ar,ap;for(var ao=0;ao<am.length;ao++){var aq=am[ao].childNodes;for(var an in aq){if(isNaN(parseInt(an,10))){continue}if(aq[an].id.indexOf(af.id+"_divider")===0&&ap&&ap.id.indexOf(af.id+"_divider")===0&&aq[an].style.backgroundImage==ap.style.backgroundImage){aq[an].style.display="none"}else{if(aq[an].id.indexOf(af.id+"_divider")===0&&ar&&ar.style.display!="none"){aq[an].style.display="block"}}if(aq[an].style.display!="none"){ap=aq[an]}ar=aq[an]}}}function ai(){if(l.jwGetFullscreen()){_show(R.normalscreenButton);_hide(R.fullscreenButton)}else{_hide(R.normalscreenButton);_show(R.fullscreenButton)}if(l.jwGetState()==a.api.events.state.BUFFERING||l.jwGetState()==a.api.events.state.PLAYING){_show(R.pauseButton);_hide(R.playButton)}else{_hide(R.pauseButton);_show(R.playButton)}if(l.jwGetMute()==true){_hide(R.muteButton);_show(R.unmuteButton);_hide(R.volumeSliderProgress)}else{_show(R.muteButton);_hide(R.unmuteButton);_show(R.volumeSliderProgress)}}function x(){o();ai();var ao={width:f};var aw={"float":"left",styleFloat:"left",cssFloat:"left"};if(D.position==a.html5.view.positions.OVER||l.jwGetFullscreen()){ao.left=D.margin;ao.width-=2*D.margin;ao.top=z-K().height-D.margin;ao.height=K().height}var aq=l.skin.getSkinElement("controlbar","capLeft");var au=l.skin.getSkinElement("controlbar","capRight");aw.width=ao.width-(aq?aq.width:0)-(au?au.width:0);var ap=_utils.getBoundingClientRect(R.leftGroup).width;var at=_utils.getBoundingClientRect(R.rightGroup).width;var ar=aw.width-ap-at-1;var an=ar;var am=l.skin.getSkinElement("controlbar","timeSliderCapLeft");var av=l.skin.getSkinElement("controlbar","timeSliderCapRight");if(_utils.exists(am)){an-=am.width}if(_utils.exists(av)){an-=av.width}R.timeSlider.style.width=ar+"px";R.timeSliderRail.style.width=an+"px";_css(af,ao);_css(R.elements,aw);_css(R.background,aw);r();return ao}function n(ar){if(_utils.exists(R.volumeSliderRail)){var ao=isNaN(ar.volume/100)?1:ar.volume/100;var ap=_utils.parseDimension(R.volumeSliderRail.style.width);var am=isNaN(Math.round(ap*ao))?0:Math.round(ap*ao);var at=_utils.parseDimension(R.volumeSliderRail.style.right);var an=(!_utils.exists(l.skin.getSkinElement("controlbar","volumeSliderCapLeft")))?0:l.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;_css(R.volumeSliderProgress,{width:am,left:an});if(R.volumeSliderThumb){var aq=(am-Math.round(_utils.parseDimension(R.volumeSliderThumb.style.width)/2));aq=Math.min(Math.max(aq,0),ap-_utils.parseDimension(R.volumeSliderThumb.style.width));_css(R.volumeSliderThumb,{left:aq})}if(_utils.exists(R.volumeSliderCapLeft)){_css(R.volumeSliderCapLeft,{left:0})}}}function S(){try{var an=(l.id.indexOf("_instream")>0?l.id.replace("_instream",""):l.id);H=document.getElementById(an);H.addEventListener("mousemove",Y)}catch(am){_utils.log("Could not add mouse listeners to controlbar: "+am)}}function u(){O();N();r();q=true;F();D.idlehide=(D.idlehide.toString().toLowerCase()=="true");if(D.position==a.html5.view.positions.OVER&&D.idlehide){af.style.opacity=0;U=true}else{af.style.opacity=1;setTimeout((function(){U=true;V()}),1)}S();ah()}u();return this}})(jwplayer);(function(b){var a=["width","height","state","playlist","item","position","buffer","duration","volume","mute","fullscreen"];var c=b.utils;b.html5.controller=function(o,K,f,h){var n=o,m=f,j=h,y=K,M=true,G=-1,A=false,d=false,P,C=[],q=false;var D=(c.exists(m.config.debug)&&(m.config.debug.toString().toLowerCase()=="console")),N=new b.html5.eventdispatcher(y.id,D);c.extend(this,N);function L(T){if(q){N.sendEvent(T.type,T)}else{C.push(T)}}function s(T){if(!q){q=true;N.sendEvent(b.api.events.JWPLAYER_READY,T);if(b.utils.exists(window.playerReady)){playerReady(T)}if(b.utils.exists(window[f.config.playerReady])){window[f.config.playerReady](T)}while(C.length>0){var V=C.shift();N.sendEvent(V.type,V)}if(f.config.autostart&&!b.utils.isIOS()){O()}while(x.length>0){var U=x.shift();B(U.method,U.arguments)}}}m.addGlobalListener(L);m.addEventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,function(){m.getMedia().play()});m.addEventListener(b.api.events.JWPLAYER_MEDIA_TIME,function(T){if(T.position>=m.playlist[m.item].start&&G>=0){m.playlist[m.item].start=G;G=-1}});m.addEventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,function(T){setTimeout(E,25)});m.addEventListener(b.api.events.JWPLAYER_PLAYLIST_LOADED,O);m.addEventListener(b.api.events.JWPLAYER_FULLSCREEN,p);function F(){try{P=F;if(!A){A=true;N.sendEvent(b.api.events.JWPLAYER_MEDIA_BEFOREPLAY);A=false;if(d){d=false;P=null;return}}v(m.item);if(m.playlist[m.item].levels[0].file.length>0){if(M||m.state==b.api.events.state.IDLE){m.getMedia().load(m.playlist[m.item]);M=false}else{if(m.state==b.api.events.state.PAUSED){m.getMedia().play()}}}return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T);P=null}return false}function e(){try{if(m.playlist[m.item].levels[0].file.length>0){switch(m.state){case b.api.events.state.PLAYING:case b.api.events.state.BUFFERING:if(m.getMedia()){m.getMedia().pause()}break;default:if(A){d=true}}}return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T)}return false}function z(T){try{if(m.playlist[m.item].levels[0].file.length>0){if(typeof T!="number"){T=parseFloat(T)}switch(m.state){case b.api.events.state.IDLE:if(G<0){G=m.playlist[m.item].start;m.playlist[m.item].start=T}if(!A){F()}break;case b.api.events.state.PLAYING:case b.api.events.state.PAUSED:case b.api.events.state.BUFFERING:m.seek(T);break}}return true}catch(U){N.sendEvent(b.api.events.JWPLAYER_ERROR,U)}return false}function w(T){P=null;if(!c.exists(T)){T=true}try{if((m.state!=b.api.events.state.IDLE||T)&&m.getMedia()){m.getMedia().stop(T)}if(A){d=true}return true}catch(U){N.sendEvent(b.api.events.JWPLAYER_ERROR,U)}return false}function k(){try{if(m.playlist[m.item].levels[0].file.length>0){if(m.config.shuffle){v(S())}else{if(m.item+1==m.playlist.length){v(0)}else{v(m.item+1)}}}if(m.state!=b.api.events.state.IDLE){var U=m.state;m.state=b.api.events.state.IDLE;N.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:U,newstate:b.api.events.state.IDLE})}F();return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T)}return false}function I(){try{if(m.playlist[m.item].levels[0].file.length>0){if(m.config.shuffle){v(S())}else{if(m.item===0){v(m.playlist.length-1)}else{v(m.item-1)}}}if(m.state!=b.api.events.state.IDLE){var U=m.state;m.state=b.api.events.state.IDLE;N.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:U,newstate:b.api.events.state.IDLE})}F();return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T)}return false}function S(){var T=null;if(m.playlist.length>1){while(!c.exists(T)){T=Math.floor(Math.random()*m.playlist.length);if(T==m.item){T=null}}}else{T=0}return T}function H(U){if(!m.playlist||!m.playlist[U]){return false}try{if(m.playlist[U].levels[0].file.length>0){var V=m.state;if(V!==b.api.events.state.IDLE){if(m.playlist[m.item]&&m.playlist[m.item].provider==m.playlist[U].provider){w(false)}else{w()}}v(U);F()}return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T)}return false}function v(T){if(!m.playlist[T]){return}m.setActiveMediaProvider(m.playlist[T]);if(m.item!=T){m.item=T;M=true;N.sendEvent(b.api.events.JWPLAYER_PLAYLIST_ITEM,{index:T})}}function g(U){try{v(m.item);var V=m.getMedia();switch(typeof(U)){case"number":V.volume(U);break;case"string":V.volume(parseInt(U,10));break}m.setVolume(U);return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T)}return false}function r(U){try{v(m.item);var V=m.getMedia();if(typeof U=="undefined"){V.mute(!m.mute);m.setMute(!m.mute)}else{if(U.toString().toLowerCase()=="true"){V.mute(true);m.setMute(true)}else{V.mute(false);m.setMute(false)}}return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T)}return false}function J(U,T){try{m.width=U;m.height=T;j.resize(U,T);N.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:m.width,height:m.height});return true}catch(V){N.sendEvent(b.api.events.JWPLAYER_ERROR,V)}return false}function u(U,V){try{if(typeof U=="undefined"){U=!m.fullscreen}if(typeof V=="undefined"){V=true}if(U!=m.fullscreen){m.fullscreen=(U.toString().toLowerCase()=="true");j.fullscreen(m.fullscreen);if(V){N.sendEvent(b.api.events.JWPLAYER_FULLSCREEN,{fullscreen:m.fullscreen})}N.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:m.width,height:m.height})}return true}catch(T){N.sendEvent(b.api.events.JWPLAYER_ERROR,T)}return false}function R(T){try{w();if(A){d=false}m.loadPlaylist(T);if(m.playlist[m.item].provider){v(m.item);if(m.config.autostart.toString().toLowerCase()=="true"&&!c.isIOS()&&!A){F()}return true}else{return false}}catch(U){N.sendEvent(b.api.events.JWPLAYER_ERROR,U)}return false}function O(T){if(!c.isIOS()){v(m.item);if(m.config.autostart.toString().toLowerCase()=="true"&&!c.isIOS()){F()}}}function p(T){u(T.fullscreen,false)}function t(){try{return m.getMedia().detachMedia()}catch(T){return null}}function l(){try{var T=m.getMedia().attachMedia();if(typeof P=="function"){P()}}catch(U){return null}}b.html5.controller.repeatoptions={LIST:"LIST",ALWAYS:"ALWAYS",SINGLE:"SINGLE",NONE:"NONE"};function E(){if(m.state!=b.api.events.state.IDLE){return}P=E;switch(m.config.repeat.toUpperCase()){case b.html5.controller.repeatoptions.SINGLE:F();break;case b.html5.controller.repeatoptions.ALWAYS:if(m.item==m.playlist.length-1&&!m.config.shuffle){H(0)}else{k()}break;case b.html5.controller.repeatoptions.LIST:if(m.item==m.playlist.length-1&&!m.config.shuffle){w();v(0)}else{k()}break;default:w();break}}var x=[];function Q(T){return function(){if(q){B(T,arguments)}else{x.push({method:T,arguments:arguments})}}}function B(V,U){var T=[];for(i=0;i<U.length;i++){T.push(U[i])}V.apply(this,T)}this.play=Q(F);this.pause=Q(e);this.seek=Q(z);this.stop=Q(w);this.next=Q(k);this.prev=Q(I);this.item=Q(H);this.setVolume=Q(g);this.setMute=Q(r);this.resize=Q(J);this.setFullscreen=Q(u);this.load=Q(R);this.playerReady=s;this.detachMedia=t;this.attachMedia=l;this.beforePlay=function(){return A}}})(jwplayer);(function(a){a.html5.defaultSkin=function(){this.text='<?xml version="1.0" ?><skin author="LongTail Video" name="Five" version="1.1"><components><component name="controlbar"><settings><setting name="margin" value="20"/><setting name="fontsize" value="11"/><setting name="fontcolor" value="0x000000"/></settings><layout><group position="left"><button name="play"/><divider name="divider"/><button name="prev"/><divider name="divider"/><button name="next"/><divider name="divider"/><text name="elapsed"/></group><group position="center"><slider name="time"/></group><group position="right"><text name="duration"/><divider name="divider"/><button name="blank"/><divider name="divider"/><button name="mute"/><slider name="volume"/><divider name="divider"/><button name="fullscreen"/></group></layout><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAElJREFUOI3t1LERACAMQlFgGvcfxNIhHMK4gsUvUviOmgtNsiAZkBSEKxKEnCYkkQrJn/YwbUNiSDDYRZaQRDaShv+oX9GBZEIuK+8hXVLs+/YAAAAASUVORK5CYII="/><element name="blankButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAYCAYAAAAyJzegAAAAFElEQVQYV2P8//8/AzpgHBUc7oIAGZdH0RjKN8EAAAAASUVORK5CYII="/><element name="capLeft" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAYAAAA7zJfaAAAAQElEQVQIWz3LsRGAMADDQJ0XB5bMINABZ9GENGrszxhjT2WLSqxEJG2JQrTMdV2q5LpOAvyRaVmsi7WdeZ/7+AAaOTq7BVrfOQAAAABJRU5ErkJggg=="/><element name="capRight" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAYAAAA7zJfaAAAAQElEQVQIWz3LsRGAMADDQJ0XB5bMINABZ9GENGrszxhjT2WLSqxEJG2JQrTMdV2q5LpOAvyRaVmsi7WdeZ/7+AAaOTq7BVrfOQAAAABJRU5ErkJggg=="/><element name="divider" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADhJREFUCB0FwcENgEAAw7Aq+893g8APUILNOQcbFRktVGqUVFRkWNz3xTa2sUaLNUosKlRUvvf5AdbWOTtzmzyWAAAAAElFTkSuQmCC"/><element name="playButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAANUlEQVR42u2RsQkAAAjD/NTTPaW6dXLrINJA1kBpGPMAjDWmOgp1HFQXx+b1KOefO4oxY57R73YnVYCQUCQAAAAASUVORK5CYII="/><element name="pauseButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAIUlEQVQ4jWNgGAWjYOiD/0gYG3/U0FFDB4Oho2AUDAYAAEwiL9HrpdMVAAAAAElFTkSuQmCC"/><element name="prevButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAQklEQVQ4y2NgGAWjYOiD/1AMA/JAfB5NjCJD/YH4PRaLyDa0H4lNNUP/DxlD59PCUBCIp3ZEwYA+NZLUKBgFgwEAAN+HLX9sB8u8AAAAAElFTkSuQmCC"/><element name="nextButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAQElEQVQ4y2NgGAWjYOiD/0B8Hojl0cT+U2ooCL8HYn9qGwrD/bQw9P+QMXQ+tSMqnpoRBUpS+tRMUqNgFAwGAADxZy1/mHvFnAAAAABJRU5ErkJggg=="/><element name="timeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAOElEQVRIDe3BwQkAIRADwAhhw/nU/kWwUK+KPITMABFh19Y+F0acY8CJvX9wYpXgRElwolSIiMf9ZWEDhtwurFsAAAAASUVORK5CYII="/><element name="timeSliderBuffer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAN0lEQVRIDe3BwQkAMQwDMBcc55mRe9zi7RR+FCwBEWG39vcfGHFm4MTuhhMlwYlVBSdKhYh43AW/LQMKm1spzwAAAABJRU5ErkJggg=="/><element name="timeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAIElEQVRIiWNgGAWjYBTQBfynMR61YCRYMApGwSigMQAAiVWPcbq6UkIAAAAASUVORK5CYII="/><element name="timeSliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAYCAYAAAA/OUfnAAAAO0lEQVQYlWP4//8/Awwz0JgDBP/BeN6Cxf/hnI2btiI4u/fsQ3AOHjqK4Jw4eQbBOX/hEoKDYjSd/AMA4cS4mfLsorgAAAAASUVORK5CYII="/><element name="muteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAJklEQVQ4y2NgGAUjDcwH4v/kaPxPikZkxcNVI9mBQ5XoGAWDFwAAsKAXKQQmfbUAAAAASUVORK5CYII="/><element name="unmuteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAMklEQVQ4y2NgGAWDHPyntub5xBr6Hwv/Pzk2/yfVG/8psRFE25Oq8T+tQnsIaB4FVAcAi2YVysVY52AAAAAASUVORK5CYII="/><element name="volumeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYAgMAAACdGdVrAAAACVBMVEUAAACmpqampqbBXAu8AAAAAnRSTlMAgJsrThgAAAArSURBVAhbY2AgErBAyA4I2QEhOyBkB4TsYOhAoaCCUCUwDTDtMMNgRuMHAFB5FoGH5T0UAAAAAElFTkSuQmCC"/><element name="volumeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYAgMAAACdGdVrAAAACVBMVEUAAAAAAAAAAACDY+nAAAAAAnRSTlMAgJsrThgAAAArSURBVAhbY2AgErBAyA4I2QEhOyBkB4TsYOhAoaCCUCUwDTDtMMNgRuMHAFB5FoGH5T0UAAAAAElFTkSuQmCC"/><element name="volumeSliderCapRight" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAYCAYAAAAyJzegAAAAFElEQVQYV2P8//8/AzpgHBUc7oIAGZdH0RjKN8EAAAAASUVORK5CYII="/><element name="fullscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAQklEQVRIiWNgGAWjYMiD/0iYFDmSLbDHImdPLQtgBpEiR7Zl2NijAA5oEkT/0Whi5UiyAJ8BVMsHNMtoo2AUDAIAAGdcIN3IDNXoAAAAAElFTkSuQmCC"/><element name="normalscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAP0lEQVRIx2NgGAWjYMiD/1RSQ5QB/wmIUWzJfzx8qhj+n4DYCAY0DyJ7PBbYU8sHMEvwiZFtODXUjIJRMJgBACpWIN2ZxdPTAAAAAElFTkSuQmCC"/></elements></component><component name="display"><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAQMAAAAk8RryAAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlOZpuml+rYAAAASSURBVBhXY2AYJuA/GBwY6jQAyDyoK8QcL4QAAAAASUVORK5CYII="/><element name="playIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiUlEQVR42u3XSw2AMBREURwgAQlIQAISKgUpSEFKJeCg5b0E0kWBTVcD9ySTsL0Jn9IBAAAA+K2UUrBlW/Rr5ZDoIeeuoFkxJD9ss03aIXXQqB9SttoG7ZA6qNcOKdttiwcJh9RB+iFl4SshkRBuLR72+9cvH0SOKI2HRo7x/Fi1/uoCAAAAwLsD8ki99IlO2dQAAAAASUVORK5CYII="/><element name="muteIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAVUlEQVR42u3WMQrAIAxAUW/g/SdvGmvpoOBeSHgPsjj5QTANAACARCJilIhYM0tEvJM+Ik3Id9E957kQIb+F3OdCPC0hPkQriqWx9hp/x/QGAABQyAPLB22VGrpLDgAAAABJRU5ErkJggg=="/><element name="errorIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAA/0lEQVR42u2U0QmEMBAF7cASLMESUoIlpARLSCkpwRJSgiWkhOvAXD4WsgRkyaG5DbyB+Yvg8KITAAAAAAAYk+u61mwk15EjPtlEfihmqIiZR1Qx80ghjgdUuiHXGHSVsoag0x6x8DUoyjD5KovmEJ9NTDMRPIT0mtdIUkjlonuNohO+Ha99DTmkuGgKCTcvebAzx82ZoCWC3/3aIMWSRucaxcjORSFY4xpFdjYJGp1rFGcyCYZ/RVh6AUnfcNZ2zih3/mGj1jVCdiNDwyrq1rA/xMdeEXvDVdnYc1vDc3uPkDObXrlaxbNHSOohQhr/WOeLEWfWTgAAAAAAADzNF9sHJ7PJ57MlAAAAAElFTkSuQmCC"/><element name="bufferIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAACBklEQVR42u3Zv0sCYRzH8USTzOsHHEWGkC1HgaDgkktGDjUYtDQ01RDSljQ1BLU02+rk1NTm2NLq4Nx/0L/h9fnCd3j4cnZe1/U8xiO8h3uurufF0/3COd/3/0UWYiEWYiEWYiGJQ+J8xuPxKhXjEMZANinjIZhkGuVRNioE4wVURo4JkHm0xKWmhRAc1bh1EyCUw5BcBIjHiApKa4CErko6DEJwuRo6IRKzyJD8FJAyI3Zp2zRImiBcRhlfo5RtlxCcE3CcDNpGrhYIT2IhAJKilO0VRmzJ32fAMTpBTS0QMfGwlcuKMRftE0DJ0wCJdcOsCkBdXP3Mh9CEFUBTPS9mDZJBG6io4aqVzMdCokCw9H3kT6j/C/9iDdSeUMNC7DkyyxAs/Rk6Qss8FPWRZgdVtUH4DjxEn1zxh+/zj1wHlf4MQhNGrwqA6sY40U8JonRJwEQh+AO3AvCG6gHv4U7IY4krxkroWoAOkoQMGfCBrgIm+YBGqPENpIJ66CJg3x66Y0gnSUidAEEnNr9jjLiWMn5DiWP0OC/oAsCgkq43xBdGDMQr7YASP/vEkHvdl1+JOCcEV5sC4hGEOzTlPuKgd0b0xD4JkRcOgnRRTjdErkYhAsQVq6IdUuPJtmk7BCL3t/h88cx91pKQkI/pkDx6pmYTIjEoxiHsN1YWYiEWYiEWknhflZ5IErA5nr8AAAAASUVORK5CYII="/></elements></component><component name="dock"><settings><setting name="fontcolor" value="0xffffff"/></settings><elements><element name="button" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAQMAAAAk8RryAAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlOZpuml+rYAAAASSURBVBhXY2AYJuA/GBwY6jQAyDyoK8QcL4QAAAAASUVORK5CYII="/></elements></component><component name="playlist"><settings><setting name="backgroundcolor" value="0xe8e8e8"/></settings><elements><element name="item" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAIAAAC1nk4lAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHBJREFUaN7t2MENwCAMBEEe9N8wSKYC/D8YV7CyJoRkVtVImxkZPQInMxoP0XiIxkM0HsGbjjSNBx544IEHHnjggUe/6UQeey0PIh7XTftGxKPj4eXCtLsHHh+ZxkO0Iw8PR55Ni8ZD9Hu/EAoP0dc5RRg9qeRjVF8AAAAASUVORK5CYII="/><element name="sliderCapTop" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAHCAYAAADnCQYGAAAAFUlEQVQokWP8//8/A7UB46ihI9hQAKt6FPPXhVGHAAAAAElFTkSuQmCC"/><element name="sliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAUCAYAAABiS3YzAAAAKElEQVQ4y2P4//8/Az68bNmy/+iYkB6GUUNHDR01dNTQUUNHDaXcUABUDOKhcxnsSwAAAABJRU5ErkJggg=="/><element name="sliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAUCAYAAABiS3YzAAAAJUlEQVQ4T2P4//8/Ay4MBP9xYbz6Rg0dNXTU0FFDRw0dNZRyQwHH4NBa7GJsXAAAAABJRU5ErkJggg=="/><element name="sliderCapBottom" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAHCAYAAADnCQYGAAAAFUlEQVQokWP8//8/A7UB46ihI9hQAKt6FPPXhVGHAAAAAElFTkSuQmCC"/></elements></component></components></skin>';this.xml=null;if(window.DOMParser){parser=new DOMParser();this.xml=parser.parseFromString(this.text,"text/xml")}else{this.xml=new ActiveXObject("Microsoft.XMLDOM");this.xml.async="false";this.xml.loadXML(this.text)}return this}})(jwplayer);(function(a){_utils=a.utils;_css=_utils.css;_hide=function(b){_css(b,{display:"none"})};_show=function(b){_css(b,{display:"block"})};a.html5.display=function(k,K){var j={icons:true,showmute:false};var X=_utils.extend({},j,K);var h=k;var W={};var e;var w;var z;var T;var u;var M;var E;var N=!_utils.exists(h.skin.getComponentSettings("display").bufferrotation)?15:parseInt(h.skin.getComponentSettings("display").bufferrotation,10);var s=!_utils.exists(h.skin.getComponentSettings("display").bufferinterval)?100:parseInt(h.skin.getComponentSettings("display").bufferinterval,10);var D=-1;var v=a.api.events.state.IDLE;var O=true;var d;var C=false,V=true;var p="";var g=false;var o=false;var m;var y,R;var L=new a.html5.eventdispatcher();_utils.extend(this,L);var H={display:{style:{cursor:"pointer",top:0,left:0,overflow:"hidden"},click:n},display_icon:{style:{cursor:"pointer",position:"absolute",top:((h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display","playIcon").height)/2),left:((h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display","playIcon").width)/2),border:0,margin:0,padding:0,zIndex:3,display:"none"}},display_iconBackground:{style:{cursor:"pointer",position:"absolute",top:((w-h.skin.getSkinElement("display","background").height)/2),left:((e-h.skin.getSkinElement("display","background").width)/2),border:0,backgroundImage:(["url(",h.skin.getSkinElement("display","background").src,")"]).join(""),width:h.skin.getSkinElement("display","background").width,height:h.skin.getSkinElement("display","background").height,margin:0,padding:0,zIndex:2,display:"none"}},display_image:{style:{display:"none",width:e,height:w,position:"absolute",cursor:"pointer",left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1}},display_text:{style:{zIndex:4,position:"relative",opacity:0.8,backgroundColor:parseInt("000000",16),color:parseInt("ffffff",16),textAlign:"center",fontFamily:"Arial,sans-serif",padding:"0 5px",fontSize:14}}};h.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,q);h.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,q);h.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,P);h.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,q);h.jwAddEventListener(a.api.events.JWPLAYER_ERROR,r);Q();function Q(){W.display=G("div","display");W.display_text=G("div","display_text");W.display.appendChild(W.display_text);W.display_image=G("img","display_image");W.display_image.onerror=function(Y){_hide(W.display_image)};W.display_image.onload=B;W.display_icon=G("div","display_icon");W.display_iconBackground=G("div","display_iconBackground");W.display.appendChild(W.display_image);W.display_iconBackground.appendChild(W.display_icon);W.display.appendChild(W.display_iconBackground);f();setTimeout((function(){o=true;if(X.icons.toString()=="true"){J()}}),1)}this.getDisplayElement=function(){return W.display};this.resize=function(Z,Y){if(h.jwGetFullscreen()&&_utils.isMobile()){return}_css(W.display,{width:Z,height:Y});_css(W.display_text,{width:(Z-10),top:((Y-_utils.getBoundingClientRect(W.display_text).height)/2)});_css(W.display_iconBackground,{top:((Y-h.skin.getSkinElement("display","background").height)/2),left:((Z-h.skin.getSkinElement("display","background").width)/2)});if(e!=Z||w!=Y){e=Z;w=Y;d=undefined;J()}if(!h.jwGetFullscreen()){y=Z;R=Y}c();q({})};this.show=function(){if(g){g=false;t(h.jwGetState())}};this.hide=function(){if(!g){F();g=true}};function B(Y){z=W.display_image.naturalWidth;T=W.display_image.naturalHeight;c();if(h.jwGetState()==a.api.events.state.IDLE){_css(W.display_image,{display:"block",opacity:0});_utils.fadeTo(W.display_image,1,0.1)}C=false}function c(){if(h.jwGetFullscreen()&&h.jwGetStretching()==a.utils.stretching.EXACTFIT){var Y=document.createElement("div");_utils.stretch(a.utils.stretching.UNIFORM,Y,e,w,y,R);_utils.stretch(a.utils.stretching.EXACTFIT,W.display_image,_utils.parseDimension(Y.style.width),_utils.parseDimension(Y.style.height),z,T);_css(W.display_image,{left:Y.style.left,top:Y.style.top})}else{_utils.stretch(h.jwGetStretching(),W.display_image,e,w,z,T)}}function G(Y,aa){var Z=document.createElement(Y);Z.id=h.id+"_jwplayer_"+aa;_css(Z,H[aa].style);return Z}function f(){for(var Y in W){if(_utils.exists(H[Y].click)){W[Y].onclick=H[Y].click}}}function n(Y){if(typeof Y.preventDefault!="undefined"){Y.preventDefault()}else{Y.returnValue=false}if(typeof m=="function"){m(Y);return}else{if(h.jwGetState()!=a.api.events.state.PLAYING){h.jwPlay()}else{h.jwPause()}}}function U(Y){if(E){F();return}W.display_icon.style.backgroundImage=(["url(",h.skin.getSkinElement("display",Y).src,")"]).join("");_css(W.display_icon,{width:h.skin.getSkinElement("display",Y).width,height:h.skin.getSkinElement("display",Y).height,top:(h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display",Y).height)/2,left:(h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display",Y).width)/2});b();if(_utils.exists(h.skin.getSkinElement("display",Y+"Over"))){W.display_icon.onmouseover=function(Z){W.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",Y+"Over").src,")"].join("")};W.display_icon.onmouseout=function(Z){W.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",Y).src,")"].join("")}}else{W.display_icon.onmouseover=null;W.display_icon.onmouseout=null}}function F(){if(X.icons.toString()=="true"){_hide(W.display_icon);_hide(W.display_iconBackground);S()}}function b(){if(!g&&X.icons.toString()=="true"){_show(W.display_icon);_show(W.display_iconBackground);J()}}function r(Y){E=true;F();W.display_text.innerHTML=Y.message;_show(W.display_text);W.display_text.style.top=((w-_utils.getBoundingClientRect(W.display_text).height)/2)+"px"}function I(){V=false;W.display_image.style.display="none"}function P(){v=""}function q(Y){if((Y.type==a.api.events.JWPLAYER_PLAYER_STATE||Y.type==a.api.events.JWPLAYER_PLAYLIST_ITEM)&&E){E=false;_hide(W.display_text)}var Z=h.jwGetState();if(Z==v){return}v=Z;if(D>=0){clearTimeout(D)}if(O||h.jwGetState()==a.api.events.state.PLAYING||h.jwGetState()==a.api.events.state.PAUSED){t(h.jwGetState())}else{D=setTimeout(l(h.jwGetState()),500)}}function l(Y){return(function(){t(Y)})}function t(Y){if(_utils.exists(M)){clearInterval(M);M=null;_utils.animations.rotate(W.display_icon,0)}switch(Y){case a.api.events.state.BUFFERING:if(_utils.isIPod()){I();F()}else{if(h.jwGetPlaylist()[h.jwGetPlaylistIndex()].provider=="sound"){x()}u=0;M=setInterval(function(){u+=N;_utils.animations.rotate(W.display_icon,u%360)},s);U("bufferIcon");O=true}break;case a.api.events.state.PAUSED:if(!_utils.isIPod()){if(h.jwGetPlaylist()[h.jwGetPlaylistIndex()].provider!="sound"){_css(W.display_image,{background:"transparent no-repeat center center"})}U("playIcon");O=true}break;case a.api.events.state.IDLE:if(h.jwGetPlaylist()[h.jwGetPlaylistIndex()]&&h.jwGetPlaylist()[h.jwGetPlaylistIndex()].image){x()}else{I()}U("playIcon");O=true;break;default:if(h.jwGetPlaylist()[h.jwGetPlaylistIndex()]&&h.jwGetPlaylist()[h.jwGetPlaylistIndex()].provider=="sound"){if(_utils.isIPod()){I();O=false}else{x()}}else{I();O=false}if(h.jwGetMute()&&X.showmute){U("muteIcon")}else{F()}break}D=-1}function x(){if(h.jwGetPlaylist()[h.jwGetPlaylistIndex()]){var Y=h.jwGetPlaylist()[h.jwGetPlaylistIndex()].image;if(Y){if(Y!=p){p=Y;C=true;W.display_image.src=_utils.getAbsolutePath(Y)}else{if(!(C||V)){V=true;W.display_image.style.opacity=0;W.display_image.style.display="block";_utils.fadeTo(W.display_image,1,0.1)}}}}}function A(Y){return function(){if(!o){return}if(!g&&d!=Y){d=Y;L.sendEvent(Y,{component:"display",boundingRect:_utils.getDimensions(W.display_iconBackground)})}}}var J=A(a.api.events.JWPLAYER_COMPONENT_SHOW);var S=A(a.api.events.JWPLAYER_COMPONENT_HIDE);this.setAlternateClickHandler=function(Y){m=Y};this.revertAlternateClickHandler=function(){m=undefined};return this}})(jwplayer);(function(a){var c=a.utils;var b=c.css;a.html5.dock=function(w,D){function x(){return{align:a.html5.view.positions.RIGHT}}var n=c.extend({},x(),D);if(n.align=="FALSE"){return}var j={};var A=[];var k;var F;var f=false;var C=false;var g={x:0,y:0,width:0,height:0};var z;var o;var y;var m=new a.html5.eventdispatcher();c.extend(this,m);var r=document.createElement("div");r.id=w.id+"_jwplayer_dock";r.style.opacity=1;p();w.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,q);this.getDisplayElement=function(){return r};this.setButton=function(K,H,I,J){if(!H&&j[K]){c.arrays.remove(A,K);r.removeChild(j[K].div);delete j[K]}else{if(H){if(!j[K]){j[K]={}}j[K].handler=H;j[K].outGraphic=I;j[K].overGraphic=J;if(!j[K].div){A.push(K);j[K].div=document.createElement("div");j[K].div.style.position="absolute";r.appendChild(j[K].div);j[K].div.appendChild(document.createElement("div"));j[K].div.childNodes[0].style.position="relative";j[K].div.childNodes[0].style.width="100%";j[K].div.childNodes[0].style.height="100%";j[K].div.childNodes[0].style.zIndex=10;j[K].div.childNodes[0].style.cursor="pointer";j[K].div.appendChild(document.createElement("img"));j[K].div.childNodes[1].style.position="absolute";j[K].div.childNodes[1].style.left=0;j[K].div.childNodes[1].style.top=0;if(w.skin.getSkinElement("dock","button")){j[K].div.childNodes[1].src=w.skin.getSkinElement("dock","button").src}j[K].div.childNodes[1].style.zIndex=9;j[K].div.childNodes[1].style.cursor="pointer";j[K].div.onmouseover=function(){if(j[K].overGraphic){j[K].div.childNodes[0].style.background=h(j[K].overGraphic)}if(w.skin.getSkinElement("dock","buttonOver")){j[K].div.childNodes[1].src=w.skin.getSkinElement("dock","buttonOver").src}};j[K].div.onmouseout=function(){if(j[K].outGraphic){j[K].div.childNodes[0].style.background=h(j[K].outGraphic)}if(w.skin.getSkinElement("dock","button")){j[K].div.childNodes[1].src=w.skin.getSkinElement("dock","button").src}};if(w.skin.getSkinElement("dock","button")){j[K].div.childNodes[1].src=w.skin.getSkinElement("dock","button").src}}if(j[K].outGraphic){j[K].div.childNodes[0].style.background=h(j[K].outGraphic)}else{if(j[K].overGraphic){j[K].div.childNodes[0].style.background=h(j[K].overGraphic)}}if(H){j[K].div.onclick=function(L){L.preventDefault();a(w.id).callback(K);if(j[K].overGraphic){j[K].div.childNodes[0].style.background=h(j[K].overGraphic)}if(w.skin.getSkinElement("dock","button")){j[K].div.childNodes[1].src=w.skin.getSkinElement("dock","button").src}}}}}l(k,F)};function h(H){return"url("+H+") no-repeat center center"}function t(H){}function l(H,T){p();if(A.length>0){var I=10;var S=I;var P=-1;var Q=w.skin.getSkinElement("dock","button").height;var O=w.skin.getSkinElement("dock","button").width;var M=H-O-I;var R,L;if(n.align==a.html5.view.positions.LEFT){P=1;M=I}for(var J=0;J<A.length;J++){var U=Math.floor(S/T);if((S+Q+I)>((U+1)*T)){S=((U+1)*T)+I;U=Math.floor(S/T)}var K=j[A[J]].div;K.style.top=(S%T)+"px";K.style.left=(M+(w.skin.getSkinElement("dock","button").width+I)*U*P)+"px";var N={x:c.parseDimension(K.style.left),y:c.parseDimension(K.style.top),width:O,height:Q};if(!R||(N.x<=R.x&&N.y<=R.y)){R=N}if(!L||(N.x>=L.x&&N.y>=L.y)){L=N}K.style.width=O+"px";K.style.height=Q+"px";S+=w.skin.getSkinElement("dock","button").height+I}g={x:R.x,y:R.y,width:L.x-R.x+L.width,height:R.y-L.y+L.height}}if(C!=w.jwGetFullscreen()||k!=H||F!=T){k=H;F=T;C=w.jwGetFullscreen();z=undefined;setTimeout(s,1)}}function d(H){return function(){if(!f&&z!=H&&A.length>0){z=H;m.sendEvent(H,{component:"dock",boundingRect:g})}}}function q(H){if(c.isMobile()){if(H.newstate==a.api.events.state.IDLE){v()}else{e()}}else{B()}}function B(H){if(f){return}clearTimeout(y);if(D.position==a.html5.view.positions.OVER||w.jwGetFullscreen()){switch(w.jwGetState()){case a.api.events.state.PAUSED:case a.api.events.state.IDLE:if(r&&r.style.opacity<1&&(!D.idlehide||c.exists(H))){E()}if(D.idlehide){y=setTimeout(function(){u()},2000)}break;default:if(c.exists(H)){E()}y=setTimeout(function(){u()},2000);break}}else{E()}}var s=d(a.api.events.JWPLAYER_COMPONENT_SHOW);var G=d(a.api.events.JWPLAYER_COMPONENT_HIDE);this.resize=l;var v=function(){b(r,{display:"block"});if(f){f=false;s()}};var e=function(){b(r,{display:"none"});if(!f){G();f=true}};function u(){if(!f){G();if(r.style.opacity==1){c.cancelAnimation(r);c.fadeTo(r,0,0.1,1,0)}}}function E(){if(!f){s();if(r.style.opacity==0){c.cancelAnimation(r);c.fadeTo(r,1,0.1,0,0)}}}function p(){try{o=document.getElementById(w.id);o.addEventListener("mousemove",B)}catch(H){c.log("Could not add mouse listeners to dock: "+H)}}this.hide=e;this.show=v;return this}})(jwplayer);(function(a){a.html5.eventdispatcher=function(d,b){var c=new a.events.eventdispatcher(b);a.utils.extend(this,c);this.sendEvent=function(e,f){if(!a.utils.exists(f)){f={}}a.utils.extend(f,{id:d,version:a.version,type:e});c.sendEvent(e,f)}}})(jwplayer);(function(a){var b=a.utils;a.html5.instream=function(y,m,x,z){var t={controlbarseekable:"always",controlbarpausable:true,controlbarstoppable:true,playlistclickable:true};var v,A,C=y,E=m,j=x,w=z,r,H,o,G,e,f,g,l,q,h=false,k,d,n=this;this.load=function(M,K){c();h=true;A=b.extend(t,K);v=a.html5.playlistitem(M);F();d=document.createElement("div");d.id=n.id+"_instream_container";w.detachMedia();r=g.getDisplayElement();f=E.playlist[E.item];e=C.jwGetState();if(e==a.api.events.state.BUFFERING||e==a.api.events.state.PLAYING){r.pause()}H=r.src?r.src:r.currentSrc;o=r.innerHTML;G=r.currentTime;q=new a.html5.display(n,b.extend({},E.plugins.config.display));q.setAlternateClickHandler(function(N){if(_fakemodel.state==a.api.events.state.PAUSED){n.jwInstreamPlay()}else{D(a.api.events.JWPLAYER_INSTREAM_CLICK,N)}});d.appendChild(q.getDisplayElement());if(!b.isMobile()){l=new a.html5.controlbar(n,b.extend({},E.plugins.config.controlbar,{}));if(E.plugins.config.controlbar.position==a.html5.view.positions.OVER){d.appendChild(l.getDisplayElement())}else{var L=E.plugins.object.controlbar.getDisplayElement().parentNode;L.appendChild(l.getDisplayElement())}}j.setupInstream(d,r);p();g.load(v)};this.jwInstreamDestroy=function(K){if(!h){return}h=false;if(e!=a.api.events.state.IDLE){g.load(f,false);g.stop(false)}else{g.stop(true)}g.detachMedia();j.destroyInstream();if(l){try{l.getDisplayElement().parentNode.removeChild(l.getDisplayElement())}catch(L){}}D(a.api.events.JWPLAYER_INSTREAM_DESTROYED,{reason:(K?"complete":"destroyed")},true);w.attachMedia();if(e==a.api.events.state.BUFFERING||e==a.api.events.state.PLAYING){r.play();if(E.playlist[E.item]==f){E.getMedia().seek(G)}}return};this.jwInstreamAddEventListener=function(K,L){k.addEventListener(K,L)};this.jwInstreamRemoveEventListener=function(K,L){k.removeEventListener(K,L)};this.jwInstreamPlay=function(){if(!h){return}g.play(true)};this.jwInstreamPause=function(){if(!h){return}g.pause(true)};this.jwInstreamSeek=function(K){if(!h){return}g.seek(K)};this.jwInstreamGetState=function(){if(!h){return undefined}return _fakemodel.state};this.jwInstreamGetPosition=function(){if(!h){return undefined}return _fakemodel.position};this.jwInstreamGetDuration=function(){if(!h){return undefined}return _fakemodel.duration};this.playlistClickable=function(){return(!h||A.playlistclickable.toString().toLowerCase()=="true")};function s(){_fakemodel=new a.html5.model(this,E.getMedia()?E.getMedia().getDisplayElement():E.container,E);k=new a.html5.eventdispatcher();C.jwAddEventListener(a.api.events.JWPLAYER_RESIZE,p);C.jwAddEventListener(a.api.events.JWPLAYER_FULLSCREEN,p)}function c(){_fakemodel.setMute(E.mute);_fakemodel.setVolume(E.volume)}function F(){if(!g){g=new a.html5.mediavideo(_fakemodel,E.getMedia()?E.getMedia().getDisplayElement():E.container);g.addGlobalListener(I);g.addEventListener(a.api.events.JWPLAYER_MEDIA_META,J);g.addEventListener(a.api.events.JWPLAYER_MEDIA_COMPLETE,u);g.addEventListener(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL,B)}g.attachMedia()}function I(K){if(h){D(K.type,K)}}function B(K){if(h){g.play()}}function u(K){if(h){setTimeout(function(){n.jwInstreamDestroy(true)},10)}}function J(K){if(K.metadata.width&&K.metadata.height){j.resizeMedia()}}function D(K,L,M){if(h||M){k.sendEvent(K,L)}}function p(){var K=E.plugins.object.display.getDisplayElement().style;if(l){var L=E.plugins.object.controlbar.getDisplayElement().style;l.resize(b.parseDimension(K.width),b.parseDimension(L.height));_css(l.getDisplayElement(),b.extend({},L,{zIndex:1001,opacity:1}))}if(q){q.resize(b.parseDimension(K.width),b.parseDimension(K.height));_css(q.getDisplayElement(),b.extend({},K,{zIndex:1000}))}if(j){j.resizeMedia()}}this.jwPlay=function(K){if(A.controlbarpausable.toString().toLowerCase()=="true"){this.jwInstreamPlay()}};this.jwPause=function(K){if(A.controlbarpausable.toString().toLowerCase()=="true"){this.jwInstreamPause()}};this.jwStop=function(){if(A.controlbarstoppable.toString().toLowerCase()=="true"){this.jwInstreamDestroy();C.jwStop()}};this.jwSeek=function(K){switch(A.controlbarseekable.toLowerCase()){case"always":this.jwInstreamSeek(K);break;case"backwards":if(_fakemodel.position>K){this.jwInstreamSeek(K)}break}};this.jwGetPosition=function(){};this.jwGetDuration=function(){};this.jwGetWidth=C.jwGetWidth;this.jwGetHeight=C.jwGetHeight;this.jwGetFullscreen=C.jwGetFullscreen;this.jwSetFullscreen=C.jwSetFullscreen;this.jwGetVolume=function(){return E.volume};this.jwSetVolume=function(K){g.volume(K);C.jwSetVolume(K)};this.jwGetMute=function(){return E.mute};this.jwSetMute=function(K){g.mute(K);C.jwSetMute(K)};this.jwGetState=function(){return _fakemodel.state};this.jwGetPlaylist=function(){return[v]};this.jwGetPlaylistIndex=function(){return 0};this.jwGetStretching=function(){return E.config.stretching};this.jwAddEventListener=function(L,K){k.addEventListener(L,K)};this.jwRemoveEventListener=function(L,K){k.removeEventListener(L,K)};this.skin=C.skin;this.id=C.id+"_instream";s();return this}})(jwplayer);(function(a){var b={prefix:"http://l.longtailvideo.com/html5/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",linktarget:"_top",margin:8,out:0.5,over:1,timeout:5,hide:true,position:"bottom-left"};_css=a.utils.css;a.html5.logo=function(n,r){var q=n;var u;var d;var t;var h=false;g();function g(){o();q.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,j);c();l()}function o(){if(b.prefix){var v=n.version.split(/\W/).splice(0,2).join("/");if(b.prefix.indexOf(v)<0){b.prefix+=v+"/"}}if(r.position==a.html5.view.positions.OVER){r.position=b.position}try{if(window.location.href.indexOf("https")==0){b.prefix=b.prefix.replace("http://l.longtailvideo.com","https://securel.longtailvideo.com")}}catch(w){}d=a.utils.extend({},b)}function c(){t=document.createElement("img");t.id=q.id+"_jwplayer_logo";t.style.display="none";t.onload=function(v){_css(t,k());p()};if(!d.file){return}if(d.file.indexOf("/")>=0){t.src=d.file}else{t.src=d.prefix+d.file}}if(!d.file){return}this.resize=function(w,v){};this.getDisplayElement=function(){return t};function l(){if(d.link){t.onmouseover=f;t.onmouseout=p;t.onclick=s}else{this.mouseEnabled=false}}function s(v){if(typeof v!="undefined"){v.stopPropagation()}if(!h){return}q.jwPause();q.jwSetFullscreen(false);if(d.link){window.open(d.link,d.linktarget)}return}function p(v){if(d.link&&h){t.style.opacity=d.out}return}function f(v){if(h){t.style.opacity=d.over}return}function k(){var x={textDecoration:"none",position:"absolute",cursor:"pointer"};x.display=(d.hide.toString()=="true"&&!h)?"none":"block";var w=d.position.toLowerCase().split("-");for(var v in w){x[w[v]]=parseInt(d.margin)}return x}function m(){if(d.hide.toString()=="true"){t.style.display="block";t.style.opacity=0;a.utils.fadeTo(t,d.out,0.1,parseFloat(t.style.opacity));u=setTimeout(function(){e()},d.timeout*1000)}h=true}function e(){h=false;if(d.hide.toString()=="true"){a.utils.fadeTo(t,0,0.1,parseFloat(t.style.opacity))}}function j(v){if(v.newstate==a.api.events.state.BUFFERING){clearTimeout(u);m()}}return this}})(jwplayer);(function(b){var d={ended:b.api.events.state.IDLE,playing:b.api.events.state.PLAYING,pause:b.api.events.state.PAUSED,buffering:b.api.events.state.BUFFERING};var e=b.utils;var a=e.isMobile();var c={};b.html5.mediavideo=function(h,F){var J={abort:y,canplay:p,canplaythrough:p,durationchange:u,emptied:y,ended:p,error:o,loadeddata:u,loadedmetadata:u,loadstart:p,pause:p,play:y,playing:p,progress:D,ratechange:y,seeked:p,seeking:p,stalled:p,suspend:p,timeupdate:N,volumechange:l,waiting:p,canshowcurrentframe:y,dataunavailable:y,empty:y,load:g,loadedfirstframe:y,webkitfullscreenchange:k};var K=new b.html5.eventdispatcher();e.extend(this,K);var j=h,B=F,m,f,C,T,E,M,L=false,t=false,x=false,I,G,Q;R();this.load=function(V,W){if(typeof W=="undefined"){W=true}if(!t){return}T=V;x=(T.duration>0);j.duration=T.duration;e.empty(m);Q=0;q(V.levels);if(V.levels&&V.levels.length>0){if(V.levels.length==1||e.isIOS()){m.src=V.levels[0].file}else{if(m.src){m.removeAttribute("src")}for(var U=0;U<V.levels.length;U++){var X=m.ownerDocument.createElement("source");X.src=V.levels[U].file;m.appendChild(X);Q++}}}else{m.src=V.file}m.style.display="block";m.style.opacity=1;m.volume=j.volume/100;m.muted=j.mute;if(a){P()}I=G=C=false;j.buffer=0;if(!e.exists(V.start)){V.start=0}M=(V.start>0)?V.start:-1;s(b.api.events.JWPLAYER_MEDIA_LOADED);if((!a&&V.levels.length==1)||!L){m.load()}L=false;if(W){w(b.api.events.state.BUFFERING);s(b.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});A()}if(m.videoWidth>0&&m.videoHeight>0){u()}};this.play=function(){if(!t){return}A();if(G){w(b.api.events.state.PLAYING)}else{w(b.api.events.state.BUFFERING)}m.play()};this.pause=function(){if(!t){return}m.pause();w(b.api.events.state.PAUSED)};this.seek=function(U){if(!t){return}if(!C&&m.readyState>0){if(!(j.duration<=0||isNaN(j.duration))&&!(j.position<=0||isNaN(j.position))){m.currentTime=U;m.play()}}else{M=U}};var z=this.stop=function(U){if(!t){return}if(!e.exists(U)){U=true}r();if(U){G=false;var V=navigator.userAgent;if(m.webkitSupportsFullscreen){try{m.webkitExitFullscreen()}catch(W){}}m.style.opacity=0;v();if(e.isIE()){m.src=""}else{m.removeAttribute("src")}e.empty(m);m.load();L=true}w(b.api.events.state.IDLE)};this.fullscreen=function(U){if(U===true){this.resize("100%","100%")}else{this.resize(j.config.width,j.config.height)}};this.resize=function(V,U){};this.volume=function(U){if(!a){m.volume=U/100;s(b.api.events.JWPLAYER_MEDIA_VOLUME,{volume:(U/100)})}};this.mute=function(U){if(!a){m.muted=U;s(b.api.events.JWPLAYER_MEDIA_MUTE,{mute:U})}};this.getDisplayElement=function(){return m};this.hasChrome=function(){return a&&(f==b.api.events.state.PLAYING)};this.detachMedia=function(){t=false;return this.getDisplayElement()};this.attachMedia=function(){t=true};function H(V,U){return function(W){if(e.exists(W.target.parentNode)){U(W)}}}function R(){f=b.api.events.state.IDLE;t=true;m=n();m.setAttribute("x-webkit-airplay","allow");if(B.parentNode){m.id=B.id;B.parentNode.replaceChild(m,B)}}function n(){var U=c[j.id];if(!U){if(B.tagName.toLowerCase()=="video"){U=B}else{U=document.createElement("video")}c[j.id]=U;if(!U.id){U.id=B.id}}for(var V in J){U.addEventListener(V,H(V,J[V]),true)}return U}function w(U){if(U==b.api.events.state.PAUSED&&f==b.api.events.state.IDLE){return}if(a){switch(U){case b.api.events.state.PLAYING:P();break;case b.api.events.state.BUFFERING:case b.api.events.state.PAUSED:v();break}}if(f!=U){var V=f;j.state=f=U;s(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:V,newstate:U})}}function y(U){}function l(U){var V=Math.round(m.volume*100);s(b.api.events.JWPLAYER_MEDIA_VOLUME,{volume:V},true);s(b.api.events.JWPLAYER_MEDIA_MUTE,{mute:m.muted},true)}function D(W){if(!t){return}var V;if(e.exists(W)&&W.lengthComputable&&W.total){V=W.loaded/W.total*100}else{if(e.exists(m.buffered)&&(m.buffered.length>0)){var U=m.buffered.length-1;if(U>=0){V=m.buffered.end(U)/m.duration*100}}}if(e.useNativeFullscreen()&&e.exists(m.webkitDisplayingFullscreen)){if(j.fullscreen!=m.webkitDisplayingFullscreen){s(b.api.events.JWPLAYER_FULLSCREEN,{fullscreen:m.webkitDisplayingFullscreen},true)}}if(G===false&&f==b.api.events.state.BUFFERING){s(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL);G=true}if(!I){if(V==100){I=true}if(e.exists(V)&&(V>j.buffer)){j.buffer=Math.round(V);s(b.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:Math.round(V)})}}}function N(V){if(!t){return}if(e.exists(V)&&e.exists(V.target)){if(x>0){if(!isNaN(V.target.duration)&&(isNaN(j.duration)||j.duration<1)){if(V.target.duration==Infinity){j.duration=0}else{j.duration=Math.round(V.target.duration*10)/10}}}if(!C&&m.readyState>0){w(b.api.events.state.PLAYING)}if(f==b.api.events.state.PLAYING){if(m.readyState>0&&(M>-1||!C)){C=true;try{if(m.currentTime!=M&&M>-1){m.currentTime=M;M=-1}}catch(U){}m.volume=j.volume/100;m.muted=j.mute}j.position=j.duration>0?(Math.round(V.target.currentTime*10)/10):0;s(b.api.events.JWPLAYER_MEDIA_TIME,{position:j.position,duration:j.duration});if(j.position>=j.duration&&(j.position>0||j.duration>0)){O();return}}}D(V)}function g(U){}function p(U){if(!t){return}if(d[U.type]){if(U.type=="ended"){O()}else{w(d[U.type])}}}function u(V){if(!t){return}var U=Math.round(m.duration*10)/10;var W={height:m.videoHeight,width:m.videoWidth,duration:U};if(!x){if((j.duration<U||isNaN(j.duration))&&m.duration!=Infinity){j.duration=U}}s(b.api.events.JWPLAYER_MEDIA_META,{metadata:W})}function o(W){if(!t){return}if(f==b.api.events.state.IDLE){return}var V="There was an error: ";if((W.target.error&&W.target.tagName.toLowerCase()=="video")||W.target.parentNode.error&&W.target.parentNode.tagName.toLowerCase()=="video"){var U=!e.exists(W.target.error)?W.target.parentNode.error:W.target.error;switch(U.code){case U.MEDIA_ERR_ABORTED:e.log("User aborted the video playback.");return;case U.MEDIA_ERR_NETWORK:V="A network error caused the video download to fail part-way: ";break;case U.MEDIA_ERR_DECODE:V="The video playback was aborted due to a corruption problem or because the video used features your browser did not support: ";break;case U.MEDIA_ERR_SRC_NOT_SUPPORTED:V="The video could not be loaded, either because the server or network failed or because the format is not supported: ";break;default:V="An unknown error occurred: ";break}}else{if(W.target.tagName.toLowerCase()=="source"){Q--;if(Q>0){return}if(e.userAgentMatch(/firefox/i)){e.log("The video could not be loaded, either because the server or network failed or because the format is not supported.");z(false);return}else{V="The video could not be loaded, either because the server or network failed or because the format is not supported: "}}else{e.log("An unknown error occurred. Continuing...");return}}z(false);V+=S();_error=true;s(b.api.events.JWPLAYER_ERROR,{message:V});return}function S(){var W="";for(var V in T.levels){var U=T.levels[V];var X=B.ownerDocument.createElement("source");W+=b.utils.getAbsolutePath(U.file);if(V<(T.levels.length-1)){W+=", "}}return W}function A(){if(!e.exists(E)){E=setInterval(function(){D()},100)}}function r(){clearInterval(E);E=null}function O(){if(f==b.api.events.state.PLAYING){z(false);s(b.api.events.JWPLAYER_MEDIA_BEFORECOMPLETE);s(b.api.events.JWPLAYER_MEDIA_COMPLETE)}}function k(U){if(e.exists(m.webkitDisplayingFullscreen)){if(j.fullscreen&&!m.webkitDisplayingFullscreen){s(b.api.events.JWPLAYER_FULLSCREEN,{fullscreen:false},true)}}}function q(W){if(W.length>0&&e.userAgentMatch(/Safari/i)&&!e.userAgentMatch(/Chrome/i)){var U=-1;for(var V=0;V<W.length;V++){switch(e.extension(W[V].file)){case"mp4":if(U<0){U=V}break;case"webm":W.splice(V,1);break}}if(U>0){var X=W.splice(U,1)[0];W.unshift(X)}}}function P(){setTimeout(function(){m.setAttribute("controls","controls")},100)}function v(){setTimeout(function(){m.removeAttribute("controls")},250)}function s(U,W,V){if(t||V){if(W){K.sendEvent(U,W)}else{K.sendEvent(U)}}}}})(jwplayer);(function(a){var c={ended:a.api.events.state.IDLE,playing:a.api.events.state.PLAYING,pause:a.api.events.state.PAUSED,buffering:a.api.events.state.BUFFERING};var b=a.utils.css;a.html5.mediayoutube=function(j,e){var f=new a.html5.eventdispatcher();a.utils.extend(this,f);var l=j;var h=document.getElementById(e.id);var g=a.api.events.state.IDLE;var n,m;function k(p){if(g!=p){var q=g;l.state=p;g=p;f.sendEvent(a.api.events.JWPLAYER_PLAYER_STATE,{oldstate:q,newstate:p})}}this.getDisplayElement=this.detachMedia=function(){return h};this.attachMedia=function(){};this.play=function(){if(g==a.api.events.state.IDLE){f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:100});f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL);k(a.api.events.state.PLAYING)}else{if(g==a.api.events.state.PAUSED){k(a.api.events.state.PLAYING)}}};this.pause=function(){k(a.api.events.state.PAUSED)};this.seek=function(p){};this.stop=function(p){if(!_utils.exists(p)){p=true}l.position=0;k(a.api.events.state.IDLE);if(p){b(h,{display:"none"})}};this.volume=function(p){l.setVolume(p);f.sendEvent(a.api.events.JWPLAYER_MEDIA_VOLUME,{volume:Math.round(p)})};this.mute=function(p){h.muted=p;f.sendEvent(a.api.events.JWPLAYER_MEDIA_MUTE,{mute:p})};this.resize=function(q,p){if(q*p>0&&n){n.width=m.width=q;n.height=m.height=p}};this.fullscreen=function(p){if(p===true){this.resize("100%","100%")}else{this.resize(l.config.width,l.config.height)}};this.load=function(p){o(p);b(n,{display:"block"});k(a.api.events.state.BUFFERING);f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});f.sendEvent(a.api.events.JWPLAYER_MEDIA_LOADED);this.play()};this.hasChrome=function(){return(g!=a.api.events.state.IDLE)};function o(v){var s=v.levels[0].file;s=["http://www.youtube.com/v/",d(s),"&hl=en_US&fs=1&autoplay=1"].join("");n=document.createElement("object");n.id=h.id;n.style.position="absolute";var u={movie:s,allowfullscreen:"true",allowscriptaccess:"always"};for(var p in u){var t=document.createElement("param");t.name=p;t.value=u[p];n.appendChild(t)}m=document.createElement("embed");n.appendChild(m);var q={src:s,type:"application/x-shockwave-flash",allowfullscreen:"true",allowscriptaccess:"always",width:n.width,height:n.height};for(var r in q){m.setAttribute(r,q[r])}n.appendChild(m);n.style.zIndex=2147483000;if(h!=n&&h.parentNode){h.parentNode.replaceChild(n,h)}h=n}function d(q){var p=q.split(/\?|\#\!/);var s="";for(var r=0;r<p.length;r++){if(p[r].substr(0,2)=="v="){s=p[r].substr(2)}}if(s==""){if(q.indexOf("/v/")>=0){s=q.substr(q.indexOf("/v/")+3)}else{if(q.indexOf("youtu.be")>=0){s=q.substr(q.indexOf("youtu.be/")+9)}else{s=q}}}if(s.indexOf("?")>-1){s=s.substr(0,s.indexOf("?"))}if(s.indexOf("&")>-1){s=s.substr(0,s.indexOf("&"))}return s}this.embed=m;return this}})(jwplayer);(function(jwplayer){var _configurableStateVariables=["width","height","start","duration","volume","mute","fullscreen","item","plugins","stretching"];var _utils=jwplayer.utils;jwplayer.html5.model=function(api,container,options){var _api=api;var _container=container;var _cookies=_utils.getCookies();var _model={id:_container.id,playlist:[],state:jwplayer.api.events.state.IDLE,position:0,buffer:0,container:_container,config:{width:480,height:320,item:-1,skin:undefined,file:undefined,image:undefined,start:0,duration:0,bufferlength:5,volume:_cookies.volume?_cookies.volume:90,mute:_cookies.mute&&_cookies.mute.toString().toLowerCase()=="true"?true:false,fullscreen:false,repeat:"",stretching:jwplayer.utils.stretching.UNIFORM,autostart:false,debug:undefined,screencolor:undefined}};var _media;var _eventDispatcher=new jwplayer.html5.eventdispatcher();var _components=["display","logo","controlbar","playlist","dock"];jwplayer.utils.extend(_model,_eventDispatcher);for(var option in options){if(typeof options[option]=="string"){var type=/color$/.test(option)?"color":null;options[option]=jwplayer.utils.typechecker(options[option],type)}var config=_model.config;var path=option.split(".");for(var edge in path){if(edge==path.length-1){config[path[edge]]=options[option]}else{if(!jwplayer.utils.exists(config[path[edge]])){config[path[edge]]={}}config=config[path[edge]]}}}for(var index in _configurableStateVariables){var configurableStateVariable=_configurableStateVariables[index];_model[configurableStateVariable]=_model.config[configurableStateVariable]}var pluginorder=_components.concat([]);if(jwplayer.utils.exists(_model.plugins)){if(typeof _model.plugins=="string"){var userplugins=_model.plugins.split(",");for(var userplugin in userplugins){if(typeof userplugins[userplugin]=="string"){pluginorder.push(userplugins[userplugin].replace(/^\s+|\s+$/g,""))}}}}if(jwplayer.utils.isMobile()){pluginorder=["display","logo","dock","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}else{if(_model.config.chromeless){pluginorder=["logo","dock","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}}_model.plugins={order:pluginorder,config:{},object:{}};if(typeof _model.config.components!="undefined"){for(var component in _model.config.components){_model.plugins.config[component]=_model.config.components[component]}}var playlistVisible=false;for(var pluginIndex in _model.plugins.order){var pluginName=_model.plugins.order[pluginIndex];var pluginConfig=!jwplayer.utils.exists(_model.plugins.config[pluginName])?{}:_model.plugins.config[pluginName];_model.plugins.config[pluginName]=!jwplayer.utils.exists(_model.plugins.config[pluginName])?pluginConfig:jwplayer.utils.extend(_model.plugins.config[pluginName],pluginConfig);if(!jwplayer.utils.exists(_model.plugins.config[pluginName].position)){if(pluginName=="playlist"){_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.NONE}else{_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.OVER}}else{if(pluginName=="playlist"){playlistVisible=true}_model.plugins.config[pluginName].position=_model.plugins.config[pluginName].position.toString().toUpperCase()}}if(_model.plugins.config.controlbar&&playlistVisible){_model.plugins.config.controlbar.hideplaylistcontrols=true}if(typeof _model.plugins.config.dock!="undefined"){if(typeof _model.plugins.config.dock!="object"){var position=_model.plugins.config.dock.toString().toUpperCase();_model.plugins.config.dock={position:position}}if(typeof _model.plugins.config.dock.position!="undefined"){_model.plugins.config.dock.align=_model.plugins.config.dock.position;_model.plugins.config.dock.position=jwplayer.html5.view.positions.OVER}if(typeof _model.plugins.config.dock.idlehide=="undefined"){try{_model.plugins.config.dock.idlehide=_model.plugins.config.controlbar.idlehide}catch(e){}}}function _loadExternal(playlistfile){var loader=new jwplayer.html5.playlistloader();loader.addEventListener(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,function(evt){_model.playlist=new jwplayer.html5.playlist(evt);_loadComplete(true)});loader.addEventListener(jwplayer.api.events.JWPLAYER_ERROR,function(evt){_model.playlist=new jwplayer.html5.playlist({playlist:[]});_loadComplete(false)});loader.load(playlistfile)}function _loadComplete(){if(_model.config.shuffle){_model.item=_getShuffleItem()}else{if(_model.config.item>=_model.playlist.length){_model.config.item=_model.playlist.length-1}else{if(_model.config.item<0){_model.config.item=0}}_model.item=_model.config.item}_model.position=0;_model.duration=_model.playlist.length>0?_model.playlist[_model.item].duration:0;_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:_model.playlist});_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_ITEM,{index:_model.item})}_model.loadPlaylist=function(arg){var input;if(typeof arg=="string"){if(arg.indexOf("[")==0||arg.indexOf("{")=="0"){try{input=eval(arg)}catch(err){input=arg}}else{input=arg}}else{input=arg}var config;switch(jwplayer.utils.typeOf(input)){case"object":config=input;break;case"array":config={playlist:input};break;default:config={file:input};break}_model.playlist=new jwplayer.html5.playlist(config);_model.item=_model.config.item>=0?_model.config.item:0;if(!_model.playlist[0].provider&&_model.playlist[0].file){_loadExternal(_model.playlist[0].file)}else{_loadComplete()}};function _getShuffleItem(){var result=null;if(_model.playlist.length>1){while(!jwplayer.utils.exists(result)){result=Math.floor(Math.random()*_model.playlist.length);if(result==_model.item){result=null}}}else{result=0}return result}function forward(evt){switch(evt.type){case jwplayer.api.events.JWPLAYER_MEDIA_LOADED:_container=_media.getDisplayElement();break;case jwplayer.api.events.JWPLAYER_MEDIA_MUTE:this.mute=evt.mute;break;case jwplayer.api.events.JWPLAYER_MEDIA_VOLUME:this.volume=evt.volume;break}_eventDispatcher.sendEvent(evt.type,evt)}var _mediaProviders={};_model.setActiveMediaProvider=function(playlistItem){if(playlistItem.provider=="audio"){playlistItem.provider="sound"}var provider=playlistItem.provider;var current=_media?_media.getDisplayElement():null;if(provider=="sound"||provider=="http"||provider==""){provider="video"}if(!jwplayer.utils.exists(_mediaProviders[provider])){switch(provider){case"video":_media=new jwplayer.html5.mediavideo(_model,current?current:_container);break;case"youtube":_media=new jwplayer.html5.mediayoutube(_model,current?current:_container);break}if(!jwplayer.utils.exists(_media)){return false}_media.addGlobalListener(forward);_mediaProviders[provider]=_media}else{if(_media!=_mediaProviders[provider]){if(_media){_media.stop()}_media=_mediaProviders[provider]}}return true};_model.getMedia=function(){return _media};_model.seek=function(pos){_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_MEDIA_SEEK,{position:_model.position,offset:pos});return _media.seek(pos)};_model.setVolume=function(newVol){_utils.saveCookie("volume",newVol);_model.volume=newVol};_model.setMute=function(state){_utils.saveCookie("mute",state);_model.mute=state};_model.setupPlugins=function(){if(!jwplayer.utils.exists(_model.plugins)||!jwplayer.utils.exists(_model.plugins.order)||_model.plugins.order.length==0){jwplayer.utils.log("No plugins to set up");return _model}for(var i=0;i<_model.plugins.order.length;i++){try{var pluginName=_model.plugins.order[i];if(jwplayer.utils.exists(jwplayer.html5[pluginName])){if(pluginName=="playlist"){_model.plugins.object[pluginName]=new jwplayer.html5.playlistcomponent(_api,_model.plugins.config[pluginName])}else{_model.plugins.object[pluginName]=new jwplayer.html5[pluginName](_api,_model.plugins.config[pluginName])}}else{_model.plugins.order.splice(plugin,plugin+1)}if(typeof _model.plugins.object[pluginName].addGlobalListener=="function"){_model.plugins.object[pluginName].addGlobalListener(forward)}}catch(err){jwplayer.utils.log("Could not setup "+pluginName)}}};return _model}})(jwplayer);(function(a){a.html5.playlist=function(b){var d=[];if(b.playlist&&b.playlist instanceof Array&&b.playlist.length>0){for(var c in b.playlist){if(!isNaN(parseInt(c))){d.push(new a.html5.playlistitem(b.playlist[c]))}}}else{d.push(new a.html5.playlistitem(b))}return d}})(jwplayer);(function(a){var c={size:180,position:a.html5.view.positions.NONE,itemheight:60,thumbs:true,fontcolor:"#000000",overcolor:"",activecolor:"",backgroundcolor:"#f8f8f8",font:"_sans",fontsize:"",fontstyle:"",fontweight:""};var b={_sans:"Arial, Helvetica, sans-serif",_serif:"Times, Times New Roman, serif",_typewriter:"Courier New, Courier, monospace"};_utils=a.utils;_css=_utils.css;_hide=function(d){_css(d,{display:"none"})};_show=function(d){_css(d,{display:"block"})};a.html5.playlistcomponent=function(r,C){var x=r;var e=a.utils.extend({},c,x.skin.getComponentSettings("playlist"),C);if(e.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[e.position]=="undefined"){return}var y;var l;var D;var d;var g;var f;var k=-1;var h={background:undefined,item:undefined,itemOver:undefined,itemImage:undefined,itemActive:undefined};this.getDisplayElement=function(){return y};this.resize=function(G,E){l=G;D=E;if(x.jwGetFullscreen()){_hide(y)}else{var F={display:"block",width:l,height:D};_css(y,F)}};this.show=function(){_show(y)};this.hide=function(){_hide(y)};function j(){y=document.createElement("div");y.id=x.id+"_jwplayer_playlistcomponent";y.style.overflow="hidden";switch(e.position){case a.html5.view.positions.RIGHT:case a.html5.view.positions.LEFT:y.style.width=e.size+"px";break;case a.html5.view.positions.TOP:case a.html5.view.positions.BOTTOM:y.style.height=e.size+"px";break}B();if(h.item){e.itemheight=h.item.height}y.style.backgroundColor="#C6C6C6";x.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,s);x.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,v);x.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,m)}function p(){var E=document.createElement("ul");_css(E,{width:y.style.width,minWidth:y.style.width,height:y.style.height,backgroundColor:e.backgroundcolor,backgroundImage:h.background?"url("+h.background.src+")":"",color:e.fontcolor,listStyle:"none",margin:0,padding:0,fontFamily:b[e.font]?b[e.font]:b._sans,fontSize:(e.fontsize?e.fontsize:11)+"px",fontStyle:e.fontstyle,fontWeight:e.fontweight,overflowY:"auto"});return E}function z(E){return function(){var F=f.getElementsByClassName("item")[E];var G=e.fontcolor;var H=h.item?"url("+h.item.src+")":"";if(E==x.jwGetPlaylistIndex()){if(e.activecolor!==""){G=e.activecolor}if(h.itemActive){H="url("+h.itemActive.src+")"}}_css(F,{color:e.overcolor!==""?e.overcolor:G,backgroundImage:h.itemOver?"url("+h.itemOver.src+")":H})}}function o(E){return function(){var F=f.getElementsByClassName("item")[E];var G=e.fontcolor;var H=h.item?"url("+h.item.src+")":"";if(E==x.jwGetPlaylistIndex()){if(e.activecolor!==""){G=e.activecolor}if(h.itemActive){H="url("+h.itemActive.src+")"}}_css(F,{color:G,backgroundImage:H})}}function q(J){var Q=d[J];var P=document.createElement("li");P.className="item";_css(P,{height:e.itemheight,display:"block",cursor:"pointer",backgroundImage:h.item?"url("+h.item.src+")":"",backgroundSize:"100% "+e.itemheight+"px"});P.onmouseover=z(J);P.onmouseout=o(J);var K=document.createElement("div");var G=new Image();var L=0;var M=0;var N=0;if(w()&&(Q.image||Q["playlist.image"]||h.itemImage)){G.className="image";if(h.itemImage){L=(e.itemheight-h.itemImage.height)/2;M=h.itemImage.width;N=h.itemImage.height}else{M=e.itemheight*4/3;N=e.itemheight}_css(K,{height:N,width:M,"float":"left",styleFloat:"left",cssFloat:"left",margin:"0 5px 0 0",background:"black",overflow:"hidden",margin:L+"px",position:"relative"});_css(G,{position:"relative"});K.appendChild(G);G.onload=function(){a.utils.stretch(a.utils.stretching.FILL,G,M,N,this.naturalWidth,this.naturalHeight)};if(Q["playlist.image"]){G.src=Q["playlist.image"]}else{if(Q.image){G.src=Q.image}else{if(h.itemImage){G.src=h.itemImage.src}}}P.appendChild(K)}var F=l-M-L*2;if(D<e.itemheight*d.length){F-=15}var E=document.createElement("div");_css(E,{position:"relative",height:"100%",overflow:"hidden"});var H=document.createElement("span");if(Q.duration>0){H.className="duration";_css(H,{fontSize:(e.fontsize?e.fontsize:11)+"px",fontWeight:(e.fontweight?e.fontweight:"bold"),width:"40px",height:e.fontsize?e.fontsize+10:20,lineHeight:24,"float":"right",styleFloat:"right",cssFloat:"right"});H.innerHTML=_utils.timeFormat(Q.duration);E.appendChild(H)}var O=document.createElement("span");O.className="title";_css(O,{padding:"5px 5px 0 "+(L?0:"5px"),height:e.fontsize?e.fontsize+10:20,lineHeight:e.fontsize?e.fontsize+10:20,overflow:"hidden","float":"left",styleFloat:"left",cssFloat:"left",width:((Q.duration>0)?F-50:F)-10+"px",fontSize:(e.fontsize?e.fontsize:13)+"px",fontWeight:(e.fontweight?e.fontweight:"bold")});O.innerHTML=Q?Q.title:"";E.appendChild(O);if(Q.description){var I=document.createElement("span");I.className="description";_css(I,{display:"block","float":"left",styleFloat:"left",cssFloat:"left",margin:0,paddingLeft:O.style.paddingLeft,paddingRight:O.style.paddingRight,lineHeight:(e.fontsize?e.fontsize+4:16)+"px",overflow:"hidden",position:"relative"});I.innerHTML=Q.description;E.appendChild(I)}P.appendChild(E);return P}function s(F){y.innerHTML="";d=t();if(!d){return}items=[];f=p();for(var G=0;G<d.length;G++){var E=q(G);E.onclick=A(G);f.appendChild(E);items.push(E)}k=x.jwGetPlaylistIndex();o(k)();y.appendChild(f);if(_utils.isIOS()&&window.iScroll){f.style.height=e.itemheight*d.length+"px";var H=new iScroll(y.id)}}function t(){var F=x.jwGetPlaylist();var G=[];for(var E=0;E<F.length;E++){if(!F[E]["ova.hidden"]){G.push(F[E])}}return G}function A(E){return function(){x.jwPlaylistItem(E);x.jwPlay(true)}}function n(){f.scrollTop=x.jwGetPlaylistIndex()*e.itemheight}function w(){return e.thumbs.toString().toLowerCase()=="true"}function v(E){if(k>=0){o(k)();k=E.index}o(E.index)();n()}function m(){if(e.position==a.html5.view.positions.OVER){switch(x.jwGetState()){case a.api.events.state.IDLE:_show(y);break;default:_hide(y);break}}}function B(){for(var E in h){h[E]=u(E)}}function u(E){return x.skin.getSkinElement("playlist",E)}j();return this}})(jwplayer);(function(b){b.html5.playlistitem=function(d){var e={author:"",date:"",description:"",image:"",link:"",mediaid:"",tags:"",title:"",provider:"",file:"",streamer:"",duration:-1,start:0,currentLevel:-1,levels:[]};var c=b.utils.extend({},e,d);if(c.type){c.provider=c.type;delete c.type}if(c.levels.length===0){c.levels[0]=new b.html5.playlistitemlevel(c)}if(!c.provider){c.provider=a(c.levels[0])}else{c.provider=c.provider.toLowerCase()}return c};function a(e){if(b.utils.isYouTube(e.file)){return"youtube"}else{var f=b.utils.extension(e.file);var c;if(f&&b.utils.extensionmap[f]){if(f=="m3u8"){return"video"}c=b.utils.extensionmap[f].html5}else{if(e.type){c=e.type}}if(c){var d=c.split("/")[0];if(d=="audio"){return"sound"}else{if(d=="video"){return d}}}}return""}})(jwplayer);(function(a){a.html5.playlistitemlevel=function(b){var d={file:"",streamer:"",bitrate:0,width:0};for(var c in d){if(a.utils.exists(b[c])){d[c]=b[c]}}return d}})(jwplayer);(function(a){a.html5.playlistloader=function(){var c=new a.html5.eventdispatcher();a.utils.extend(this,c);this.load=function(e){a.utils.ajax(e,d,b)};function d(g){var f=[];try{var f=a.utils.parsers.rssparser.parse(g.responseXML.firstChild);c.sendEvent(a.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:new a.html5.playlist({playlist:f})})}catch(h){b("Could not parse the playlist")}}function b(e){c.sendEvent(a.api.events.JWPLAYER_ERROR,{message:e?e:"Could not load playlist an unknown reason."})}}})(jwplayer);(function(a){a.html5.skin=function(){var b={};var c=false;this.load=function(d,e){new a.html5.skinloader(d,function(f){c=true;b=f;e()},function(){new a.html5.skinloader("",function(f){c=true;b=f;e()})})};this.getSkinElement=function(d,e){if(c){try{return b[d].elements[e]}catch(f){a.utils.log("No such skin component / element: ",[d,e])}}return null};this.getComponentSettings=function(d){if(c&&b&&b[d]){return b[d].settings}return null};this.getComponentLayout=function(d){if(c){return b[d].layout}return null}}})(jwplayer);(function(a){a.html5.skinloader=function(f,p,k){var o={};var c=p;var l=k;var e=true;var j;var n=f;var s=false;function m(){if(typeof n!="string"||n===""){d(a.html5.defaultSkin().xml)}else{a.utils.ajax(a.utils.getAbsolutePath(n),function(t){try{if(a.utils.exists(t.responseXML)){d(t.responseXML);return}}catch(u){h()}d(a.html5.defaultSkin().xml)},function(t){d(a.html5.defaultSkin().xml)})}}function d(y){var E=y.getElementsByTagName("component");if(E.length===0){return}for(var H=0;H<E.length;H++){var C=E[H].getAttribute("name");var B={settings:{},elements:{},layout:{}};o[C]=B;var G=E[H].getElementsByTagName("elements")[0].getElementsByTagName("element");for(var F=0;F<G.length;F++){b(G[F],C)}var z=E[H].getElementsByTagName("settings")[0];if(z&&z.childNodes.length>0){var K=z.getElementsByTagName("setting");for(var P=0;P<K.length;P++){var Q=K[P].getAttribute("name");var I=K[P].getAttribute("value");var x=/color$/.test(Q)?"color":null;o[C].settings[Q]=a.utils.typechecker(I,x)}}var L=E[H].getElementsByTagName("layout")[0];if(L&&L.childNodes.length>0){var M=L.getElementsByTagName("group");for(var w=0;w<M.length;w++){var A=M[w];o[C].layout[A.getAttribute("position")]={elements:[]};for(var O=0;O<A.attributes.length;O++){var D=A.attributes[O];o[C].layout[A.getAttribute("position")][D.name]=D.value}var N=A.getElementsByTagName("*");for(var v=0;v<N.length;v++){var t=N[v];o[C].layout[A.getAttribute("position")].elements.push({type:t.tagName});for(var u=0;u<t.attributes.length;u++){var J=t.attributes[u];o[C].layout[A.getAttribute("position")].elements[v][J.name]=J.value}if(!a.utils.exists(o[C].layout[A.getAttribute("position")].elements[v].name)){o[C].layout[A.getAttribute("position")].elements[v].name=t.tagName}}}}e=false;r()}}function r(){clearInterval(j);if(!s){j=setInterval(function(){q()},100)}}function b(y,x){var w=new Image();var t=y.getAttribute("name");var v=y.getAttribute("src");var A;if(v.indexOf("data:image/png;base64,")===0){A=v}else{var u=a.utils.getAbsolutePath(n);var z=u.substr(0,u.lastIndexOf("/"));A=[z,x,v].join("/")}o[x].elements[t]={height:0,width:0,src:"",ready:false,image:w};w.onload=function(B){g(w,t,x)};w.onerror=function(B){s=true;r();l()};w.src=A}function h(){for(var u in o){var w=o[u];for(var t in w.elements){var x=w.elements[t];var v=x.image;v.onload=null;v.onerror=null;delete x.image;delete w.elements[t]}delete o[u]}}function q(){for(var t in o){if(t!="properties"){for(var u in o[t].elements){if(!o[t].elements[u].ready){return}}}}if(e===false){clearInterval(j);c(o)}}function g(t,v,u){if(o[u]&&o[u].elements[v]){o[u].elements[v].height=t.height;o[u].elements[v].width=t.width;o[u].elements[v].src=t.src;o[u].elements[v].ready=true;r()}else{a.utils.log("Loaded an image for a missing element: "+u+"."+v)}}m()}})(jwplayer);(function(a){a.html5.api=function(c,p){var n={};var g=document.createElement("div");c.parentNode.replaceChild(g,c);g.id=c.id;n.version=a.version;n.id=g.id;var m=new a.html5.model(n,g,p);var k=new a.html5.view(n,g,m);var l=new a.html5.controller(n,g,m,k);n.skin=new a.html5.skin();n.jwPlay=function(q){if(typeof q=="undefined"){f()}else{if(q.toString().toLowerCase()=="true"){l.play()}else{l.pause()}}};n.jwPause=function(q){if(typeof q=="undefined"){f()}else{if(q.toString().toLowerCase()=="true"){l.pause()}else{l.play()}}};function f(){if(m.state==a.api.events.state.PLAYING||m.state==a.api.events.state.BUFFERING){l.pause()}else{l.play()}}n.jwStop=l.stop;n.jwSeek=l.seek;n.jwPlaylistItem=function(q){if(d){if(d.playlistClickable()){d.jwInstreamDestroy();return l.item(q)}}else{return l.item(q)}};n.jwPlaylistNext=l.next;n.jwPlaylistPrev=l.prev;n.jwResize=l.resize;n.jwLoad=l.load;n.jwDetachMedia=l.detachMedia;n.jwAttachMedia=l.attachMedia;function j(q){return function(){return m[q]}}function e(q,s,r){return function(){var t=m.plugins.object[q];if(t&&t[s]&&typeof t[s]=="function"){t[s].apply(t,r)}}}n.jwGetPlaylistIndex=j("item");n.jwGetPosition=j("position");n.jwGetDuration=j("duration");n.jwGetBuffer=j("buffer");n.jwGetWidth=j("width");n.jwGetHeight=j("height");n.jwGetFullscreen=j("fullscreen");n.jwSetFullscreen=l.setFullscreen;n.jwGetVolume=j("volume");n.jwSetVolume=l.setVolume;n.jwGetMute=j("mute");n.jwSetMute=l.setMute;n.jwGetStretching=function(){return m.stretching.toUpperCase()};n.jwGetState=j("state");n.jwGetVersion=function(){return n.version};n.jwGetPlaylist=function(){return m.playlist};n.jwAddEventListener=l.addEventListener;n.jwRemoveEventListener=l.removeEventListener;n.jwSendEvent=l.sendEvent;n.jwDockSetButton=function(t,q,r,s){if(m.plugins.object.dock&&m.plugins.object.dock.setButton){m.plugins.object.dock.setButton(t,q,r,s)}};n.jwControlbarShow=e("controlbar","show");n.jwControlbarHide=e("controlbar","hide");n.jwDockShow=e("dock","show");n.jwDockHide=e("dock","hide");n.jwDisplayShow=e("display","show");n.jwDisplayHide=e("display","hide");var d;n.jwLoadInstream=function(r,q){if(!d){d=new a.html5.instream(n,m,k,l)}setTimeout(function(){d.load(r,q)},10)};n.jwInstreamDestroy=function(){if(d){d.jwInstreamDestroy()}};n.jwInstreamAddEventListener=o("jwInstreamAddEventListener");n.jwInstreamRemoveEventListener=o("jwInstreamRemoveEventListener");n.jwInstreamGetState=o("jwInstreamGetState");n.jwInstreamGetDuration=o("jwInstreamGetDuration");n.jwInstreamGetPosition=o("jwInstreamGetPosition");n.jwInstreamPlay=o("jwInstreamPlay");n.jwInstreamPause=o("jwInstreamPause");n.jwInstreamSeek=o("jwInstreamSeek");function o(q){return function(){if(d&&typeof d[q]=="function"){return d[q].apply(this,arguments)}else{_utils.log("Could not call instream method - instream API not initialized")}}}n.jwGetLevel=function(){};n.jwGetBandwidth=function(){};n.jwGetLockState=function(){};n.jwLock=function(){};n.jwUnlock=function(){};function b(){if(m.config.playlistfile){m.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,h);m.loadPlaylist(m.config.playlistfile)}else{if(typeof m.config.playlist=="string"){m.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,h);m.loadPlaylist(m.config.playlist)}else{m.loadPlaylist(m.config);setTimeout(h,25)}}}function h(q){m.removeEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,h);m.setupPlugins();k.setup();var q={id:n.id,version:n.version};l.playerReady(q)}if(m.config.chromeless&&!a.utils.isIOS()){b()}else{n.skin.load(m.config.skin,b)}return n}})(jwplayer)}; \ No newline at end of file +"undefined"==typeof jwplayer&&(jwplayer=function(d){if(jwplayer.api)return jwplayer.api.selectPlayer(d)},jwplayer.version="6.3.3242",jwplayer.vid=document.createElement("video"),jwplayer.audio=document.createElement("audio"),jwplayer.source=document.createElement("source"),function(d){function a(b){return function(){return e(b)}}var h=document,g=window,c=navigator,b=d.utils=function(){};b.exists=function(b){switch(typeof b){case "string":return 0<b.length;case "object":return null!==b;case "undefined":return!1}return!0}; +b.styleDimension=function(b){return b+(0<b.toString().indexOf("%")?"":"px")};b.getAbsolutePath=function(a,e){b.exists(e)||(e=h.location.href);if(b.exists(a)){var c;if(b.exists(a)){c=a.indexOf("://");var g=a.indexOf("?");c=0<c&&(0>g||g>c)}else c=void 0;if(c)return a;c=e.substring(0,e.indexOf("://")+3);var g=e.substring(c.length,e.indexOf("/",c.length+1)),k;0===a.indexOf("/")?k=a.split("/"):(k=e.split("?")[0],k=k.substring(c.length+g.length+1,k.lastIndexOf("/")),k=k.split("/").concat(a.split("/"))); +for(var f=[],d=0;d<k.length;d++)k[d]&&(b.exists(k[d])&&"."!=k[d])&&(".."==k[d]?f.pop():f.push(k[d]));return c+g+"/"+f.join("/")}};b.extend=function(){var a=b.extend.arguments;if(1<a.length){for(var e=1;e<a.length;e++)for(var c in a[e])try{b.exists(a[e][c])&&(a[0][c]=a[e][c])}catch(k){}return a[0]}return null};b.log=function(b,a){"undefined"!=typeof console&&"undefined"!=typeof console.log&&(a?console.log(b,a):console.log(b))};var e=b.userAgentMatch=function(b){return null!==c.userAgent.toLowerCase().match(b)}; +b.isIE=a(/msie/i);b.isFF=a(/firefox/i);b.isChrome=a(/chrome/i);b.isIOS=a(/iP(hone|ad|od)/i);b.isIPod=a(/iP(hone|od)/i);b.isIPad=a(/iPad/i);b.isSafari602=a(/Macintosh.*Mac OS X 10_8.*6\.0\.\d* Safari/i);b.isAndroid=function(b){return b?e(RegExp("android.*"+b,"i")):e(/android/i)};b.isMobile=function(){return b.isIOS()||b.isAndroid()};b.saveCookie=function(b,a){h.cookie="jwplayer."+b+"\x3d"+a+"; path\x3d/"};b.getCookies=function(){for(var b={},a=h.cookie.split("; "),e=0;e<a.length;e++){var c=a[e].split("\x3d"); +0==c[0].indexOf("jwplayer.")&&(b[c[0].substring(9,c[0].length)]=c[1])}return b};b.typeOf=function(b){var a=typeof b;return"object"===a?!b?"null":b instanceof Array?"array":a:a};b.translateEventResponse=function(a,e){var c=b.extend({},e);a==d.events.JWPLAYER_FULLSCREEN&&!c.fullscreen?(c.fullscreen="true"==c.message?!0:!1,delete c.message):"object"==typeof c.data?(c=b.extend(c,c.data),delete c.data):"object"==typeof c.metadata&&b.deepReplaceKeyName(c.metadata,["__dot__","__spc__","__dsh__","__default__"], +["."," ","-","default"]);var k=["position","duration","offset"],g;for(g in k)c[k[g]]&&(c[k[g]]=Math.round(1E3*c[k[g]])/1E3);return c};b.flashVersion=function(){if(b.isAndroid())return 0;var a=c.plugins,e;try{if("undefined"!==a&&(e=a["Shockwave Flash"]))return parseInt(e.description.replace(/\D+(\d+)\..*/,"$1"))}catch(k){}if("undefined"!=typeof g.ActiveXObject)try{if(e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash"))return parseInt(e.GetVariable("$version").split(" ")[1].split(",")[0])}catch(d){}return 0}; +b.getScriptPath=function(b){for(var a=h.getElementsByTagName("script"),e=0;e<a.length;e++){var c=a[e].src;if(c&&0<=c.indexOf(b))return c.substr(0,c.indexOf(b))}return""};b.deepReplaceKeyName=function(b,a,e){switch(d.utils.typeOf(b)){case "array":for(var c=0;c<b.length;c++)b[c]=d.utils.deepReplaceKeyName(b[c],a,e);break;case "object":for(var k in b){var f;if(a instanceof Array&&e instanceof Array)if(a.length!=e.length)continue;else f=a;else f=[a];for(var g=k,c=0;c<f.length;c++)g=g.replace(RegExp(a[c], +"g"),e[c]);b[g]=d.utils.deepReplaceKeyName(b[k],a,e);k!=g&&delete b[k]}}return b};var k=b.pluginPathType={ABSOLUTE:0,RELATIVE:1,CDN:2};b.getPluginPathType=function(a){if("string"==typeof a){a=a.split("?")[0];var e=a.indexOf("://");if(0<e)return k.ABSOLUTE;var c=a.indexOf("/");a=b.extension(a);return 0>e&&0>c&&(!a||!isNaN(a))?k.CDN:k.RELATIVE}};b.getPluginName=function(a){return a.replace(/^(.*\/)?([^-]*)-?.*\.(swf|js)$/,"$2")};b.getPluginVersion=function(a){return a.replace(/[^-]*-?([^\.]*).*$/,"$1")}; +b.isYouTube=function(a){return-1<a.indexOf("youtube.com")||-1<a.indexOf("youtu.be")};b.isRtmp=function(a,b){return 0==a.indexOf("rtmp")||"rtmp"==b};b.foreach=function(a,b){for(var e in a)a.hasOwnProperty(e)&&b(e)};b.isHTTPS=function(){return 0==g.location.href.indexOf("https")};b.repo=function(){var a="http://p.jwpcdn.com/"+d.version.split(/\W/).splice(0,2).join("/")+"/";try{b.isHTTPS()&&(a=a.replace("http://","https://ssl."))}catch(e){}return a}}(jwplayer),function(d){var a="video/",h={mp4:a+"mp4", +vorbis:"audio/ogg",ogg:a+"ogg",webm:a+"webm",aac:"audio/mp4",mp3:"audio/mpeg",hls:"application/vnd.apple.mpegurl"},g={mp4:h.mp4,f4v:h.mp4,m4v:h.mp4,mov:h.mp4,m4a:h.aac,f4a:h.aac,aac:h.aac,mp3:h.mp3,ogv:h.ogg,ogg:h.vorbis,oga:h.vorbis,webm:h.webm,m3u8:h.hls,hls:h.hls},a="video",a={flv:a,f4v:a,mov:a,m4a:a,m4v:a,mp4:a,aac:a,f4a:a,mp3:"sound",smil:"rtmp",m3u8:"hls",hls:"hls"},c=d.extensionmap={},b;for(b in g)c[b]={html5:g[b]};for(b in a)c[b]||(c[b]={}),c[b].flash=a[b];c.types=h;c.mimeType=function(a){for(var b in h)if(h[b]== +a)return b};c.extType=function(a){return c.mimeType(g[a])}}(jwplayer.utils),function(d){var a=d.loaderstatus={NEW:0,LOADING:1,ERROR:2,COMPLETE:3},h=document;d.scriptloader=function(g){function c(){e=a.ERROR;l.sendEvent(k.ERROR)}function b(){e=a.COMPLETE;l.sendEvent(k.COMPLETE)}var e=a.NEW,k=jwplayer.events,l=new k.eventdispatcher;d.extend(this,l);this.load=function(){var l=d.scriptloader.loaders[g];if(l&&(l.getStatus()==a.NEW||l.getStatus()==a.LOADING))l.addEventListener(k.ERROR,c),l.addEventListener(k.COMPLETE, +b);else if(d.scriptloader.loaders[g]=this,e==a.NEW){e=a.LOADING;var n=h.createElement("script");n.addEventListener?(n.onload=b,n.onerror=c):n.readyState&&(n.onreadystatechange=function(){("loaded"==n.readyState||"complete"==n.readyState)&&b()});h.getElementsByTagName("head")[0].appendChild(n);n.src=g}};this.getStatus=function(){return e}};d.scriptloader.loaders={}}(jwplayer.utils),function(d){d.trim=function(a){return a.replace(/^\s*/,"").replace(/\s*$/,"")};d.pad=function(a,d,g){for(g||(g="0");a.length< +d;)a=g+a;return a};d.xmlAttribute=function(a,d){for(var g=0;g<a.attributes.length;g++)if(a.attributes[g].name&&a.attributes[g].name.toLowerCase()==d.toLowerCase())return a.attributes[g].value.toString();return""};d.extension=function(a){if(!a||"rtmp"==a.substr(0,4))return"";a=a.substring(a.lastIndexOf("/")+1,a.length).split("?")[0].split("#")[0];if(-1<a.lastIndexOf("."))return a.substr(a.lastIndexOf(".")+1,a.length).toLowerCase()};d.stringToColor=function(a){a=a.replace(/(#|0x)?([0-9A-F]{3,6})$/gi, +"$2");3==a.length&&(a=a.charAt(0)+a.charAt(0)+a.charAt(1)+a.charAt(1)+a.charAt(2)+a.charAt(2));return parseInt(a,16)}}(jwplayer.utils),function(d){d.key=function(a){var h,g,c;this.edition=function(){return c&&c.getTime()<(new Date).getTime()?"invalid":h};this.token=function(){return g};d.exists(a)||(a="");try{a=d.tea.decrypt(a,"36QXq4W@GSBV^teR");var b=a.split("/");(h=b[0])||(h="free");g=b[1];b[2]&&0<parseInt(b[2])&&(c=new Date,c.setTime(String(b[2])))}catch(e){h="invalid"}}}(jwplayer.utils),function(d){var a= +d.tea={};a.encrypt=function(c,b){if(0==c.length)return"";var e=a.strToLongs(g.encode(c));1>=e.length&&(e[1]=0);for(var k=a.strToLongs(g.encode(b).slice(0,16)),l=e.length,d=e[l-1],n=e[0],q,j=Math.floor(6+52/l),f=0;0<j--;){f+=2654435769;q=f>>>2&3;for(var r=0;r<l;r++)n=e[(r+1)%l],d=(d>>>5^n<<2)+(n>>>3^d<<4)^(f^n)+(k[r&3^q]^d),d=e[r]+=d}e=a.longsToStr(e);return h.encode(e)};a.decrypt=function(c,b){if(0==c.length)return"";for(var e=a.strToLongs(h.decode(c)),k=a.strToLongs(g.encode(b).slice(0,16)),d=e.length, +m=e[d-1],n=e[0],q,j=2654435769*Math.floor(6+52/d);0!=j;){q=j>>>2&3;for(var f=d-1;0<=f;f--)m=e[0<f?f-1:d-1],m=(m>>>5^n<<2)+(n>>>3^m<<4)^(j^n)+(k[f&3^q]^m),n=e[f]-=m;j-=2654435769}e=a.longsToStr(e);e=e.replace(/\0+$/,"");return g.decode(e)};a.strToLongs=function(a){for(var b=Array(Math.ceil(a.length/4)),e=0;e<b.length;e++)b[e]=a.charCodeAt(4*e)+(a.charCodeAt(4*e+1)<<8)+(a.charCodeAt(4*e+2)<<16)+(a.charCodeAt(4*e+3)<<24);return b};a.longsToStr=function(a){for(var b=Array(a.length),e=0;e<a.length;e++)b[e]= +String.fromCharCode(a[e]&255,a[e]>>>8&255,a[e]>>>16&255,a[e]>>>24&255);return b.join("")};var h={code:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\x3d",encode:function(a,b){var e,k,d,m,n=[],q="",j,f,r=h.code;f=("undefined"==typeof b?0:b)?g.encode(a):a;j=f.length%3;if(0<j)for(;3>j++;)q+="\x3d",f+="\x00";for(j=0;j<f.length;j+=3)e=f.charCodeAt(j),k=f.charCodeAt(j+1),d=f.charCodeAt(j+2),m=e<<16|k<<8|d,e=m>>18&63,k=m>>12&63,d=m>>6&63,m&=63,n[j/3]=r.charAt(e)+r.charAt(k)+r.charAt(d)+ +r.charAt(m);n=n.join("");return n=n.slice(0,n.length-q.length)+q},decode:function(a,b){b="undefined"==typeof b?!1:b;var e,k,d,m,n,q=[],j,f=h.code;j=b?g.decode(a):a;for(var r=0;r<j.length;r+=4)e=f.indexOf(j.charAt(r)),k=f.indexOf(j.charAt(r+1)),m=f.indexOf(j.charAt(r+2)),n=f.indexOf(j.charAt(r+3)),d=e<<18|k<<12|m<<6|n,e=d>>>16&255,k=d>>>8&255,d&=255,q[r/4]=String.fromCharCode(e,k,d),64==n&&(q[r/4]=String.fromCharCode(e,k)),64==m&&(q[r/4]=String.fromCharCode(e));m=q.join("");return b?g.decode(m):m}}, +g={encode:function(a){a=a.replace(/[\u0080-\u07ff]/g,function(a){a=a.charCodeAt(0);return String.fromCharCode(192|a>>6,128|a&63)});return a=a.replace(/[\u0800-\uffff]/g,function(a){a=a.charCodeAt(0);return String.fromCharCode(224|a>>12,128|a>>6&63,128|a&63)})},decode:function(a){a=a.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,function(a){a=(a.charCodeAt(0)&15)<<12|(a.charCodeAt(1)&63)<<6|a.charCodeAt(2)&63;return String.fromCharCode(a)});return a=a.replace(/[\u00c0-\u00df][\u0080-\u00bf]/g, +function(a){a=(a.charCodeAt(0)&31)<<6|a.charCodeAt(1)&63;return String.fromCharCode(a)})}}}(jwplayer.utils),function(d){d.events={COMPLETE:"COMPLETE",ERROR:"ERROR",API_READY:"jwplayerAPIReady",JWPLAYER_READY:"jwplayerReady",JWPLAYER_FULLSCREEN:"jwplayerFullscreen",JWPLAYER_RESIZE:"jwplayerResize",JWPLAYER_ERROR:"jwplayerError",JWPLAYER_MEDIA_BEFOREPLAY:"jwplayerMediaBeforePlay",JWPLAYER_MEDIA_BEFORECOMPLETE:"jwplayerMediaBeforeComplete",JWPLAYER_COMPONENT_SHOW:"jwplayerComponentShow",JWPLAYER_COMPONENT_HIDE:"jwplayerComponentHide", +JWPLAYER_MEDIA_BUFFER:"jwplayerMediaBuffer",JWPLAYER_MEDIA_BUFFER_FULL:"jwplayerMediaBufferFull",JWPLAYER_MEDIA_ERROR:"jwplayerMediaError",JWPLAYER_MEDIA_LOADED:"jwplayerMediaLoaded",JWPLAYER_MEDIA_COMPLETE:"jwplayerMediaComplete",JWPLAYER_MEDIA_SEEK:"jwplayerMediaSeek",JWPLAYER_MEDIA_TIME:"jwplayerMediaTime",JWPLAYER_MEDIA_VOLUME:"jwplayerMediaVolume",JWPLAYER_MEDIA_META:"jwplayerMediaMeta",JWPLAYER_MEDIA_MUTE:"jwplayerMediaMute",JWPLAYER_MEDIA_LEVELS:"jwplayerMediaLevels",JWPLAYER_MEDIA_LEVEL_CHANGED:"jwplayerMediaLevelChanged", +JWPLAYER_CAPTIONS_CHANGED:"jwplayerCaptionsChanged",JWPLAYER_CAPTIONS_LIST:"jwplayerCaptionsList",JWPLAYER_PLAYER_STATE:"jwplayerPlayerState",state:{BUFFERING:"BUFFERING",IDLE:"IDLE",PAUSED:"PAUSED",PLAYING:"PLAYING"},JWPLAYER_PLAYLIST_LOADED:"jwplayerPlaylistLoaded",JWPLAYER_PLAYLIST_ITEM:"jwplayerPlaylistItem",JWPLAYER_PLAYLIST_COMPLETE:"jwplayerPlaylistComplete",JWPLAYER_DISPLAY_CLICK:"jwplayerViewClick",JWPLAYER_CONTROLS:"jwplayerViewControls",JWPLAYER_INSTREAM_CLICK:"jwplayerInstreamClicked", +JWPLAYER_INSTREAM_DESTROYED:"jwplayerInstreamDestroyed"}}(jwplayer),function(d){var a=jwplayer.utils;d.eventdispatcher=function(d,g){var c,b;this.resetEventListeners=function(){c={};b=[]};this.resetEventListeners();this.addEventListener=function(b,k,d){try{a.exists(c[b])||(c[b]=[]),"string"==a.typeOf(k)&&(k=(new Function("return "+k))()),c[b].push({listener:k,count:d})}catch(g){a.log("error",g)}return!1};this.removeEventListener=function(b,d){if(c[b]){try{for(var g=0;g<c[b].length;g++)if(c[b][g].listener.toString()== +d.toString()){c[b].splice(g,1);break}}catch(h){a.log("error",h)}return!1}};this.addGlobalListener=function(e,c){try{"string"==a.typeOf(e)&&(e=(new Function("return "+e))()),b.push({listener:e,count:c})}catch(d){a.log("error",d)}return!1};this.removeGlobalListener=function(e){if(e){try{for(var c=0;c<b.length;c++)if(b[c].listener.toString()==e.toString()){b.splice(c,1);break}}catch(d){a.log("error",d)}return!1}};this.sendEvent=function(e,k){a.exists(k)||(k={});a.extend(k,{id:d,version:jwplayer.version, +type:e});g&&a.log(e,k);if("undefined"!=a.typeOf(c[e]))for(var l=0;l<c[e].length;l++){try{c[e][l].listener(k)}catch(m){a.log("There was an error while handling a listener: "+m.toString(),c[e][l].listener)}c[e][l]&&(1===c[e][l].count?delete c[e][l]:0<c[e][l].count&&(c[e][l].count-=1))}for(l=0;l<b.length;l++){try{b[l].listener(k)}catch(n){a.log("There was an error while handling a listener: "+n.toString(),b[l].listener)}b[l]&&(1===b[l].count?delete b[l]:0<b[l].count&&(b[l].count-=1))}}}}(jwplayer.events), +function(d){var a={},h={};d.plugins=function(){};d.plugins.loadPlugins=function(g,c){h[g]=new d.plugins.pluginloader(new d.plugins.model(a),c);return h[g]};d.plugins.registerPlugin=function(g,c,b,e){var k=d.utils.getPluginName(g);a[k]||(a[k]=new d.plugins.plugin(g));a[k].registerPlugin(g,c,b,e)}}(jwplayer),function(d){d.plugins.model=function(a){this.addPlugin=function(h){var g=d.utils.getPluginName(h);a[g]||(a[g]=new d.plugins.plugin(h));return a[g]};this.getPlugins=function(){return a}}}(jwplayer), +function(d){var a=jwplayer.utils,h=jwplayer.events;d.pluginmodes={FLASH:0,JAVASCRIPT:1,HYBRID:2};d.plugin=function(g){function c(){switch(a.getPluginPathType(g)){case a.pluginPathType.ABSOLUTE:return g;case a.pluginPathType.RELATIVE:return a.getAbsolutePath(g,window.location.href)}}function b(){q=setTimeout(function(){k=a.loaderstatus.COMPLETE;j.sendEvent(h.COMPLETE)},1E3)}function e(){k=a.loaderstatus.ERROR;j.sendEvent(h.ERROR)}var k=a.loaderstatus.NEW,l,m,n,q,j=new h.eventdispatcher;a.extend(this, +j);this.load=function(){if(k==a.loaderstatus.NEW)if(0<g.lastIndexOf(".swf"))l=g,k=a.loaderstatus.COMPLETE,j.sendEvent(h.COMPLETE);else if(a.getPluginPathType(g)==a.pluginPathType.CDN)k=a.loaderstatus.COMPLETE,j.sendEvent(h.COMPLETE);else{k=a.loaderstatus.LOADING;var f=new a.scriptloader(c());f.addEventListener(h.COMPLETE,b);f.addEventListener(h.ERROR,e);f.load()}};this.registerPlugin=function(b,e,c,d){q&&(clearTimeout(q),q=void 0);n=e;c&&d?(l=d,m=c):"string"==typeof c?l=c:"function"==typeof c?m=c: +!c&&!d&&(l=b);k=a.loaderstatus.COMPLETE;j.sendEvent(h.COMPLETE)};this.getStatus=function(){return k};this.getPluginName=function(){return a.getPluginName(g)};this.getFlashPath=function(){if(l)switch(a.getPluginPathType(l)){case a.pluginPathType.ABSOLUTE:return l;case a.pluginPathType.RELATIVE:return 0<g.lastIndexOf(".swf")?a.getAbsolutePath(l,window.location.href):a.getAbsolutePath(l,c())}return null};this.getJS=function(){return m};this.getTarget=function(){return n};this.getPluginmode=function(){if("undefined"!= +typeof l&&"undefined"!=typeof m)return d.pluginmodes.HYBRID;if("undefined"!=typeof l)return d.pluginmodes.FLASH;if("undefined"!=typeof m)return d.pluginmodes.JAVASCRIPT};this.getNewInstance=function(a,b,e){return new m(a,b,e)};this.getURL=function(){return g}}}(jwplayer.plugins),function(d){var a=d.utils,h=d.events;d.plugins.pluginloader=function(g,c){function b(){m?j.sendEvent(h.ERROR,{message:n}):l||(l=!0,k=a.loaderstatus.COMPLETE,j.sendEvent(h.COMPLETE))}function e(){q||b();if(!l&&!m){var e=0, +c=g.getPlugins(),f;for(f in q){var k=a.getPluginName(f),h=c[k],k=h.getJS(),j=h.getTarget(),h=h.getStatus();if(h==a.loaderstatus.LOADING||h==a.loaderstatus.NEW)e++;else if(k&&(!j||parseFloat(j)>parseFloat(d.version)))m=!0,n="Incompatible player version",b()}0==e&&b()}}var k=a.loaderstatus.NEW,l=!1,m=!1,n,q=c,j=new h.eventdispatcher;a.extend(this,j);this.setupPlugins=function(b,e,c){var f={length:0,plugins:{}},d=0,k={},h=g.getPlugins(),l;for(l in e.plugins){var j=a.getPluginName(l),m=h[j],B=m.getFlashPath(), +n=m.getJS(),q=m.getURL();B&&(f.plugins[B]=a.extend({},e.plugins[l]),f.plugins[B].pluginmode=m.getPluginmode(),f.length++);try{if(n&&e.plugins&&e.plugins[q]){var v=document.createElement("div");v.id=b.id+"_"+j;v.style.position="absolute";v.style.top=0;v.style.zIndex=d+10;k[j]=m.getNewInstance(b,a.extend({},e.plugins[q]),v);d++;b.onReady(c(k[j],v,!0));b.onResize(c(k[j],v))}}catch(C){a.log("ERROR: Failed to load "+j+".")}}b.plugins=k;return f};this.load=function(){if(!(a.exists(c)&&"object"!=a.typeOf(c))){k= +a.loaderstatus.LOADING;for(var b in c)if(a.exists(b)){var d=g.addPlugin(b);d.addEventListener(h.COMPLETE,e);d.addEventListener(h.ERROR,f)}d=g.getPlugins();for(b in d)d[b].load()}e()};var f=this.pluginFailed=function(){m||(m=!0,n="File not found",b())};this.getStatus=function(){return k}}}(jwplayer),function(d){d.playlist=function(a){var h=[];if("array"==d.utils.typeOf(a))for(var g=0;g<a.length;g++)h.push(new d.playlist.item(a[g]));else h.push(new d.playlist.item(a));return h}}(jwplayer),function(d){var a= +d.item=function(h){var g=jwplayer.utils,c=g.extend({},a.defaults,h);c.tracks=g.exists(h.tracks)?h.tracks:[];0==c.sources.length&&(c.sources=[new d.source(c)]);for(var b=0;b<c.sources.length;b++){var e=c.sources[b]["default"];c.sources[b]["default"]=e?"true"==e.toString():!1;c.sources[b]=new d.source(c.sources[b])}if(c.captions&&!g.exists(h.tracks)){for(h=0;h<c.captions.length;h++)c.tracks.push(c.captions[h]);delete c.captions}for(b=0;b<c.tracks.length;b++)c.tracks[b]=new d.track(c.tracks[b]);return c}; +a.defaults={description:"",image:"",mediaid:"",title:"",sources:[],tracks:[]}}(jwplayer.playlist),function(d){var a=jwplayer.utils,h={file:void 0,label:void 0,type:void 0,"default":void 0};d.source=function(d){var c=a.extend({},h),b;for(b in h)a.exists(d[b])&&(c[b]=d[b],delete d[b]);c.type&&0<c.type.indexOf("/")&&(c.type=a.extensionmap.mimeType(c.type));"m3u8"==c.type&&(c.type="hls");"smil"==c.type&&(c.type="rtmp");return c}}(jwplayer.playlist),function(d){var a=jwplayer.utils,h={file:void 0,label:void 0, +kind:"captions","default":!1};d.track=function(d){var c=a.extend({},h);d||(d={});for(var b in h)a.exists(d[b])&&(c[b]=d[b],delete d[b]);return c}}(jwplayer.playlist),function(d){var a=d.utils,h=d.events,g=document,c=d.embed=function(b){function e(a){l(n,p+a.message)}function k(){l(n,p+"No playable sources found")}function l(b,e){if(m.fallback){var c=b.style;c.backgroundColor="#000";c.color="#FFF";c.width=a.styleDimension(m.width);c.height=a.styleDimension(m.height);c.display="table";c.opacity=1;var c= +document.createElement("p"),d=c.style;d.verticalAlign="middle";d.textAlign="center";d.display="table-cell";d.font="15px/20px Arial, Helvetica, sans-serif";c.innerHTML=e.replace(":",":\x3cbr\x3e");b.innerHTML="";b.appendChild(c)}}var m=new c.config(b.config),n,q,j,f=m.width,r=m.height,p="Error loading player: ",s=d.plugins.loadPlugins(b.id,m.plugins);m.fallbackDiv&&(j=m.fallbackDiv,delete m.fallbackDiv);m.id=b.id;q=g.getElementById(b.id);n=g.createElement("div");n.id=q.id;n.style.width=0<f.toString().indexOf("%")? +f:f+"px";n.style.height=0<r.toString().indexOf("%")?r:r+"px";q.parentNode.replaceChild(n,q);d.embed.errorScreen=l;s.addEventListener(h.COMPLETE,function(){if("array"==a.typeOf(m.playlist)&&2>m.playlist.length&&(0==m.playlist.length||!m.playlist[0].sources||0==m.playlist[0].sources.length))k();else if(s.getStatus()==a.loaderstatus.COMPLETE){for(var d=0;d<m.modes.length;d++)if(m.modes[d].type&&c[m.modes[d].type]){var f=a.extend({},m),g=new c[m.modes[d].type](n,m.modes[d],f,s,b);if(g.supportsConfig()){g.addEventListener(h.ERROR, +e);g.embed();d=b;f=f.events;g=void 0;for(g in f)"function"==typeof d[g]&&d[g].call(d,f[g]);return b}}m.fallback?(a.log("No suitable players found and fallback enabled"),new c.download(n,m,k)):(a.log("No suitable players found and fallback disabled"),n.parentNode.replaceChild(j,n))}});s.addEventListener(h.ERROR,function(a){l(n,"Could not load plugins: "+a.message)});s.load();return b}}(jwplayer),function(d){function a(a){if(a.playlist)for(var e=0;e<a.playlist.length;e++)a.playlist[e]=new c(a.playlist[e]); +else{var e={},d;for(d in c.defaults)h(a,e,d);e.sources||(a.levels?(e.sources=a.levels,delete a.levels):(d={},h(a,d,"file"),h(a,d,"type"),e.sources=d.file?[d]:[]));a.playlist=[new c(e)]}}function h(a,e,c){g.exists(a[c])&&(e[c]=a[c],delete a[c])}var g=d.utils,c=d.playlist.item;(d.embed.config=function(b){var e={fallback:!0,height:270,primary:"html5",width:480,base:b.base?b.base:g.getScriptPath("jwplayer.js")};b=g.extend(e,d.defaults,b);var e={type:"html5",src:b.base+"jwplayer.html5.js"},c={type:"flash", +src:b.base+"jwplayer.flash.swf"};b.modes="flash"==b.primary?[c,e]:[e,c];b.listbar&&(b.playlistsize=b.listbar.size,b.playlistposition=b.listbar.position);b.flashplayer&&(c.src=b.flashplayer);b.html5player&&(e.src=b.html5player);a(b);return b}).addConfig=function(b,c){a(c);return g.extend(b,c)}}(jwplayer),function(d){var a=d.utils,h=document;d.embed.download=function(d,c,b){function e(a,b){for(var c=h.querySelectorAll(a),e=0;e<c.length;e++)for(var d in b)c[e].style[d]=b[d]}function k(a,b,c){a=h.createElement(a); +b&&(a.className="jwdownload"+b);c&&c.appendChild(a);return a}var l=a.extend({},c),m,n=l.width?l.width:480,q=l.height?l.height:320,j;c=c.logo?c.logo:{prefix:a.repo(),file:"logo.png",margin:10};var f,r;r=l.playlist;var p,s,l=["mp4","aac","mp3"];if(r&&r.length){p=r[0];s=p.sources;for(r=0;r<s.length;r++){var u=s[r],t=u.type?u.type:a.extensionmap.extType(a.extension(u.file));if(u.file)for(r in l)t==l[r]?(m=u.file,j=p.image):a.isYouTube(u.file)&&(f=u.file)}m?(b=m,d&&(m=k("a","display",d),k("div","icon", +m),k("div","logo",m),b&&m.setAttribute("href",a.getAbsolutePath(b))),b="#"+d.id+" .jwdownload",d.style.width="",d.style.height="",e(b+"display",{width:a.styleDimension(Math.max(320,n)),height:a.styleDimension(Math.max(180,q)),background:"black center no-repeat "+(j?"url("+j+")":""),backgroundSize:"contain",position:"relative",border:"none",display:"block"}),e(b+"display div",{position:"absolute",width:"100%",height:"100%"}),e(b+"logo",{top:c.margin+"px",right:c.margin+"px",background:"top right no-repeat url("+ +c.prefix+c.file+")"}),e(b+"icon",{background:"center no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAgNJREFUeNrs28lqwkAYB/CZqNVDDj2r6FN41QeIy8Fe+gj6BL275Q08u9FbT8ZdwVfotSBYEPUkxFOoks4EKiJdaDuTjMn3wWBO0V/+sySR8SNSqVRKIR8qaXHkzlqS9jCfzzWcTCYp9hF5o+59sVjsiRzcegSckFzcjT+ruN80TeSlAjCAAXzdJSGPFXRpAAMYwACGZQkSdhG4WCzehMNhqV6vG6vVSrirKVEw66YoSqDb7cqlUilE8JjHd/y1MQefVzqdDmiaJpfLZWHgXMHn8F6vJ1cqlVAkEsGuAn83J4gAd2RZymQygX6/L1erVQt+9ZPWb+CDwcCC2zXGJaewl/DhcHhK3DVj+KfKZrMWvFarcYNLomAv4aPRSFZVlTlcSPA5fDweW/BoNIqFnKV53JvncjkLns/n/cLdS+92O7RYLLgsKfv9/t8XlDn4eDyiw+HA9Jyz2eyt0+kY2+3WFC5hluej0Ha7zQQq9PPwdDq1Et1sNsx/nFBgCqWJ8oAK1aUptNVqcYWewE4nahfU0YQnk4ntUEfGMIU2m01HoLaCKbTRaDgKtaVLk9tBYaBcE/6Artdr4RZ5TB6/dC+9iIe/WgAMYADDpAUJAxjAAAYwgGFZgoS/AtNNTF7Z2bL0BYPBV3Jw5xFwwWcYxgtBP5OkE8i9G7aWGOOCruvauwADALMLMEbKf4SdAAAAAElFTkSuQmCC)"})): +f?(c=f,d=k("embed","",d),d.src="http://www.youtube.com/v/"+/v[=\/](\w*)|\/(\w+)$|^(\w+)$/i.exec(c).slice(1).join(""),d.type="application/x-shockwave-flash",d.width=n,d.height=q):b()}}}(jwplayer),function(d){var a=d.utils,h=d.events,g={};(d.embed.flash=function(c,b,e,k,l){function m(a,b,c){var e=document.createElement("param");e.setAttribute("name",b);e.setAttribute("value",c);a.appendChild(e)}function n(a,b,c){return function(){try{c&&document.getElementById(l.id+"_wrapper").appendChild(b);var e= +document.getElementById(l.id).getPluginConfig("display");"function"==typeof a.resize&&a.resize(e.width,e.height);b.style.left=e.x;b.style.top=e.h}catch(d){}}}function q(b){if(!b)return{};var c={},e=[],d;for(d in b){var f=a.getPluginName(d),g=b[d];e.push(d);for(var k in g)c[f+"."+k]=g[k]}c.plugins=e.join(",");return c}var j=new d.events.eventdispatcher,f=a.flashVersion();a.extend(this,j);this.embed=function(){e.id=l.id;if(10>f)return j.sendEvent(h.ERROR,{message:"Flash version must be 10.0 or greater"}), +!1;var d,p=a.extend({},e);c.id+"_wrapper"==c.parentNode.id?document.getElementById(c.id+"_wrapper"):(d=document.createElement("div"),d.id=c.id+"_wrapper",d.style.position="relative",d.style.width=a.styleDimension(p.width),d.style.height=a.styleDimension(p.height),c.parentNode.replaceChild(d,c),d.appendChild(c));d=k.setupPlugins(l,p,n);0<d.length?a.extend(p,q(d.plugins)):delete p.plugins;"undefined"!=typeof p["dock.position"]&&"false"==p["dock.position"].toString().toLowerCase()&&(p.dock=p["dock.position"], +delete p["dock.position"]);d=p.wmode?p.wmode:p.height&&40>=p.height?"transparent":"opaque";for(var s="height width modes events primary base fallback volume".split(" "),u=0;u<s.length;u++)delete p[s[u]];var s=a.getCookies(),t;for(t in s)"undefined"==typeof p[t]&&(p[t]=s[t]);t=window.location.pathname.split("/");t.splice(t.length-1,1);t=t.join("/");p.base=t+"/";g[c.id]=p;a.isIE()?(p='\x3cobject classid\x3d"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" " width\x3d"100%" height\x3d"100%" id\x3d"'+c.id+ +'" name\x3d"'+c.id+'" tabindex\x3d0""\x3e',p+='\x3cparam name\x3d"movie" value\x3d"'+b.src+'"\x3e',p+='\x3cparam name\x3d"allowfullscreen" value\x3d"true"\x3e\x3cparam name\x3d"allowscriptaccess" value\x3d"always"\x3e',p+='\x3cparam name\x3d"seamlesstabbing" value\x3d"true"\x3e',p+='\x3cparam name\x3d"wmode" value\x3d"'+d+'"\x3e',p+='\x3cparam name\x3d"bgcolor" value\x3d"#000000"\x3e',p+="\x3c/object\x3e",c.outerHTML=p,p=document.getElementById(c.id)):(p=document.createElement("object"),p.setAttribute("type", +"application/x-shockwave-flash"),p.setAttribute("data",b.src),p.setAttribute("width","100%"),p.setAttribute("height","100%"),p.setAttribute("bgcolor","#000000"),p.setAttribute("id",c.id),p.setAttribute("name",c.id),p.setAttribute("tabindex",0),m(p,"allowfullscreen","true"),m(p,"allowscriptaccess","always"),m(p,"seamlesstabbing","true"),m(p,"wmode",d),c.parentNode.replaceChild(p,c));l.container=p;l.setPlayer(p,"flash")};this.supportsConfig=function(){if(f)if(e){if("string"==a.typeOf(e.playlist))return!0; +try{var b=e.playlist[0].sources;if("undefined"==typeof b)return!0;for(var c=0;c<b.length;c++){var d;if(d=b[c].file){var g=b[c].file,k=b[c].type;if(a.isYouTube(g)||a.isRtmp(g,k)||"hls"==k)d=!0;else{var h=a.extensionmap[k?k:a.extension(g)];d=!h?!1:!!h.flash}}if(d)return!0}}catch(j){}}else return!0;return!1}}).getVars=function(a){return g[a]}}(jwplayer),function(d){var a=d.utils,h=a.extensionmap,g=d.events;d.embed.html5=function(c,b,e,k,l){function m(a,b,d){return function(){try{var e=document.querySelector("#"+ +c.id+" .jwmain");d&&e.appendChild(b);"function"==typeof a.resize&&(a.resize(e.clientWidth,e.clientHeight),setTimeout(function(){a.resize(e.clientWidth,e.clientHeight)},400));b.left=e.style.left;b.top=e.style.top}catch(g){}}}function n(a){q.sendEvent(a.type,{message:"HTML5 player not found"})}var q=this,j=new g.eventdispatcher;a.extend(q,j);q.embed=function(){if(d.html5){k.setupPlugins(l,e,m);c.innerHTML="";var f=d.utils.extend({},e);delete f.volume;f=new d.html5.player(f);l.container=document.getElementById(l.id); +l.setPlayer(f,"html5")}else f=new a.scriptloader(b.src),f.addEventListener(g.ERROR,n),f.addEventListener(g.COMPLETE,q.embed),f.load()};q.supportsConfig=function(){if(d.vid.canPlayType)try{if("string"==a.typeOf(e.playlist))return!0;for(var b=e.playlist[0].sources,c=0;c<b.length;c++){var g;var k=b[c].file,j=b[c].type;if(null!==navigator.userAgent.match(/BlackBerry/i)||a.isAndroid()&&("m3u"==a.extension(k)||"m3u8"==a.extension(k))||a.isRtmp(k,j))g=!1;else{var l=h[j?j:a.extension(k)],m;if(!l||l.flash&& +!l.html5)m=!1;else{var n=l.html5,q=d.vid;if(n)try{m=q.canPlayType(n)?!0:!1}catch(z){m=!1}else m=!0}g=m}if(g)return!0}}catch(A){}return!1}}}(jwplayer),function(d){var a=d.embed,h=d.utils,g=h.extend(function(c){var b=h.repo(),e=c.config,g=e.plugins,l=e.analytics,m=b+"jwpsrv.js",n=b+"sharing.js",q=b+"related.js",j=b+"gapro.js",f=(new d.utils.key(d.key)).edition(),g=g?g:{};"ads"==f&&e.advertising&&(e.advertising.client.match(".js$|.swf$")?g[e.advertising.client]=e.advertising:g[b+e.advertising.client+ +("flash"==e.primary?".swf":".js")]=e.advertising);delete e.advertising;e.key=d.key;e.analytics&&(e.analytics.client&&e.analytics.client.match(".js$|.swf$"))&&(m=e.analytics.client);delete e.analytics;if("free"==f||!l||!1!==l.enabled)g[m]=l?l:{};delete g.sharing;delete g.related;if("premium"==f||"ads"==f)e.sharing&&(e.sharing.client&&e.sharing.client.match(".js$|.swf$")&&(n=e.sharing.client),g[n]=e.sharing),e.related&&(e.related.client&&e.related.client.match(".js$|.swf$")&&(q=e.related.client),g[q]= +e.related),e.ga&&(e.ga.client&&e.ga.client.match(".js$|.swf$")&&(j=e.ga.client),g[j]=e.ga),e.skin&&(e.skin=e.skin.replace(/^(beelden|bekle|five|glow|modieus|roundster|stormtrooper|vapor)$/i,h.repo()+"skins/$1.xml").toLowerCase());e.plugins=g;return new a(c)},a);d.embed=g}(jwplayer),function(d){var a=[],h=d.utils,g=d.events,c=g.state,b=document,e=d.api=function(a){function l(a,b){return function(c){return b(a,c)}}function m(a,b){p[a]||(p[a]=[],q(g.JWPLAYER_PLAYER_STATE,function(b){var c=b.newstate; +b=b.oldstate;if(c==a){var e=p[c];if(e)for(var d=0;d<e.length;d++)"function"==typeof e[d]&&e[d].call(this,{oldstate:b,newstate:c})}}));p[a].push(b);return f}function n(a,b){try{a.jwAddEventListener(b,'function(dat) { jwplayer("'+f.id+'").dispatchEvent("'+b+'", dat); }')}catch(c){h.log("Could not add internal listener")}}function q(a,b){r[a]||(r[a]=[],s&&u&&n(s,a));r[a].push(b);return f}function j(){if(u){for(var a=arguments[0],b=[],c=1;c<arguments.length;c++)b.push(arguments[c]);if("undefined"!=typeof s&& +"function"==typeof s[a])switch(b.length){case 4:return s[a](b[0],b[1],b[2],b[3]);case 3:return s[a](b[0],b[1],b[2]);case 2:return s[a](b[0],b[1]);case 1:return s[a](b[0]);default:return s[a]()}return null}t.push(arguments)}var f=this,r={},p={},s=void 0,u=!1,t=[],w=void 0,x={},y={};f.container=a;f.id=a.id;f.getBuffer=function(){return j("jwGetBuffer")};f.getContainer=function(){return f.container};f.addButton=function(a,b,c,e){try{y[e]=c,j("jwDockAddButton",a,b,"jwplayer('"+f.id+"').callback('"+e+ +"')",e)}catch(d){h.log("Could not add dock button"+d.message)}};f.removeButton=function(a){j("jwDockRemoveButton",a)};f.callback=function(a){if(y[a])y[a]()};f.forceState=function(a){j("jwForceState",a);return f};f.releaseState=function(){return j("jwReleaseState")};f.getDuration=function(){return j("jwGetDuration")};f.getFullscreen=function(){return j("jwGetFullscreen")};f.getStretching=function(){return j("jwGetStretching")};f.getHeight=function(){return j("jwGetHeight")};f.getLockState=function(){return j("jwGetLockState")}; +f.getMeta=function(){return f.getItemMeta()};f.getMute=function(){return j("jwGetMute")};f.getPlaylist=function(){var a=j("jwGetPlaylist");"flash"==f.renderingMode&&h.deepReplaceKeyName(a,["__dot__","__spc__","__dsh__","__default__"],["."," ","-","default"]);return a};f.getPlaylistItem=function(a){h.exists(a)||(a=f.getCurrentItem());return f.getPlaylist()[a]};f.getPosition=function(){return j("jwGetPosition")};f.getRenderingMode=function(){return f.renderingMode};f.getState=function(){return j("jwGetState")}; +f.getVolume=function(){return j("jwGetVolume")};f.getWidth=function(){return j("jwGetWidth")};f.setFullscreen=function(a){h.exists(a)?j("jwSetFullscreen",a):j("jwSetFullscreen",!j("jwGetFullscreen"));return f};f.setStretching=function(a){j("jwSetStretching",a);return f};f.setMute=function(a){h.exists(a)?j("jwSetMute",a):j("jwSetMute",!j("jwGetMute"));return f};f.lock=function(){return f};f.unlock=function(){return f};f.load=function(a){j("jwLoad",a);return f};f.playlistItem=function(a){j("jwPlaylistItem", +parseInt(a));return f};f.playlistPrev=function(){j("jwPlaylistPrev");return f};f.playlistNext=function(){j("jwPlaylistNext");return f};f.resize=function(a,c){if("flash"!=f.renderingMode)j("jwResize",a,c);else{var e=b.getElementById(f.id+"_wrapper");e&&(e.style.width=h.styleDimension(a),e.style.height=h.styleDimension(c))}return f};f.play=function(a){"undefined"==typeof a?(a=f.getState(),a==c.PLAYING||a==c.BUFFERING?j("jwPause"):j("jwPlay")):j("jwPlay",a);return f};f.pause=function(a){"undefined"== +typeof a?(a=f.getState(),a==c.PLAYING||a==c.BUFFERING?j("jwPause"):j("jwPlay")):j("jwPause",a);return f};f.stop=function(){j("jwStop");return f};f.seek=function(a){j("jwSeek",a);return f};f.setVolume=function(a){j("jwSetVolume",a);return f};f.loadInstream=function(a,b){return w=new e.instream(this,s,a,b)};f.getQualityLevels=function(){return j("jwGetQualityLevels")};f.getCurrentQuality=function(){return j("jwGetCurrentQuality")};f.setCurrentQuality=function(a){j("jwSetCurrentQuality",a)};f.getCaptionsList= +function(){return j("jwGetCaptionsList")};f.getCurrentCaptions=function(){return j("jwGetCurrentCaptions")};f.setCurrentCaptions=function(a){j("jwSetCurrentCaptions",a)};f.getControls=function(){return j("jwGetControls")};f.getSafeRegion=function(){return j("jwGetSafeRegion")};f.setControls=function(a){j("jwSetControls",a)};f.destroyPlayer=function(){j("jwPlayerDestroy")};var z={onBufferChange:g.JWPLAYER_MEDIA_BUFFER,onBufferFull:g.JWPLAYER_MEDIA_BUFFER_FULL,onError:g.JWPLAYER_ERROR,onFullscreen:g.JWPLAYER_FULLSCREEN, +onMeta:g.JWPLAYER_MEDIA_META,onMute:g.JWPLAYER_MEDIA_MUTE,onPlaylist:g.JWPLAYER_PLAYLIST_LOADED,onPlaylistItem:g.JWPLAYER_PLAYLIST_ITEM,onPlaylistComplete:g.JWPLAYER_PLAYLIST_COMPLETE,onReady:g.API_READY,onResize:g.JWPLAYER_RESIZE,onComplete:g.JWPLAYER_MEDIA_COMPLETE,onSeek:g.JWPLAYER_MEDIA_SEEK,onTime:g.JWPLAYER_MEDIA_TIME,onVolume:g.JWPLAYER_MEDIA_VOLUME,onBeforePlay:g.JWPLAYER_MEDIA_BEFOREPLAY,onBeforeComplete:g.JWPLAYER_MEDIA_BEFORECOMPLETE,onDisplayClick:g.JWPLAYER_DISPLAY_CLICK,onControls:g.JWPLAYER_CONTROLS, +onQualityLevels:g.JWPLAYER_MEDIA_LEVELS,onQualityChange:g.JWPLAYER_MEDIA_LEVEL_CHANGED,onCaptionsList:g.JWPLAYER_CAPTIONS_LIST,onCaptionsChange:g.JWPLAYER_CAPTIONS_CHANGED};h.foreach(z,function(a){f[a]=l(z[a],q)});var A={onBuffer:c.BUFFERING,onPause:c.PAUSED,onPlay:c.PLAYING,onIdle:c.IDLE};h.foreach(A,function(a){f[a]=l(A[a],m)});f.remove=function(){if(!u)throw"Cannot call remove() before player is ready";t=[];e.destroyPlayer(this.id)};f.setup=function(a){if(d.embed){var c=b.getElementById(f.id); +c&&(a.fallbackDiv=c);c=f;t=[];e.destroyPlayer(c.id);c=d(f.id);c.config=a;return new d.embed(c)}return f};f.registerPlugin=function(a,b,c,e){d.plugins.registerPlugin(a,b,c,e)};f.setPlayer=function(a,b){s=a;f.renderingMode=b};f.detachMedia=function(){if("html5"==f.renderingMode)return j("jwDetachMedia")};f.attachMedia=function(a){if("html5"==f.renderingMode)return j("jwAttachMedia",a)};f.dispatchEvent=function(a,b){if(r[a])for(var c=h.translateEventResponse(a,b),e=0;e<r[a].length;e++)if("function"== +typeof r[a][e])try{r[a][e].call(this,c)}catch(d){h.log("There was an error calling back an event handler")}};f.dispatchInstreamEvent=function(a){w&&w.dispatchEvent(a,arguments)};f.callInternal=j;f.playerReady=function(a){u=!0;s||f.setPlayer(b.getElementById(a.id));f.container=b.getElementById(f.id);h.foreach(r,function(a){n(s,a)});q(g.JWPLAYER_PLAYLIST_ITEM,function(){x={}});q(g.JWPLAYER_MEDIA_META,function(a){h.extend(x,a.metadata)});for(f.dispatchEvent(g.API_READY);0<t.length;)j.apply(this,t.shift())}; +f.getItemMeta=function(){return x};f.getCurrentItem=function(){return j("jwGetPlaylistIndex")};return f};e.selectPlayer=function(c){var d;h.exists(c)||(c=0);c.nodeType?d=c:"string"==typeof c&&(d=b.getElementById(c));return d?(c=e.playerById(d.id))?c:e.addPlayer(new e(d)):"number"==typeof c?a[c]:null};e.playerById=function(b){for(var c=0;c<a.length;c++)if(a[c].id==b)return a[c];return null};e.addPlayer=function(b){for(var c=0;c<a.length;c++)if(a[c]==b)return b;a.push(b);return b};e.destroyPlayer=function(c){for(var e= +-1,d,g=0;g<a.length;g++)a[g].id==c&&(e=g,d=a[g]);0<=e&&(c=d.id,g=b.getElementById(c+("flash"==d.renderingMode?"_wrapper":"")),h.clearCss&&h.clearCss("#"+c),g&&("html5"==d.renderingMode&&d.destroyPlayer(),d=b.createElement("div"),d.id=c,g.parentNode.replaceChild(d,g)),a.splice(e,1));return null};d.playerReady=function(a){var b=d.api.playerById(a.id);b?b.playerReady(a):d.api.selectPlayer(a.id).playerReady(a)}}(jwplayer),function(d){d.api.instream=function(a,d,g,c){this.play=function(a){d.jwInstreamPlay(a)}; +this.pause=function(a){d.jwInstreamPause(a)};this.destroy=function(){d.jwInstreamDestroy()};a.callInternal("jwLoadInstream",g,c?c:{})}}(jwplayer),function(d){var a=d.api,h=a.selectPlayer;a.selectPlayer=function(a){return(a=h(a))?a:{registerPlugin:function(a,b,e){d.plugins.registerPlugin(a,b,e)}}}}(jwplayer)); \ No newline at end of file |