'Icecast (status-json.xsl)', 'description' => __( 'Reads /status-json.xsl on the stream host and matches the mount.', 'streamsera' ), 'usesUrl' => true, 'usesMount' => true, ); } /** * {@inheritdoc} * * @param array $source Source definition (url, mount, stream_url). */ public function fetch( array $source ) { $status_url = ! empty( $source['url'] ) ? $source['url'] : Resolver::status_url( $source['stream_url'], '/status-json.xsl' ); if ( ! $status_url ) { return null; } $body = Resolver::http_get( $status_url ); if ( ! $body ) { return null; } // Icecast can emit invalid JSON for empty fields ("title": ,). Patch the common case. $body = preg_replace( '/"([a-z_]+)":\s*,/', '"$1": "",', $body ); $json = json_decode( $body, true ); if ( empty( $json['icestats'] ) ) { return null; } $sources = isset( $json['icestats']['source'] ) ? $json['icestats']['source'] : array(); if ( isset( $sources['listenurl'] ) ) { $sources = array( $sources ); } // Remote data: keep only well-formed source entries. $sources = is_array( $sources ) ? array_values( array_filter( $sources, 'is_array' ) ) : array(); if ( empty( $sources ) ) { return array( 'title' => '', 'artist' => '', 'raw' => '', 'live' => false, 'server' => 'icecast', 'listeners' => null, ); } $mount = ! empty( $source['mount'] ) ? $source['mount'] : Resolver::mount_from_url( $source['stream_url'] ); $match = null; foreach ( $sources as $src ) { $listen = isset( $src['listenurl'] ) && is_string( $src['listenurl'] ) ? $src['listenurl'] : ''; if ( $mount && $listen && substr( (string) wp_parse_url( $listen, PHP_URL_PATH ), -strlen( $mount ) ) === $mount ) { $match = $src; break; } } if ( ! $match ) { $match = $sources[0]; } $raw = isset( $match['title'] ) && is_scalar( $match['title'] ) ? (string) $match['title'] : ''; $parts = Resolver::split_title( $raw, isset( $match['artist'] ) && is_scalar( $match['artist'] ) ? (string) $match['artist'] : '' ); return array( 'title' => $parts['title'], 'artist' => $parts['artist'], 'raw' => $raw, 'listeners' => isset( $match['listeners'] ) ? (int) $match['listeners'] : null, 'live' => true, 'server' => 'icecast', 'bitrate' => isset( $match['bitrate'] ) ? (int) $match['bitrate'] : null, 'server_name' => isset( $match['server_name'] ) && is_scalar( $match['server_name'] ) ? (string) $match['server_name'] : '', ); } }