+/**
+ * Provide a No-JS Flash fallback as a last resort for audio / video
+ *
+ * @since 3.6.0
+ *
+ * @param string $url
+ * @return string Fallback HTML
+ */
+function wp_mediaelement_fallback( $url ) {
+ return apply_filters( 'wp_mediaelement_fallback', sprintf( '<a href="%1$s">%1$s</a>', esc_url( $url ) ), $url );
+}
+
+/**
+ * Return a filtered list of WP-supported audio formats
+ *
+ * @since 3.6.0
+ * @return array
+ */
+function wp_get_audio_extensions() {
+ return apply_filters( 'wp_audio_extensions', array( 'mp3', 'ogg', 'wma', 'm4a', 'wav' ) );
+}
+
+/**
+ * The Audio shortcode.
+ *
+ * This implements the functionality of the Audio Shortcode for displaying
+ * WordPress mp3s in a post.
+ *
+ * @since 3.6.0
+ *
+ * @param array $attr Attributes of the shortcode.
+ * @return string HTML content to display audio.
+ */
+function wp_audio_shortcode( $attr ) {
+ $post_id = get_post() ? get_the_ID() : 0;
+
+ static $instances = 0;
+ $instances++;
+
+ $audio = null;
+
+ $default_types = wp_get_audio_extensions();
+ $defaults_atts = array(
+ 'src' => '',
+ 'loop' => '',
+ 'autoplay' => '',
+ 'preload' => 'none'
+ );
+ foreach ( $default_types as $type )
+ $defaults_atts[$type] = '';
+
+ $atts = shortcode_atts( $defaults_atts, $attr, 'audio' );
+ extract( $atts );
+
+ $primary = false;
+ if ( ! empty( $src ) ) {
+ $type = wp_check_filetype( $src, wp_get_mime_types() );
+ if ( ! in_array( $type['ext'], $default_types ) )
+ return sprintf( '<a class="wp-embedded-audio" href="%s">%s</a>', esc_url( $src ), esc_html( $src ) );
+ $primary = true;
+ array_unshift( $default_types, 'src' );
+ } else {
+ foreach ( $default_types as $ext ) {
+ if ( ! empty( $$ext ) ) {
+ $type = wp_check_filetype( $$ext, wp_get_mime_types() );
+ if ( $type['ext'] === $ext )
+ $primary = true;
+ }
+ }
+ }
+
+ if ( ! $primary ) {
+ $audios = get_attached_media( 'audio', $post_id );
+ if ( empty( $audios ) )
+ return;
+
+ $audio = reset( $audios );
+ $src = wp_get_attachment_url( $audio->ID );
+ if ( empty( $src ) )
+ return;
+
+ array_unshift( $default_types, 'src' );
+ }
+
+ $library = apply_filters( 'wp_audio_shortcode_library', 'mediaelement' );
+ if ( 'mediaelement' === $library && did_action( 'init' ) ) {
+ wp_enqueue_style( 'wp-mediaelement' );
+ wp_enqueue_script( 'wp-mediaelement' );
+ }
+
+ $atts = array(
+ 'class' => apply_filters( 'wp_audio_shortcode_class', 'wp-audio-shortcode' ),
+ 'id' => sprintf( 'audio-%d-%d', $post_id, $instances ),
+ 'loop' => $loop,
+ 'autoplay' => $autoplay,
+ 'preload' => $preload,
+ 'style' => 'width: 100%',
+ );
+
+ // These ones should just be omitted altogether if they are blank
+ foreach ( array( 'loop', 'autoplay', 'preload' ) as $a ) {
+ if ( empty( $atts[$a] ) )
+ unset( $atts[$a] );
+ }
+
+ $attr_strings = array();
+ foreach ( $atts as $k => $v ) {
+ $attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
+ }
+
+ $html = '';
+ if ( 'mediaelement' === $library && 1 === $instances )
+ $html .= "<!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->\n";
+ $html .= sprintf( '<audio %s controls="controls">', join( ' ', $attr_strings ) );
+
+ $fileurl = '';
+ $source = '<source type="%s" src="%s" />';
+ foreach ( $default_types as $fallback ) {
+ if ( ! empty( $$fallback ) ) {
+ if ( empty( $fileurl ) )
+ $fileurl = $$fallback;
+ $type = wp_check_filetype( $$fallback, wp_get_mime_types() );
+ $html .= sprintf( $source, $type['type'], esc_url( $$fallback ) );
+ }
+ }
+
+ if ( 'mediaelement' === $library )
+ $html .= wp_mediaelement_fallback( $fileurl );
+ $html .= '</audio>';
+
+ return apply_filters( 'wp_audio_shortcode', $html, $atts, $audio, $post_id, $library );
+}
+add_shortcode( 'audio', apply_filters( 'wp_audio_shortcode_handler', 'wp_audio_shortcode' ) );
+
+/**
+ * Return a filtered list of WP-supported video formats
+ *
+ * @since 3.6.0
+ * @return array
+ */
+function wp_get_video_extensions() {
+ return apply_filters( 'wp_video_extensions', array( 'mp4', 'm4v', 'webm', 'ogv', 'wmv', 'flv' ) );
+}
+
+/**
+ * The Video shortcode.
+ *
+ * This implements the functionality of the Video Shortcode for displaying
+ * WordPress mp4s in a post.
+ *
+ * @since 3.6.0
+ *
+ * @param array $attr Attributes of the shortcode.
+ * @return string HTML content to display video.
+ */
+function wp_video_shortcode( $attr ) {
+ global $content_width;
+ $post_id = get_post() ? get_the_ID() : 0;
+
+ static $instances = 0;
+ $instances++;
+
+ $video = null;
+
+ $default_types = wp_get_video_extensions();
+ $defaults_atts = array(
+ 'src' => '',
+ 'poster' => '',
+ 'loop' => '',
+ 'autoplay' => '',
+ 'preload' => 'metadata',
+ 'height' => 360,
+ 'width' => empty( $content_width ) ? 640 : $content_width,
+ );
+
+ foreach ( $default_types as $type )
+ $defaults_atts[$type] = '';
+
+ $atts = shortcode_atts( $defaults_atts, $attr, 'video' );
+ extract( $atts );
+
+ $w = $width;
+ $h = $height;
+ if ( is_admin() && $width > 600 )
+ $w = 600;
+ elseif ( ! is_admin() && $w > $defaults_atts['width'] )
+ $w = $defaults_atts['width'];
+
+ if ( $w < $width )
+ $height = round( ( $h * $w ) / $width );
+
+ $width = $w;
+
+ $primary = false;
+ if ( ! empty( $src ) ) {
+ $type = wp_check_filetype( $src, wp_get_mime_types() );
+ if ( ! in_array( $type['ext'], $default_types ) )
+ return sprintf( '<a class="wp-embedded-video" href="%s">%s</a>', esc_url( $src ), esc_html( $src ) );
+ $primary = true;
+ array_unshift( $default_types, 'src' );
+ } else {
+ foreach ( $default_types as $ext ) {
+ if ( ! empty( $$ext ) ) {
+ $type = wp_check_filetype( $$ext, wp_get_mime_types() );
+ if ( $type['ext'] === $ext )
+ $primary = true;
+ }
+ }
+ }
+
+ if ( ! $primary ) {
+ $videos = get_attached_media( 'video', $post_id );
+ if ( empty( $videos ) )
+ return;
+
+ $video = reset( $videos );
+ $src = wp_get_attachment_url( $video->ID );
+ if ( empty( $src ) )
+ return;
+
+ array_unshift( $default_types, 'src' );
+ }
+
+ $library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
+ if ( 'mediaelement' === $library && did_action( 'init' ) ) {
+ wp_enqueue_style( 'wp-mediaelement' );
+ wp_enqueue_script( 'wp-mediaelement' );
+ }
+
+ $atts = array(
+ 'class' => apply_filters( 'wp_video_shortcode_class', 'wp-video-shortcode' ),
+ 'id' => sprintf( 'video-%d-%d', $post_id, $instances ),
+ 'width' => absint( $width ),
+ 'height' => absint( $height ),
+ 'poster' => esc_url( $poster ),
+ 'loop' => $loop,
+ 'autoplay' => $autoplay,
+ 'preload' => $preload,
+ );
+
+ // These ones should just be omitted altogether if they are blank
+ foreach ( array( 'poster', 'loop', 'autoplay', 'preload' ) as $a ) {
+ if ( empty( $atts[$a] ) )
+ unset( $atts[$a] );
+ }
+
+ $attr_strings = array();
+ foreach ( $atts as $k => $v ) {
+ $attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
+ }
+
+ $html = '';
+ if ( 'mediaelement' === $library && 1 === $instances )
+ $html .= "<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->\n";
+ $html .= sprintf( '<video %s controls="controls">', join( ' ', $attr_strings ) );
+
+ $fileurl = '';
+ $source = '<source type="%s" src="%s" />';
+ foreach ( $default_types as $fallback ) {
+ if ( ! empty( $$fallback ) ) {
+ if ( empty( $fileurl ) )
+ $fileurl = $$fallback;
+ $type = wp_check_filetype( $$fallback, wp_get_mime_types() );
+ // m4v sometimes shows up as video/mpeg which collides with mp4
+ if ( 'm4v' === $type['ext'] )
+ $type['type'] = 'video/m4v';
+ $html .= sprintf( $source, $type['type'], esc_url( $$fallback ) );
+ }
+ }
+ if ( 'mediaelement' === $library )
+ $html .= wp_mediaelement_fallback( $fileurl );
+ $html .= '</video>';
+
+ $html = sprintf( '<div style="width: %dpx; max-width: 100%%;">%s</div>', $width, $html );
+ return apply_filters( 'wp_video_shortcode', $html, $atts, $video, $post_id, $library );
+}
+add_shortcode( 'video', apply_filters( 'wp_video_shortcode_handler', 'wp_video_shortcode' ) );
+