├── wpse-playlist.php ├── README.md └── php └── class.playlist.php /wpse-playlist.php: -------------------------------------------------------------------------------- 1 | init(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | wpse-playlist 2 | ================= 3 | 4 | WordPress - Playlist shortcode with support for external audio and video files. 5 | 6 | ### Description 7 | 8 | This plugin allows you to use external audio or video files with the native WordPress playlist, through the use of a shortcode. 9 | 10 | This started as an answer on WordPress StackExchange, see [here](http://wordpress.stackexchange.com/questions/141766/making-audio-playlist-with-external-audio-files/), hence the name wpse-playlist. 11 | 12 | The plugin works on PHP 5.3+ and WordPress 4.0+ 13 | 14 | Tested up to WordPress 5.8.1 15 | 16 | It supports the GitHub Updater. 17 | 18 | ### Supported shortcodes and default attributes: 19 | 20 | [_playlist type="audio" 21 | class="wpse-playlist" 22 | current="true" 23 | autoplay="false" 24 | style="light" 25 | tracklist="true" 26 | tracknumbers="true" 27 | images="true" 28 | artists="true" 29 | width="" 30 | height="" 31 | outer="20" 32 | default_width="640" 33 | default_height="380"] 34 | [_track src="" 35 | title="" 36 | type="audio/mpeg" 37 | caption="" 38 | description="" 39 | image="" 40 | meta_artist="" 41 | meta_album="" 42 | meta_genre="" 43 | meta_length_formatted="" 44 | image_src="%s/wp-includes/images/media/%s.png" 45 | image_width="48" 46 | image_height="64" 47 | thumb_src="%s/wp-includes/images/media/%s.png" 48 | thumb_width="48" 49 | thumb_height="64" 50 | dimensions_original_width="300" 51 | dimensions_original_height="200" 52 | dimensions_resized_width="600" 53 | dimensions_resized_height="400"] 54 | [/_playlist] 55 | 56 | where one can add multiple `[_track]`, one for each track, inside `[_playlist]`. 57 | 58 | The shortcodes `[wpse_trac]` and `[wpse_playlist]` are also supported, but are deprecated. 59 | 60 | When the `width` and `height` is empty, the global `$content_width` is used to calculate these values. 61 | 62 | When the playlist type is `"video"` the track type is automatically set to `"video/mp4"` as the default value. 63 | 64 | The attributes `artists`, `images`, `meta_artist`, `meta_album` and `meta_genre` are only audio related. 65 | 66 | Similarly the `dimensions_original_width`, `dimensions_original_height`, `dimensions_resized_width`, `dimensions_resized_height` are only video related. 67 | 68 | ### Demo 69 | 70 | [Check it out here.](http://xlino.com/projects/wordpress-playlist-shortcode-with-external-audio-or-video-files/) 71 | 72 | ### Example 1 73 | 74 | A simple example for the audio playlist: 75 | 76 | [_playlist] 77 | [_track title="Ain't Misbehavin'" src="//s.w.org/images/core/3.9/AintMisbehavin.mp3"] 78 | [_track title="Buddy Bolden's Blues" src="//s.w.org/images/core/3.9/JellyRollMorton-BuddyBoldensBlues.mp3"] 79 | [/_playlist] 80 | 81 | 82 | ### Example 2 83 | 84 | The vanilla audio version is generated with: 85 | 86 | [_playlist type="audio" current="no" tracklist="yes" tracknumbers="no" images="no" artist="no"] 87 | [_track title="Davenport Blues" src="//s.w.org/images/core/3.9/DavenportBlues.mp3"] 88 | [_track title="Dixie Blues" src="//s.w.org/images/core/3.9/Louisiana_Five-Dixie_Blues-1919.mp3"] 89 | [/_playlist] 90 | 91 | ### Example 3 92 | 93 | The video playlist can be generated with: 94 | 95 | [_playlist type="video"] 96 | [_track caption="Live widgets previews in WordPress 3.9" src="//s.w.org/images/core/3.9/widgets.mp4" image_src="/wp-content/uploads/2014/04/widgets_screen.png"] 97 | [_track caption="Another cool video showing how live widgets previews works in WordPress 3.9" src="//s.w.org/images/core/3.9/widgets.mp4" image_src="/wp-content/uploads/2014/04/widgets_screen2.png"] 98 | [/_playlist] 99 | 100 | 101 | Any suggestions are welcomed. 102 | 103 | ### Changelog 104 | 105 | 0.0.11 (2023-01-13) 106 | 107 | - Fixed: Some formatting issues. 108 | - Fixed: Removed an unused constant and added instead a Requires header just for info. 109 | 110 | 0.0.10 (2023-01-13) 111 | 112 | - Fixed: Issue #20 re-evaluated by using esc_url_raw to support multiple GET parameters in Google Drive links (Props: @honoluluman2, @mikigp) 113 | 114 | 0.0.9 (2015-08-02) 115 | 116 | - Fixed: Issue #7 by using true/false instead of 1/0 (Props: @X-PRESSIVE) 117 | 118 | 0.0.7 (2015-03-08) 119 | 120 | - Added: New shortcodes [_playlist] and [_track]. 121 | - Deprecated: The support for the shortcodes [wpse_playlist] and [wpse_trac] will phase out. 122 | 123 | 0.0.6 (2015-03-07) 124 | 125 | - Added: Support for the autoplay attribute. 126 | - Added: Support for the GitHub Updater. (Probs: @BlaineMoore) 127 | - Added: More info in the README.md file. 128 | - Changed: Refactored regarding late escaping. 129 | - Changed: Replaced filter_var() with wp_validate_boolean(), so we need WordPress 4.0+. 130 | - Fixed: Some minor adjustments. 131 | 132 | 0.0.5 133 | 134 | - Fixed: added the missing script class to support WordPress 4.0 (Props: @ruLait) 135 | -------------------------------------------------------------------------------- /php/class.playlist.php: -------------------------------------------------------------------------------- 1 | instance++; // Counter to activate the 'wp_playlist_scripts' action only once 32 | 33 | $atts = shortcode_atts( 34 | array( 35 | 'type' => 'audio', 36 | 'style' => 'light', 37 | 'tracklist' => 'true', 38 | 'tracknumbers' => 'true', 39 | 'images' => 'true', // Audio related 40 | 'artists' => 'true', // Audio related 41 | 'current' => 'true', 42 | 'autoplay' => 'false', 43 | 'class' => 'wpse-playlist', 44 | 'width' => '', 45 | 'height' => '', 46 | 'outer' => '20', 47 | 'default_width' => '640', 48 | 'default_height' => '380', 49 | ), 50 | $atts, 51 | 'wpse_playlist_shortcode' 52 | ); 53 | 54 | // Autoplay: 55 | $autoplay = wp_validate_boolean( $atts['autoplay'] ) ? 'autoplay="yes"' : ''; 56 | 57 | // Nested shortcode support: 58 | $this->type = ( in_array( $atts['type'], $this->types, TRUE ) ) ? esc_attr( $atts['type'] ) : 'audio'; 59 | 60 | // Enqueue default scripts and styles for the playlist. 61 | if (1 === $this->instance) { 62 | do_action( 'wp_playlist_scripts', esc_attr($atts['type']), esc_attr($atts['style'])); 63 | } 64 | 65 | // Height & Width - Adjusted from the WordPress core. 66 | 67 | $width = esc_attr( $atts['width'] ); 68 | if( empty( $width ) ) { 69 | $width = empty( $content_width ) 70 | ? intval( $atts['default_width'] ) 71 | : ( $content_width - intval( $atts['outer'] ) ); 72 | } 73 | 74 | $height = esc_attr( $atts['height'] ); 75 | if( empty( $height ) && intval( $atts['default_height'] ) > 0 ) { 76 | $height = empty( $content_width ) 77 | ? intval( $atts['default_height'] ) 78 | : round( ( intval( $atts['default_height'] ) * $width ) / intval( $atts['default_width'] ) ); 79 | } 80 | 81 | // Output 82 | $html = ''; 83 | 84 | // Start div container: 85 | $html .= sprintf( '
', 86 | $this->type, 87 | esc_attr( $atts['style'] ) 88 | ); 89 | 90 | // Current audio item: 91 | if( $atts['current'] && 'audio' === $this->type ) { 92 | $html .= '
'; 93 | } 94 | 95 | // Video player: 96 | if( 'video' === $this->type ) { 97 | $html .= sprintf( '', 98 | $width, 99 | $height 100 | ); 101 | } 102 | 103 | // Audio player: 104 | else { 105 | $html .= sprintf( '', 106 | $width 107 | ); 108 | } 109 | 110 | // Next/Previous: 111 | $html .= '
'; 112 | 113 | // JSON 114 | $html .= sprintf( ' 115 | ', 123 | esc_attr( $atts['type'] ), 124 | wp_validate_boolean( $atts['tracklist'] ) ? 'true' : 'false', 125 | wp_validate_boolean( $atts['tracknumbers'] ) ? 'true' : 'false', 126 | wp_validate_boolean( $atts['images'] ) ? 'true' : 'false', 127 | wp_validate_boolean( $atts['artists'] ) ? 'true' : 'false', 128 | $this->get_tracks_from_content( $content ) 129 | ); 130 | 131 | // Close div container: 132 | $html .= '
'; 133 | 134 | return $html; 135 | } 136 | 137 | 138 | /** 139 | * Get tracks from the [_playlist] shortcode content string 140 | */ 141 | 142 | private function get_tracks_from_content( $content ) 143 | { 144 | // Get tracs: 145 | $content = strip_tags( nl2br( do_shortcode( $content ) ) ); 146 | 147 | // Replace last comma: 148 | if( FALSE !== ( $pos = strrpos( $content, ',' ) ) ) { 149 | $content = substr_replace( $content, '', $pos, 1 ); 150 | } 151 | 152 | return $content; 153 | } 154 | 155 | /** 156 | * Callback for the [_track] shortcode. 157 | */ 158 | public function track_shortcode( $atts = array(), $content = '' ) { 159 | $atts = shortcode_atts( 160 | array( 161 | 'src' => '', 162 | 'type' => ( 'video' === $this->type ) ? 'video/mp4' : 'audio/mpeg', 163 | 'title' => '', 164 | 'caption' => '', 165 | 'description' => '', 166 | 'image_src' => sprintf( '%s/wp-includes/images/media/%s.png', get_site_url(), $this->type ), 167 | 'image_width' => '48', 168 | 'image_height' => '64', 169 | 'thumb_src' => sprintf( '%s/wp-includes/images/media/%s.png', get_site_url(), $this->type ), 170 | 'thumb_width' => '48', 171 | 'thumb_height' => '64', 172 | 'meta_artist' => '', 173 | 'meta_album' => '', 174 | 'meta_genre' => '', 175 | 'meta_length_formatted' => '', 176 | 'dimensions_original_width' => '300', 177 | 'dimensions_original_height' => '200', 178 | 'dimensions_resized_width' => '600', 179 | 'dimensions_resized_height' => '400', 180 | ), 181 | $atts, 182 | 'wpse_track_shortcode' 183 | ); 184 | 185 | // Data output. 186 | $data['src'] = esc_url_raw( $atts['src'] ); 187 | $data['title'] = sanitize_text_field( $atts['title'] ); 188 | $data['type'] = sanitize_text_field( $atts['type'] ); 189 | $data['caption'] = sanitize_text_field( $atts['caption'] ); 190 | $data['description'] = sanitize_text_field( $atts['description'] ); 191 | $data['image']['src'] = esc_url( $atts['image_src'] ); 192 | $data['image']['width'] = intval( $atts['image_width'] ); 193 | $data['image']['height'] = intval( $atts['image_height'] ); 194 | $data['thumb']['src'] = esc_url( $atts['thumb_src'] ); 195 | $data['thumb']['width'] = intval( $atts['thumb_width'] ); 196 | $data['thumb']['height'] = intval( $atts['thumb_height'] ); 197 | $data['meta']['length_formatted'] = sanitize_text_field( $atts['meta_length_formatted'] ); 198 | 199 | // Video related. 200 | if( 'video' === $this->type ) { 201 | $data['dimensions']['original']['width'] = sanitize_text_field( $atts['dimensions_original_width'] ); 202 | $data['dimensions']['original']['height'] = sanitize_text_field( $atts['dimensions_original_height'] ); 203 | $data['dimensions']['resized']['width'] = sanitize_text_field( $atts['dimensions_resized_width'] ); 204 | $data['dimensions']['resized']['height'] = sanitize_text_field( $atts['dimensions_resized_height'] ); 205 | 206 | // Audio related. 207 | } else { 208 | $data['meta']['artist'] = sanitize_text_field( $atts['meta_artist'] ); 209 | $data['meta']['album'] = sanitize_text_field( $atts['meta_album'] ); 210 | $data['meta']['genre'] = sanitize_text_field( $atts['meta_genre'] ); 211 | } 212 | 213 | return json_encode( $data ) . ','; 214 | } 215 | 216 | } --------------------------------------------------------------------------------