├── static ├── nopic.jpg ├── favicon.ico ├── player.swf ├── apple-touch-icon.png ├── style.css └── music.js ├── .editorconfig ├── LICENSE ├── index.php ├── README.md ├── template └── index.php └── core ├── Curl.php └── music.php /static/nopic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/music/master/static/nopic.jpg -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/music/master/static/favicon.ico -------------------------------------------------------------------------------- /static/player.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/music/master/static/player.swf -------------------------------------------------------------------------------- /static/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YiuChoi/music/master/static/apple-touch-icon.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 4 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Maicong 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://github.com/maicong/music 8 | * @since 1.2.6 9 | * 10 | */ 11 | 12 | define('MC_CORE', true); 13 | 14 | define('MC_VERSION', '1.2.6'); 15 | 16 | // SoundCloud 客户端 ID,如果失效请更改 17 | define('MC_SC_CLIENT_ID', '2t9loNQH90kzJcsFCODdigxfp325aq4z'); 18 | 19 | // Curl 代理地址,解决翻墙问题。例如:define('MC_PROXY', 'http://10.10.10.10:8123'); 20 | define('MC_PROXY', false); 21 | 22 | // 核心文件目录; 23 | define('MC_CORE_DIR', __DIR__.'/core'); 24 | 25 | // 模版文件目录; 26 | define('MC_TPL_DIR', __DIR__.'/template'); 27 | 28 | // PHP 版本判断 29 | if (version_compare(phpversion(), '5.4', '<')) { 30 | echo sprintf( 31 | '

程序运行失败:

您的 PHP 版本低于最低要求 5.4,当前版本为 %s
', 32 | phpversion() 33 | ); 34 | exit; 35 | } 36 | 37 | // 支持的网站 38 | $music_type_list = array( 39 | 'netease' => '网易', 40 | 'qq' => 'QQ', 41 | 'kugou' => '酷狗', 42 | 'kuwo' => '酷我', 43 | 'xiami' => '虾米', 44 | 'baidu' => '百度', 45 | '1ting' => '一听', 46 | 'migu' => '咪咕', 47 | 'lizhi' => '荔枝', 48 | 'qingting' => '蜻蜓', 49 | 'ximalaya' => '喜马拉雅', 50 | '5sing' => '5sing', 51 | 'soundcloud' => 'SoundCloud' 52 | ); 53 | 54 | require_once(MC_CORE_DIR.'/music.php'); 55 | 56 | if (server('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest') { 57 | $music_input = trim(post('music_input')); 58 | $music_filter = post('music_filter'); 59 | $music_type = post('music_type'); 60 | $music_valid_patterns = array( 61 | 'name' => '/^.+$/i', 62 | 'id' => '/^[\w\/\|]+$/i', 63 | 'url' => '/^https?:\/\/\S+$/i' 64 | ); 65 | 66 | if (!$music_input || !$music_filter || !$music_type) { 67 | response('', 403, '(°ー°〃) 传入的数据不对啊'); 68 | } 69 | 70 | if ($music_filter !== 'url' && !in_array($music_type, array_keys($music_type_list), true)) { 71 | response('', 403, '(°ー°〃) 目前还不支持这个网站'); 72 | } 73 | 74 | if (!preg_match($music_valid_patterns[$music_filter], $music_input)) { 75 | response('', 403, '(・-・*) 请检查您的输入是否正确'); 76 | } 77 | 78 | switch ($music_filter) { 79 | case 'name': 80 | $music_response = maicong_get_song_by_name($music_input, $music_type); 81 | break; 82 | case 'id': 83 | $music_response = maicong_get_song_by_id($music_input, $music_type); 84 | break; 85 | case 'url': 86 | $music_response = maicong_get_song_by_url($music_input); 87 | break; 88 | } 89 | 90 | if (empty($music_response)) { 91 | response('', 404, 'ㄟ( ▔, ▔ )ㄏ 没有找到相关信息'); 92 | } 93 | 94 | response($music_response, 200, ''); 95 | } 96 | 97 | include_once(MC_TPL_DIR.'/index.php'); 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 麦葱特制多站合一音乐搜索解决方案 2 | 3 | ## (๑•̀ㅂ•́)و✧ 4 | 5 | 目前支持搜索试听以下网站音乐: 6 | 7 | > [网易云音乐](http://music.163.com/) 8 | > [QQ 音乐](http://y.qq.com/) 9 | > [酷狗音乐](http://www.kugou.com/) 10 | > [酷我音乐](http://www.kuwo.cn/) 11 | > [虾米音乐](http://www.xiami.com/) 12 | > [百度音乐](http://music.baidu.com/) 13 | > [一听音乐](http://www.1ting.com/) 14 | > [咪咕音乐](http://music.migu.cn/) 15 | > [荔枝 FM](http://www.lizhi.fm/) 16 | > [蜻蜓 FM](http://www.qingting.fm/) 17 | > [喜马拉雅 FM](http://www.ximalaya.com/) 18 | > [5sing 原创音乐](http://5sing.kugou.com/) 19 | > [SoundCloud](https://soundcloud.com/) 20 | 21 | 数据调用的是各音频网站 JSON 接口! 22 | 23 | 问我怎么来的?噗,抓包发现的。。。 24 | 25 | 有的接口并不是开放的 API 接口,随时可能失效,所以本项目相关代码仅供参考。 26 | 27 | [点击下载源代码](https://github.com/maicong/music/archive/master.zip) 28 | 29 | ## Demo / 演示 30 | 31 | [http://music.2333.me/](http://music.2333.me/ "音乐搜索器") 32 | 33 | 如果获取失败什么的,可以到 [我的博客](https://maicong.me/msg) 留言告诉我。 34 | 35 | ## Changelog / 更新日志 36 | 37 | - 2017.08.03 `v1.2.6` 更新页脚和注释 38 | - 2017.08.03 `v1.2.6` 增加低版本提示,优化 蜻蜓 FM 的 songid 代码 39 | - 2017.08.01 `v1.2.5` 增加对 喜马拉雅 FM 的支持,修复 url 无法获取问题 40 | - 2017.07.26 `v1.2.4` 优化代码兼容性 41 | - 2017.07.24 `v1.2.3` 优化目录结构和模版 42 | - 2017.07.20 `v1.2.2` 优化回调代码 43 | - 2017.07.20 `v1.2.1` 更新正则匹配规则 44 | - 2017.07.19 `v1.2.0` 修复正则表达式问题 45 | - 2017.07.19 `v1.1.9` 增加对蜻蜓 FM 的支持 (resolve [#6](https://github.com/maicong/music/issues/6)) 46 | - 2017.07.10 `v1.1.8` 修复 api 请求接口问题 47 | - 2017.07.05 `v1.1.7` 增加对 荔枝 FM 的支持 48 | - 2017.06.26 `v1.1.6` 修复数组写法兼容性 49 | - 2017.05.19 `v1.1.5` 修复 网易云音乐 音乐链接失效问题 50 | - 2017.04.28 `v1.1.4` 更新 QQ 音乐 API 接口,优化代码 51 | - 2017.04.21 `v1.1.3` 优化代码和播放器视觉 52 | - 2017.04.20 `v1.1.2` 更新音乐地址匹配规则 53 | - 2017.03.24 `v1.1.1` 移除对天天动听的支持,修复无法获取咪咕音乐的问题,更新 SoundCloud client_id 54 | - 2017.03.23 `v1.1.0` 更新外链资源地址,优化代码 55 | - 2015.06.15 `v1.0.4` 增加对 SoundCloud 的支持,增加代理支持,修复音乐名称识别问题,优化代码 56 | - 2015.06.13 `v1.0.3` 增加对 天天动听、咪咕 的支持 57 | - 2015.06.12 `v1.0.2` 增加对 5sing 的支持 (开源发布) 58 | - 2015.06.12 `v1.0.1` 代码优化 + BUG修复 59 | - 2015.06.10 `v1.0.0` 音乐搜索器上线 60 | 61 | ## Help / 数据获取失败解决方案 62 | 63 | 方案1: 64 | 65 | ``` 66 | 修改 index.php 文件里的 MC_PROXY 为您的代理地址 67 | 将 core/music.php 里需要代理的 URL 'proxy' => false 改为 'proxy' => true 68 | ``` 69 | 70 | 方案2: 71 | 72 | ``` 73 | 在 music.php 里查找 setTimeout,将其后面的数值 20 改为更大。 74 | 在 static/music.js 里查找 data: post_data,将其上面的数值 30000 改为更大。 75 | ``` 76 | 77 | 方案3: 78 | 79 | ``` 80 | 服务器要支持 curl。 81 | 更换服务器,选择延迟更低的服务器。 82 | ``` 83 | 84 | ## License / 开源协议 85 | 86 | ``` 87 | The MIT License (MIT) 88 | 89 | Copyright (c) 2015 Maicong 90 | 91 | Permission is hereby granted, free of charge, to any person obtaining a copy 92 | of this software and associated documentation files (the "Software"), to deal 93 | in the Software without restriction, including without limitation the rights 94 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 95 | copies of the Software, and to permit persons to whom the Software is 96 | furnished to do so, subject to the following conditions: 97 | 98 | The above copyright notice and this permission notice shall be included in all 99 | copies or substantial portions of the Software. 100 | 101 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 102 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 103 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 104 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 105 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 106 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 107 | SOFTWARE. 108 | ``` 109 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 音乐搜索器 - CSS 文件 4 | * 5 | * @author MaiCong 6 | * @link https://github.com/maicong/music 7 | * @since 1.1.9 8 | * 9 | */ 10 | 11 | html { 12 | font-family: -apple-system, BlinkMacSystemFont, "San Francisco", 13 | "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", "WenQuanYi Micro Hei", 14 | "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", 15 | "Droid Sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif, 16 | "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 17 | height: 100%; 18 | -webkit-text-size-adjust: 100%; 19 | -moz-text-size-adjust: 100%; 20 | -ms-text-size-adjust: 100%; 21 | text-size-adjust: 100%; 22 | } 23 | body { 24 | margin: 0; 25 | -webkit-tap-highlight-color: transparent; 26 | -webkit-font-smoothing: subpixel-antialiased; 27 | } 28 | a { 29 | -webkit-transition: all .3s; 30 | -moz-transition: all .3s; 31 | -ms-transition: all .3s; 32 | -o-transition: all .3s; 33 | transition: all .3s; 34 | } 35 | .about { 36 | background: #fff; 37 | color: #7f8c8d; 38 | height: 100%; 39 | min-height: 500px; 40 | } 41 | .about-color { 42 | color: #34495e; 43 | } 44 | .about-title { 45 | font-size: 180%; 46 | text-align: center; 47 | } 48 | .main { 49 | margin: 60px 0; 50 | } 51 | .am-alert { 52 | display: none; 53 | } 54 | .music-tabs > li > a { 55 | padding: 0.5em 1em; 56 | cursor: pointer; 57 | } 58 | .music-tips { 59 | line-height: 1.5; 60 | overflow: hidden; 61 | } 62 | .music-tips .more { 63 | height: 30px; 64 | line-height: 30px; 65 | text-align: center; 66 | font-size: 14px; 67 | color: #666; 68 | background: #eee; 69 | cursor: pointer; 70 | } 71 | .music-tips blockquote { 72 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 73 | font-size: 13px; 74 | } 75 | .music-tips p:nth-child(5) ~ p { 76 | display: none; 77 | } 78 | .music-tips p span { 79 | display: inline-block; 80 | min-width: 50px; 81 | } 82 | .music-tips p b { 83 | font-weight: 500; 84 | color: #c7254e; 85 | } 86 | .music-main { 87 | display: none; 88 | } 89 | .music-main input { 90 | text-overflow: ellipsis; 91 | } 92 | .music-main input:focus, 93 | .music-main input:hover { 94 | background: #eee; 95 | border-color: #ccc; 96 | color: #222; 97 | } 98 | .music-type .am-radio-inline, 99 | .music-type label { 100 | color: #7f8c8d; 101 | } 102 | .music-type .am-icon-unchecked, 103 | .music-type .am-icon-checked { 104 | color: #0e90d2; 105 | } 106 | .mejs-container { 107 | min-width: 100%; 108 | } 109 | .am-popup-bd { 110 | height: 100%; 111 | } 112 | .footer { 113 | position: relative; 114 | left: 0; 115 | bottom: 0; 116 | width: 100%; 117 | overflow: hidden; 118 | } 119 | .footer p { 120 | color: #7f8c8d; 121 | margin: 0; 122 | padding: 15px; 123 | text-align: center; 124 | background: #2d3e50; 125 | } 126 | .footer p a { 127 | color: #7f8c8d; 128 | } 129 | .footer p a:hover { 130 | color: #bbb; 131 | } 132 | .audio-player { 133 | position: relative; 134 | width: 100%; 135 | background-color: #eee; 136 | border: 1px solid #ccc; 137 | } 138 | .audio-player .amazingaudioplayer-audios { 139 | display: none; 140 | } 141 | .audio-player .amazingaudioplayer-image { 142 | display: block; 143 | position: absolute; 144 | top: 8px; 145 | left: 12px; 146 | margin: 4px; 147 | width: 100px; 148 | height: 100px; 149 | overflow: hidden; 150 | background: #ddd; 151 | border: 1px solid #ddd; 152 | border-radius: 5px; 153 | } 154 | .audio-player .amazingaudioplayer-image img { 155 | max-width: 100%; 156 | height: auto; 157 | vertical-align: middle; 158 | } 159 | .audio-player .amazingaudioplayer-text { 160 | display: block; 161 | position: relative; 162 | top: 12px; 163 | padding: 0 12px 0 136px; 164 | overflow: hidden; 165 | } 166 | .audio-player .amazingaudioplayer-title { 167 | display: block; 168 | color: #333; 169 | font-size: 16px; 170 | min-height: 26px; 171 | white-space: nowrap; 172 | text-overflow: ellipsis; 173 | overflow: hidden; 174 | } 175 | .audio-player .amazingaudioplayer-info { 176 | display: block; 177 | color: #666; 178 | font-size: 12px; 179 | min-height: 20px; 180 | white-space: nowrap; 181 | text-overflow: ellipsis; 182 | overflow: hidden; 183 | } 184 | .audio-player .amazingaudioplayer-bar { 185 | position: relative; 186 | height: 135px; 187 | } 188 | .audio-player .amazingaudioplayer-icon { 189 | display: block; 190 | cursor: pointer; 191 | width: 32px; 192 | height: 32px; 193 | line-height: 32px; 194 | font-size: 12px; 195 | color: #888; 196 | text-align: center; 197 | background-color: #ccc; 198 | border: 1px solid #bbb; 199 | border-radius: 50%; 200 | transition: all .2s; 201 | -webkit-transition: all .2s; 202 | -moz-transition: all .2s; 203 | -ms-transition: all .2s; 204 | -o-transition: all .2s; 205 | -webkit-user-select: none; 206 | -moz-user-select: none; 207 | user-select: none; 208 | } 209 | .audio-player .amazingaudioplayer-icon:hover, 210 | .audio-player .amazingaudioplayer-icon:active { 211 | color: #555; 212 | transition: all .2s; 213 | -webkit-transition: all .2s; 214 | -moz-transition: all .2s; 215 | -ms-transition: all .2s; 216 | -o-transition: all .2s; 217 | } 218 | .audio-player .amazingaudioplayer-bar .display-block { 219 | color: #666; 220 | } 221 | .audio-player .amazingaudioplayer-playpause { 222 | position: absolute; 223 | left: 175px; 224 | top: 32px; 225 | } 226 | .audio-player .amazingaudioplayer-play { 227 | position: relative; 228 | } 229 | .audio-player .amazingaudioplayer-pause { 230 | position: relative; 231 | } 232 | .audio-player .amazingaudioplayer-prev { 233 | position: absolute; 234 | left: 135px; 235 | top: 32px; 236 | } 237 | .audio-player .amazingaudioplayer-next { 238 | position: absolute; 239 | left: 215px; 240 | top: 32px; 241 | } 242 | .audio-player .amazingaudioplayer-loop { 243 | position: absolute; 244 | top: 32px; 245 | right: 12px; 246 | } 247 | .audio-player .amazingaudioplayer-volume { 248 | position: absolute; 249 | top: 32px; 250 | right: 53px; 251 | } 252 | .audio-player .amazingaudioplayer-volume:hover .amazingaudioplayer-icon { 253 | color: #555; 254 | } 255 | .audio-player .amazingaudioplayer-progress { 256 | display: block; 257 | position: absolute; 258 | left: 12px; 259 | right: 12px; 260 | top: 100px; 261 | height: 8px; 262 | margin: 8px 4px; 263 | background-color: #e5e5e5; 264 | cursor: pointer; 265 | overflow: hidden; 266 | } 267 | .audio-player .amazingaudioplayer-progress-loaded { 268 | display: block; 269 | position: absolute; 270 | left: 0; 271 | top: 0; 272 | height: 100%; 273 | background-color: #ccc; 274 | border-radius: 4px; 275 | } 276 | .audio-player .amazingaudioplayer-progress-played { 277 | display: block; 278 | position: absolute; 279 | left: 0; 280 | top: 0; 281 | height: 100%; 282 | background-color: #999; 283 | border-radius: 4px; 284 | } 285 | .audio-player .amazingaudioplayer-time { 286 | position: relative; 287 | top: 80px; 288 | left: 12px; 289 | color: #555; 290 | font-size: 12px; 291 | line-height: 24px; 292 | margin: 0 4px; 293 | } 294 | .audio-player .amazingaudioplayer-volume-bar { 295 | display: none; 296 | position: absolute; 297 | left: 3px; 298 | bottom: 100%; 299 | width: 8px; 300 | height: 35px; 301 | padding: 8px; 302 | margin-bottom: 5px; 303 | background-color: #ccc; 304 | border: 1px solid #bbb; 305 | border-radius: 4px; 306 | -webkit-box-sizing: content-box; 307 | -moz-box-sizing: content-box; 308 | box-sizing: content-box; 309 | -webkit-user-select: none; 310 | -moz-user-select: none; 311 | user-select: none; 312 | } 313 | .audio-player .amazingaudioplayer-volume-bar-adjust { 314 | position: relative; 315 | display: block; 316 | width: 100%; 317 | height: 100%; 318 | cursor: pointer; 319 | background-color: #aaa; 320 | } 321 | .audio-player .amazingaudioplayer-volume-bar-adjust-active { 322 | position: absolute; 323 | display: block; 324 | left: 0; 325 | bottom: 0; 326 | width: 100%; 327 | height: 60%; 328 | background-color: #555; 329 | } 330 | .audio-player .amazingaudioplayer-tracklist { 331 | display: block; 332 | width: 100%; 333 | } 334 | .audio-player .amazingaudioplayer-tracklist-container { 335 | display: block; 336 | position: relative; 337 | padding: 12px; 338 | border-top: 1px solid #ccc; 339 | } 340 | .audio-player .amazingaudioplayer-tracks-wrapper { 341 | position: relative; 342 | overflow: hidden; 343 | } 344 | .audio-player .amazingaudioplayer-tracks { 345 | display: block; 346 | position: relative; 347 | list-style-type: none; 348 | margin: 0; 349 | padding: 0; 350 | } 351 | .audio-player .amazingaudioplayer-track-item { 352 | position: relative; 353 | cursor: pointer; 354 | white-space: nowrap; 355 | color: #555; 356 | font-size: 12px; 357 | line-height: 20px; 358 | padding-right: 35%; 359 | text-overflow: ellipsis; 360 | overflow: hidden; 361 | } 362 | .audio-player .amazingaudioplayer-track-item span { 363 | position: absolute; 364 | top: 0; 365 | right: 0; 366 | max-width: 30%; 367 | text-overflow: ellipsis; 368 | overflow: hidden; 369 | } 370 | .audio-player .amazingaudioplayer-track-item-active { 371 | font-weight: 700; 372 | } 373 | .audio-player .amazingaudioplayer-track-item-duration { 374 | position: absolute; 375 | top: 0; 376 | right: 0; 377 | } 378 | .audio-player .display-none { 379 | display: none; 380 | } 381 | .audio-player .display-block { 382 | display: block; 383 | } 384 | -------------------------------------------------------------------------------- /template/index.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 音乐搜索器 - 多站合一音乐搜索,音乐在线试听 - By 麦葱 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |

34 | 2333 实验室 35 |

36 | 40 | 50 |
51 |
52 |
53 |
54 |
55 |

音乐搜索器

56 |

麦葱特制多站合一音乐搜索解决方案

57 |
58 |
59 |
60 |
61 |
62 | 73 |
74 | 75 |
76 |
77 |
78 | $val) { ?> 79 | 83 | 84 |
85 | 86 |
87 |
88 |
89 | 成功 Get √ 返回继续 90 |
91 |
92 |
93 | 94 | 95 |
96 |
97 |
98 |
99 | 100 | 101 |
102 |
103 |
104 |
105 |
106 |
107 | 108 | 109 |
110 |
111 |
112 |
113 | 114 | 115 |
116 |
117 |
118 |
119 |
120 |
121 |

帮助:

122 |

123 | 标红音乐 ID下划线 表示 音乐地址 124 |

125 |
126 |

蜻蜓 FM 的 音乐 ID 需要使用 | (管道符) 组合,例如 158696|5266259

127 |
128 |

129 | 网易:http://music.163.com/#/song?id=25906124 130 |

131 |

132 | QQ:http://y.qq.com/n/yqq/song/002B2EAA3brD5b.html 133 |

134 |

135 | 酷狗:http://m.kugou.com/play/info/08228af3cb404e8a4e7e9871bf543ff6 136 |

137 |

138 | 酷我:http://www.kuwo.cn/yinyue/382425/ 139 |

140 |

141 | 虾米:http://www.xiami.com/song/2113248 142 |

143 |

144 | 百度:http://music.baidu.com/song/556113 145 |

146 |

147 | 一听:http://www.1ting.com/player/b6/player_220513.html 148 |

149 |

150 | 咪咕:http://music.migu.cn/#/song/1002531572/P7Z1Y1L1N1/3/001002C 151 |

152 |

153 | 荔枝:http://www.lizhi.fm/1947925/2498707770886461446 154 |

155 |

156 | 蜻蜓:http://www.qingting.fm/channels/158696/programs/5266259 157 |

158 |

159 | 喜马拉雅:http://www.ximalaya.com/51701370/sound/24755731 160 |

161 |

162 | 5sing:http://5sing.kugou.com/yc/1089684.html 163 |

164 |

165 | SoundCloud (ID):soundcloud://sounds:197401418 (请查看源码) 166 |

167 |

168 | SoundCloud (地址):https://soundcloud.com/user2953945/tr-n-d-ch-t-n-eason-chan-kh-ng 169 |

170 |
查看更多
171 |
172 |
173 |
174 |
175 |
176 |
177 |

版权声明

178 | × 179 |
180 |
181 |

本站音频文件来自各网站接口,本站不会修改任何音频文件

182 |

音频版权来自各网站,本站只提供数据查询服务,不提供任何音频存储和贩卖服务

183 |
184 |
185 |
186 |
187 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /core/Curl.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://github.com/maicong/music 8 | * @since 1.2.3 9 | * 10 | */ 11 | 12 | if (!defined('MC_CORE') || !defined('MC_SC_CLIENT_ID')) { 13 | header("Location: /"); 14 | exit(); 15 | } 16 | 17 | class Curl 18 | { 19 | const VERSION = '3.6.5'; 20 | const DEFAULT_TIMEOUT = 30; 21 | 22 | public $curl; 23 | public $id = null; 24 | 25 | public $error = false; 26 | public $error_code = 0; 27 | public $error_message = null; 28 | 29 | public $curl_error = false; 30 | public $curl_error_code = 0; 31 | public $curl_error_message = null; 32 | 33 | public $http_error = false; 34 | public $http_status_code = 0; 35 | public $http_error_message = null; 36 | 37 | public $base_url = null; 38 | public $url = null; 39 | public $request_headers = null; 40 | public $response_headers = null; 41 | public $raw_response_headers = ''; 42 | public $response = null; 43 | public $raw_response = null; 44 | 45 | public $before_send_function = null; 46 | public $download_complete_function = null; 47 | private $success_function = null; 48 | private $error_function = null; 49 | private $complete_function = null; 50 | 51 | private $cookies = array(); 52 | private $headers = array(); 53 | private $options = array(); 54 | 55 | private $json_decoder = null; 56 | private $json_pattern = '/^(?:application|text)\/(?:[a-z]+(?:[\.-][0-9a-z]+){0,}[\+\.]|x-)?json(?:-[a-z]+)?/i'; 57 | private $xml_pattern = '~^(?:text/|application/(?:atom\+|rss\+)?)xml~i'; 58 | 59 | /** 60 | * Construct 61 | * 62 | * @access public 63 | * @param $base_url 64 | * @throws \ErrorException 65 | */ 66 | public function __construct($base_url = null) 67 | { 68 | if (!extension_loaded('curl')) { 69 | throw new \ErrorException('cURL library is not loaded'); 70 | } 71 | 72 | $this->curl = curl_init(); 73 | $this->id = 1; 74 | $this->setDefaultUserAgent(); 75 | $this->setDefaultJsonDecoder(); 76 | $this->setDefaultTimeout(); 77 | $this->setOpt(CURLINFO_HEADER_OUT, true); 78 | $this->setOpt(CURLOPT_HEADERFUNCTION, array($this, 'headerCallback')); 79 | $this->setOpt(CURLOPT_RETURNTRANSFER, true); 80 | $this->headers = new CaseInsensitiveArray(); 81 | $this->setURL($base_url); 82 | } 83 | 84 | /** 85 | * Before Send 86 | * 87 | * @access public 88 | * @param $callback 89 | */ 90 | public function beforeSend($callback) 91 | { 92 | $this->before_send_function = $callback; 93 | } 94 | 95 | /** 96 | * Build Post Data 97 | * 98 | * @access public 99 | * @param $data 100 | * 101 | * @return array|string 102 | */ 103 | public function buildPostData($data) 104 | { 105 | if (is_array($data)) { 106 | if (self::is_array_multidim($data)) { 107 | if (isset($this->headers['Content-Type']) && 108 | preg_match($this->json_pattern, $this->headers['Content-Type'])) { 109 | $json_str = json_encode($data); 110 | if (!($json_str === false)) { 111 | $data = $json_str; 112 | } 113 | } else { 114 | $data = self::http_build_multi_query($data); 115 | } 116 | } else { 117 | $binary_data = false; 118 | foreach ($data as $key => $value) { 119 | // Fix "Notice: Array to string conversion" when $value in 120 | // curl_setopt($ch, CURLOPT_POSTFIELDS, $value) is an array 121 | // that contains an empty array. 122 | if (is_array($value) && empty($value)) { 123 | $data[$key] = ''; 124 | // Fix "curl_setopt(): The usage of the @filename API for 125 | // file uploading is deprecated. Please use the CURLFile 126 | // class instead". 127 | } elseif (is_string($value) && strpos($value, '@') === 0) { 128 | $binary_data = true; 129 | if (class_exists('CURLFile')) { 130 | $data[$key] = new \CURLFile(substr($value, 1)); 131 | } 132 | } elseif ($value instanceof \CURLFile) { 133 | $binary_data = true; 134 | } 135 | } 136 | 137 | if (!$binary_data) { 138 | if (isset($this->headers['Content-Type']) && 139 | preg_match($this->json_pattern, $this->headers['Content-Type'])) { 140 | $json_str = json_encode($data); 141 | if (!($json_str === false)) { 142 | $data = $json_str; 143 | } 144 | } else { 145 | $data = http_build_query($data, '', '&'); 146 | } 147 | } 148 | } 149 | } 150 | 151 | return $data; 152 | } 153 | 154 | /** 155 | * Call 156 | * 157 | * @access public 158 | */ 159 | public function call() 160 | { 161 | $args = func_get_args(); 162 | $function = array_shift($args); 163 | if (is_callable($function)) { 164 | array_unshift($args, $this); 165 | call_user_func_array($function, $args); 166 | } 167 | } 168 | 169 | /** 170 | * Close 171 | * 172 | * @access public 173 | */ 174 | public function close() 175 | { 176 | if (is_resource($this->curl)) { 177 | curl_close($this->curl); 178 | } 179 | $this->options = null; 180 | $this->json_decoder = null; 181 | } 182 | 183 | /** 184 | * Complete 185 | * 186 | * @access public 187 | * @param $callback 188 | */ 189 | public function complete($callback) 190 | { 191 | $this->complete_function = $callback; 192 | } 193 | 194 | /** 195 | * Progress 196 | * 197 | * @access public 198 | * @param $callback 199 | */ 200 | public function progress($callback) 201 | { 202 | $this->setOpt(CURLOPT_PROGRESSFUNCTION, $callback); 203 | $this->setOpt(CURLOPT_NOPROGRESS, false); 204 | } 205 | 206 | /** 207 | * Delete 208 | * 209 | * @access public 210 | * @param $url 211 | * @param $query_parameters 212 | * @param $data 213 | * 214 | * @return string 215 | */ 216 | public function delete($url, $query_parameters = array(), $data = array()) 217 | { 218 | if (is_array($url)) { 219 | $data = $query_parameters; 220 | $query_parameters = $url; 221 | $url = $this->base_url; 222 | } 223 | 224 | $this->setURL($url, $query_parameters); 225 | $this->setOpt(CURLOPT_CUSTOMREQUEST, 'DELETE'); 226 | $this->setOpt(CURLOPT_POSTFIELDS, $this->buildPostData($data)); 227 | return $this->exec(); 228 | } 229 | 230 | /** 231 | * Download Complete 232 | * 233 | * @access public 234 | * @param $fh 235 | */ 236 | public function downloadComplete($fh) 237 | { 238 | if (!$this->error && $this->download_complete_function) { 239 | rewind($fh); 240 | $this->call($this->download_complete_function, $fh); 241 | $this->download_complete_function = null; 242 | } 243 | 244 | if (is_resource($fh)) { 245 | fclose($fh); 246 | } 247 | 248 | // Fix "PHP Notice: Use of undefined constant STDOUT" when reading the 249 | // PHP script from stdin. Using null causes "Warning: curl_setopt(): 250 | // supplied argument is not a valid File-Handle resource". 251 | if (!defined('STDOUT')) { 252 | define('STDOUT', fopen('php://stdout', 'w')); 253 | } 254 | 255 | // Reset CURLOPT_FILE with STDOUT to avoid: "curl_exec(): CURLOPT_FILE 256 | // resource has gone away, resetting to default". 257 | $this->setOpt(CURLOPT_FILE, STDOUT); 258 | 259 | // Reset CURLOPT_RETURNTRANSFER to tell cURL to return subsequent 260 | // responses as the return value of curl_exec(). Without this, 261 | // curl_exec() will revert to returning boolean values. 262 | $this->setOpt(CURLOPT_RETURNTRANSFER, true); 263 | } 264 | 265 | /** 266 | * Download 267 | * 268 | * @access public 269 | * @param $url 270 | * @param $mixed_filename 271 | * 272 | * @return boolean 273 | */ 274 | public function download($url, $mixed_filename) 275 | { 276 | if (is_callable($mixed_filename)) { 277 | $this->download_complete_function = $mixed_filename; 278 | $fh = tmpfile(); 279 | } else { 280 | $filename = $mixed_filename; 281 | $fh = fopen($filename, 'wb'); 282 | } 283 | 284 | $this->setOpt(CURLOPT_FILE, $fh); 285 | $this->get($url); 286 | $this->downloadComplete($fh); 287 | 288 | return ! $this->error; 289 | } 290 | 291 | /** 292 | * Error 293 | * 294 | * @access public 295 | * @param $callback 296 | */ 297 | public function error($callback) 298 | { 299 | $this->error_function = $callback; 300 | } 301 | 302 | /** 303 | * Exec 304 | * 305 | * @access public 306 | * @param $ch 307 | * 308 | * @return string 309 | */ 310 | public function exec($ch = null) 311 | { 312 | if (!($ch === null)) { 313 | $this->raw_response = curl_multi_getcontent($ch); 314 | } else { 315 | $this->call($this->before_send_function); 316 | $this->raw_response = curl_exec($this->curl); 317 | $this->curl_error_code = curl_errno($this->curl); 318 | } 319 | 320 | $this->curl_error_message = curl_error($this->curl); 321 | $this->curl_error = !($this->curl_error_code === 0); 322 | $this->http_status_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); 323 | $this->http_error = in_array(floor($this->http_status_code / 100), array(4, 5)); 324 | $this->error = $this->curl_error || $this->http_error; 325 | $this->error_code = $this->error ? ($this->curl_error ? $this->curl_error_code : $this->http_status_code) : 0; 326 | 327 | $this->request_headers = $this->parseRequestHeaders(curl_getinfo($this->curl, CURLINFO_HEADER_OUT)); 328 | $this->response_headers = $this->parseResponseHeaders($this->raw_response_headers); 329 | list($this->response, $this->raw_response) = $this->parseResponse($this->response_headers, $this->raw_response); 330 | 331 | $this->http_error_message = ''; 332 | if ($this->error) { 333 | if (isset($this->response_headers['Status-Line'])) { 334 | $this->http_error_message = $this->response_headers['Status-Line']; 335 | } 336 | } 337 | $this->error_message = $this->curl_error ? $this->curl_error_message : $this->http_error_message; 338 | 339 | if (!$this->error) { 340 | $this->call($this->success_function); 341 | } else { 342 | $this->call($this->error_function); 343 | } 344 | 345 | $this->call($this->complete_function); 346 | 347 | return $this->response; 348 | } 349 | 350 | /** 351 | * Get 352 | * 353 | * @access public 354 | * @param $url 355 | * @param $data 356 | * 357 | * @return string 358 | */ 359 | public function get($url, $data = array()) 360 | { 361 | if (is_array($url)) { 362 | $data = $url; 363 | $url = $this->base_url; 364 | } 365 | $this->setURL($url, $data); 366 | $this->setOpt(CURLOPT_CUSTOMREQUEST, 'GET'); 367 | $this->setOpt(CURLOPT_HTTPGET, true); 368 | return $this->exec(); 369 | } 370 | 371 | /** 372 | * Get Opt 373 | * 374 | * @access public 375 | * @param $option 376 | * 377 | * @return mixed 378 | */ 379 | public function getOpt($option) 380 | { 381 | return $this->options[$option]; 382 | } 383 | 384 | /** 385 | * Head 386 | * 387 | * @access public 388 | * @param $url 389 | * @param $data 390 | * 391 | * @return string 392 | */ 393 | public function head($url, $data = array()) 394 | { 395 | if (is_array($url)) { 396 | $data = $url; 397 | $url = $this->base_url; 398 | } 399 | $this->setURL($url, $data); 400 | $this->setOpt(CURLOPT_CUSTOMREQUEST, 'HEAD'); 401 | $this->setOpt(CURLOPT_NOBODY, true); 402 | return $this->exec(); 403 | } 404 | 405 | /** 406 | * Header Callback 407 | * 408 | * @access public 409 | * @param $ch 410 | * @param $header 411 | * 412 | * @return integer 413 | */ 414 | public function headerCallback($ch, $header) 415 | { 416 | $this->raw_response_headers .= $header; 417 | return strlen($header); 418 | } 419 | 420 | /** 421 | * Options 422 | * 423 | * @access public 424 | * @param $url 425 | * @param $data 426 | * 427 | * @return string 428 | */ 429 | public function options($url, $data = array()) 430 | { 431 | if (is_array($url)) { 432 | $data = $url; 433 | $url = $this->base_url; 434 | } 435 | $this->setURL($url, $data); 436 | $this->unsetHeader('Content-Length'); 437 | $this->setOpt(CURLOPT_CUSTOMREQUEST, 'OPTIONS'); 438 | return $this->exec(); 439 | } 440 | 441 | /** 442 | * Patch 443 | * 444 | * @access public 445 | * @param $url 446 | * @param $data 447 | * 448 | * @return string 449 | */ 450 | public function patch($url, $data = array()) 451 | { 452 | if (is_array($url)) { 453 | $data = $url; 454 | $url = $this->base_url; 455 | } 456 | $this->setURL($url); 457 | $this->unsetHeader('Content-Length'); 458 | $this->setOpt(CURLOPT_CUSTOMREQUEST, 'PATCH'); 459 | $this->setOpt(CURLOPT_POSTFIELDS, $data); 460 | return $this->exec(); 461 | } 462 | 463 | /** 464 | * Post 465 | * 466 | * @access public 467 | * @param $url 468 | * @param $data 469 | * 470 | * @return string 471 | */ 472 | public function post($url, $data = array()) 473 | { 474 | if (is_array($url)) { 475 | $data = $url; 476 | $url = $this->base_url; 477 | } 478 | 479 | if (is_array($data) && empty($data)) { 480 | $this->unsetHeader('Content-Length'); 481 | } 482 | 483 | $this->setURL($url); 484 | $this->setOpt(CURLOPT_CUSTOMREQUEST, 'POST'); 485 | $this->setOpt(CURLOPT_POST, true); 486 | $this->setOpt(CURLOPT_POSTFIELDS, $this->buildPostData($data)); 487 | return $this->exec(); 488 | } 489 | 490 | /** 491 | * Put 492 | * 493 | * @access public 494 | * @param $url 495 | * @param $data 496 | * 497 | * @return string 498 | */ 499 | public function put($url, $data = array()) 500 | { 501 | if (is_array($url)) { 502 | $data = $url; 503 | $url = $this->base_url; 504 | } 505 | $this->setURL($url); 506 | $this->setOpt(CURLOPT_CUSTOMREQUEST, 'PUT'); 507 | $put_data = $this->buildPostData($data); 508 | if (empty($this->options[CURLOPT_INFILE]) && empty($this->options[CURLOPT_INFILESIZE])) { 509 | $this->setHeader('Content-Length', strlen($put_data)); 510 | } 511 | $this->setOpt(CURLOPT_POSTFIELDS, $put_data); 512 | return $this->exec(); 513 | } 514 | 515 | /** 516 | * Set Basic Authentication 517 | * 518 | * @access public 519 | * @param $username 520 | * @param $password 521 | */ 522 | public function setBasicAuthentication($username, $password = '') 523 | { 524 | $this->setOpt(CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 525 | $this->setOpt(CURLOPT_USERPWD, $username . ':' . $password); 526 | } 527 | 528 | /** 529 | * Set Digest Authentication 530 | * 531 | * @access public 532 | * @param $username 533 | * @param $password 534 | */ 535 | public function setDigestAuthentication($username, $password = '') 536 | { 537 | $this->setOpt(CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); 538 | $this->setOpt(CURLOPT_USERPWD, $username . ':' . $password); 539 | } 540 | 541 | /** 542 | * Set Cookie 543 | * 544 | * @access public 545 | * @param $key 546 | * @param $value 547 | */ 548 | public function setCookie($key, $value) 549 | { 550 | $this->cookies[$key] = $value; 551 | $this->setOpt(CURLOPT_COOKIE, str_replace(' ', '%20', urldecode(http_build_query($this->cookies, '', '; ')))); 552 | } 553 | 554 | /** 555 | * Set Port 556 | * 557 | * @access public 558 | * @param $port 559 | */ 560 | public function setPort($port) 561 | { 562 | $this->setOpt(CURLOPT_PORT, intval($port)); 563 | } 564 | 565 | /** 566 | * Set Connect Timeout 567 | * 568 | * @access public 569 | * @param $seconds 570 | */ 571 | public function setConnectTimeout($seconds) 572 | { 573 | $this->setOpt(CURLOPT_CONNECTTIMEOUT, $seconds); 574 | } 575 | 576 | /** 577 | * Set Cookie File 578 | * 579 | * @access public 580 | * @param $cookie_file 581 | */ 582 | public function setCookieFile($cookie_file) 583 | { 584 | $this->setOpt(CURLOPT_COOKIEFILE, $cookie_file); 585 | } 586 | 587 | /** 588 | * Set Cookie Jar 589 | * 590 | * @access public 591 | * @param $cookie_jar 592 | */ 593 | public function setCookieJar($cookie_jar) 594 | { 595 | $this->setOpt(CURLOPT_COOKIEJAR, $cookie_jar); 596 | } 597 | 598 | /** 599 | * Set Default JSON Decoder 600 | * 601 | * @access public 602 | */ 603 | public function setDefaultJsonDecoder() 604 | { 605 | $this->json_decoder = function($response) { 606 | $json_obj = json_decode($response, false); 607 | if (!($json_obj === null)) { 608 | $response = $json_obj; 609 | } 610 | return $response; 611 | }; 612 | } 613 | 614 | /** 615 | * Set Default Timeout 616 | * 617 | * @access public 618 | */ 619 | public function setDefaultTimeout() 620 | { 621 | $this->setTimeout(self::DEFAULT_TIMEOUT); 622 | } 623 | 624 | /** 625 | * Set Default User Agent 626 | * 627 | * @access public 628 | */ 629 | public function setDefaultUserAgent() 630 | { 631 | $user_agent = 'PHP-Curl-Class/' . self::VERSION . ' (+https://github.com/php-curl-class/php-curl-class)'; 632 | $user_agent .= ' PHP/' . PHP_VERSION; 633 | $curl_version = curl_version(); 634 | $user_agent .= ' curl/' . $curl_version['version']; 635 | $this->setUserAgent($user_agent); 636 | } 637 | 638 | /** 639 | * Set Header 640 | * 641 | * @access public 642 | * @param $key 643 | * @param $value 644 | * 645 | * @return string 646 | */ 647 | public function setHeader($key, $value) 648 | { 649 | $this->headers[$key] = $value; 650 | $headers = array(); 651 | foreach ($this->headers as $key => $value) { 652 | $headers[$key] = $value; 653 | } 654 | $this->setOpt(CURLOPT_HTTPHEADER, array_map(function($value, $key) { 655 | return $key . ': ' . $value; 656 | }, $headers, array_keys($headers))); 657 | } 658 | 659 | /** 660 | * Set JSON Decoder 661 | * 662 | * @access public 663 | * @param $function 664 | */ 665 | public function setJsonDecoder($function) 666 | { 667 | if (is_callable($function)) { 668 | $this->json_decoder = $function; 669 | } 670 | } 671 | 672 | /** 673 | * Set Opt 674 | * 675 | * @access public 676 | * @param $option 677 | * @param $value 678 | * 679 | * @return boolean 680 | */ 681 | public function setOpt($option, $value) 682 | { 683 | $required_options = array( 684 | CURLINFO_HEADER_OUT => 'CURLINFO_HEADER_OUT', 685 | CURLOPT_RETURNTRANSFER => 'CURLOPT_RETURNTRANSFER', 686 | ); 687 | 688 | if (in_array($option, array_keys($required_options), true) && !($value === true)) { 689 | trigger_error($required_options[$option] . ' is a required option', E_USER_WARNING); 690 | } 691 | 692 | $this->options[$option] = $value; 693 | return curl_setopt($this->curl, $option, $value); 694 | } 695 | 696 | /** 697 | * Set Referer 698 | * 699 | * @access public 700 | * @param $referer 701 | */ 702 | public function setReferer($referer) 703 | { 704 | $this->setReferrer($referer); 705 | } 706 | 707 | /** 708 | * Set Referrer 709 | * 710 | * @access public 711 | * @param $referrer 712 | */ 713 | public function setReferrer($referrer) 714 | { 715 | $this->setOpt(CURLOPT_REFERER, $referrer); 716 | } 717 | 718 | /** 719 | * Set Timeout 720 | * 721 | * @access public 722 | * @param $seconds 723 | */ 724 | public function setTimeout($seconds) 725 | { 726 | $this->setOpt(CURLOPT_TIMEOUT, $seconds); 727 | } 728 | 729 | /** 730 | * Set Url 731 | * 732 | * @access public 733 | * @param $url 734 | * @param $data 735 | */ 736 | public function setURL($url, $data = array()) 737 | { 738 | $this->base_url = $url; 739 | $this->url = $this->buildURL($url, $data); 740 | $this->setOpt(CURLOPT_URL, $this->url); 741 | } 742 | 743 | /** 744 | * Set User Agent 745 | * 746 | * @access public 747 | * @param $user_agent 748 | */ 749 | public function setUserAgent($user_agent) 750 | { 751 | $this->setOpt(CURLOPT_USERAGENT, $user_agent); 752 | } 753 | 754 | /** 755 | * Success 756 | * 757 | * @access public 758 | * @param $callback 759 | */ 760 | public function success($callback) 761 | { 762 | $this->success_function = $callback; 763 | } 764 | 765 | /** 766 | * Unset Header 767 | * 768 | * @access public 769 | * @param $key 770 | */ 771 | public function unsetHeader($key) 772 | { 773 | $this->setHeader($key, ''); 774 | unset($this->headers[$key]); 775 | } 776 | 777 | /** 778 | * Verbose 779 | * 780 | * @access public 781 | * @param $on 782 | */ 783 | public function verbose($on = true) 784 | { 785 | $this->setOpt(CURLOPT_VERBOSE, $on); 786 | } 787 | 788 | /** 789 | * Destruct 790 | * 791 | * @access public 792 | */ 793 | public function __destruct() 794 | { 795 | $this->close(); 796 | } 797 | 798 | /** 799 | * Build Url 800 | * 801 | * @access private 802 | * @param $url 803 | * @param $data 804 | * 805 | * @return string 806 | */ 807 | private function buildURL($url, $data = array()) 808 | { 809 | return $url . (empty($data) ? '' : '?' . http_build_query($data)); 810 | } 811 | 812 | /** 813 | * Parse Headers 814 | * 815 | * @access private 816 | * @param $raw_headers 817 | * 818 | * @return array 819 | */ 820 | private function parseHeaders($raw_headers) 821 | { 822 | $raw_headers = preg_split('/\r\n/', $raw_headers, null, PREG_SPLIT_NO_EMPTY); 823 | $http_headers = new CaseInsensitiveArray(); 824 | 825 | $raw_headers_count = count($raw_headers); 826 | for ($i = 1; $i < $raw_headers_count; $i++) { 827 | list($key, $value) = explode(':', $raw_headers[$i], 2); 828 | $key = trim($key); 829 | $value = trim($value); 830 | // Use isset() as array_key_exists() and ArrayAccess are not compatible. 831 | if (isset($http_headers[$key])) { 832 | $http_headers[$key] .= ',' . $value; 833 | } else { 834 | $http_headers[$key] = $value; 835 | } 836 | } 837 | 838 | return array(isset($raw_headers['0']) ? $raw_headers['0'] : '', $http_headers); 839 | } 840 | 841 | /** 842 | * Parse Request Headers 843 | * 844 | * @access private 845 | * @param $raw_headers 846 | * 847 | * @return array 848 | */ 849 | private function parseRequestHeaders($raw_headers) 850 | { 851 | $request_headers = new CaseInsensitiveArray(); 852 | list($first_line, $headers) = $this->parseHeaders($raw_headers); 853 | $request_headers['Request-Line'] = $first_line; 854 | foreach ($headers as $key => $value) { 855 | $request_headers[$key] = $value; 856 | } 857 | return $request_headers; 858 | } 859 | 860 | /** 861 | * Parse Response 862 | * 863 | * @access private 864 | * @param $response_headers 865 | * @param $raw_response 866 | * 867 | * @return array 868 | */ 869 | private function parseResponse($response_headers, $raw_response) 870 | { 871 | $response = $raw_response; 872 | if (isset($response_headers['Content-Type'])) { 873 | if (preg_match($this->json_pattern, $response_headers['Content-Type'])) { 874 | $json_decoder = $this->json_decoder; 875 | if (is_callable($json_decoder)) { 876 | $response = $json_decoder($response); 877 | } 878 | } elseif (preg_match($this->xml_pattern, $response_headers['Content-Type'])) { 879 | $xml_obj = @simplexml_load_string($response); 880 | if (!($xml_obj === false)) { 881 | $response = $xml_obj; 882 | } 883 | } 884 | } 885 | 886 | return array($response, $raw_response); 887 | } 888 | 889 | /** 890 | * Parse Response Headers 891 | * 892 | * @access private 893 | * @param $raw_response_headers 894 | * 895 | * @return array 896 | */ 897 | private function parseResponseHeaders($raw_response_headers) 898 | { 899 | $response_header_array = explode("\r\n\r\n", $raw_response_headers); 900 | $response_header = ''; 901 | for ($i = count($response_header_array) - 1; $i >= 0; $i--) { 902 | if (stripos($response_header_array[$i], 'HTTP/') === 0) { 903 | $response_header = $response_header_array[$i]; 904 | break; 905 | } 906 | } 907 | 908 | $response_headers = new CaseInsensitiveArray(); 909 | list($first_line, $headers) = $this->parseHeaders($response_header); 910 | $response_headers['Status-Line'] = $first_line; 911 | foreach ($headers as $key => $value) { 912 | $response_headers[$key] = $value; 913 | } 914 | return $response_headers; 915 | } 916 | 917 | /** 918 | * Http Build Multi Query 919 | * 920 | * @access public 921 | * @param $data 922 | * @param $key 923 | * 924 | * @return string 925 | */ 926 | public static function http_build_multi_query($data, $key = null) 927 | { 928 | $query = array(); 929 | 930 | if (empty($data)) { 931 | return $key . '='; 932 | } 933 | 934 | $is_array_assoc = self::is_array_assoc($data); 935 | 936 | foreach ($data as $k => $value) { 937 | if (is_string($value) || is_numeric($value)) { 938 | $brackets = $is_array_assoc ? '[' . $k . ']' : '[]'; 939 | $query[] = urlencode($key === null ? $k : $key . $brackets) . '=' . rawurlencode($value); 940 | } elseif (is_array($value)) { 941 | $nested = $key === null ? $k : $key . '[' . $k . ']'; 942 | $query[] = self::http_build_multi_query($value, $nested); 943 | } 944 | } 945 | 946 | return implode('&', $query); 947 | } 948 | 949 | /** 950 | * Is Array Assoc 951 | * 952 | * @access public 953 | * @param $array 954 | * 955 | * @return boolean 956 | */ 957 | public static function is_array_assoc($array) 958 | { 959 | return (bool)count(array_filter(array_keys($array), 'is_string')); 960 | } 961 | 962 | /** 963 | * Is Array Multidim 964 | * 965 | * @access public 966 | * @param $array 967 | * 968 | * @return boolean 969 | */ 970 | public static function is_array_multidim($array) 971 | { 972 | if (!is_array($array)) { 973 | return false; 974 | } 975 | 976 | return (bool)count(array_filter($array, 'is_array')); 977 | } 978 | } 979 | 980 | class CaseInsensitiveArray implements \ArrayAccess, \Countable, \Iterator 981 | { 982 | private $container = array(); 983 | 984 | public function offsetSet($offset, $value) 985 | { 986 | if ($offset === null) { 987 | $this->container[] = $value; 988 | } else { 989 | $index = array_search(strtolower($offset), array_keys(array_change_key_case($this->container, CASE_LOWER))); 990 | if (!($index === false)) { 991 | $keys = array_keys($this->container); 992 | unset($this->container[$keys[$index]]); 993 | } 994 | $this->container[$offset] = $value; 995 | } 996 | } 997 | 998 | public function offsetExists($offset) 999 | { 1000 | return array_key_exists(strtolower($offset), array_change_key_case($this->container, CASE_LOWER)); 1001 | } 1002 | 1003 | public function offsetUnset($offset) 1004 | { 1005 | unset($this->container[$offset]); 1006 | } 1007 | 1008 | public function offsetGet($offset) 1009 | { 1010 | $index = array_search(strtolower($offset), array_keys(array_change_key_case($this->container, CASE_LOWER))); 1011 | if ($index === false) { 1012 | return null; 1013 | } 1014 | 1015 | $values = array_values($this->container); 1016 | return $values[$index]; 1017 | } 1018 | 1019 | public function count() 1020 | { 1021 | return count($this->container); 1022 | } 1023 | 1024 | public function current() 1025 | { 1026 | return current($this->container); 1027 | } 1028 | 1029 | public function next() 1030 | { 1031 | return next($this->container); 1032 | } 1033 | 1034 | public function key() 1035 | { 1036 | return key($this->container); 1037 | } 1038 | 1039 | public function valid() 1040 | { 1041 | return !($this->current() === false); 1042 | } 1043 | 1044 | public function rewind() 1045 | { 1046 | reset($this->container); 1047 | } 1048 | } 1049 | -------------------------------------------------------------------------------- /core/music.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://github.com/maicong/music 8 | * @since 1.2.6 9 | * 10 | */ 11 | 12 | if (!defined('MC_CORE') || !defined('MC_SC_CLIENT_ID')) { 13 | header("Location: /"); 14 | exit(); 15 | } 16 | 17 | // 关闭错误信息,如果要调试请注释掉 18 | error_reporting(0); 19 | 20 | // 引入 curl 21 | require_once(__DIR__.'/Curl.php'); 22 | 23 | // 参数处理 24 | function stripslashes_deep($value) 25 | { 26 | if (is_array($value)) { 27 | $value = array_map('stripslashes_deep', $value); 28 | } elseif (is_object($value)) { 29 | $vars = get_object_vars($value); 30 | foreach ($vars as $key => $data) { 31 | $value->{$key} 32 | = stripslashes_deep($data); 33 | } 34 | } elseif (is_string($value)) { 35 | $value = stripslashes($value); 36 | } 37 | return $value; 38 | } 39 | function maicong_parse_str($string, &$array) 40 | { 41 | parse_str($string, $array); 42 | if (get_magic_quotes_gpc()) { 43 | $array = stripslashes_deep($array); 44 | } 45 | } 46 | function maicong_parse_args($args, $defaults = array()) 47 | { 48 | if (is_object($args)) { 49 | $r = get_object_vars($args); 50 | } elseif (is_array($args)) { 51 | $r = &$args; 52 | } else { 53 | maicong_parse_str($args, $r); 54 | } 55 | if (is_array($defaults)) { 56 | return array_merge($defaults, $r); 57 | } 58 | return $r; 59 | } 60 | 61 | // Curl 内容获取 62 | function maicong_curl($args = array()) 63 | { 64 | $default = array( 65 | 'method' => 'GET', 66 | 'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.50 Safari/537.36', 67 | 'url' => null, 68 | 'referer' => 'https://www.google.co.uk', 69 | 'headers' => null, 70 | 'body' => null, 71 | 'sslverify' => false, 72 | 'proxy' => false, 73 | 'range' => false 74 | ); 75 | $args = maicong_parse_args($args, $default); 76 | $method = mb_strtolower($args['method']); 77 | $method_allow = array('get', 'post', 'put', 'patch', 'delete', 'head', 'options'); 78 | if (null === $args['url'] || !in_array($method, $method_allow, true)) { 79 | return; 80 | } 81 | $curl = new Curl(); 82 | $curl->setOpt(CURLOPT_SSL_VERIFYPEER, $args['sslverify']); 83 | $curl->setUserAgent($args['user-agent']); 84 | $curl->setReferrer($args['referer']); 85 | $curl->setTimeout(20); 86 | $curl->setHeader('X-Requested-With', 'XMLHttpRequest'); 87 | if ($args['proxy'] && define('MC_PROXY') && MC_PROXY) { 88 | $curl->setOpt(CURLOPT_PROXY, MC_PROXY); 89 | } 90 | if (!empty($args['range'])) { 91 | $curl->setOpt(CURLOPT_RANGE, $args['range']); 92 | } 93 | if (!empty($args['headers'])) { 94 | foreach ($args['headers'] as $key => $val) { 95 | $curl->setHeader($key, $val); 96 | } 97 | } 98 | $curl->$method($args['url'], $args['body']); 99 | $curl->close(); 100 | $response = $curl->raw_response; 101 | if (!empty($response)) { 102 | return $response; 103 | } 104 | return; 105 | } 106 | 107 | // 音频数据接口地址 108 | function maicong_song_urls($value, $type = 'query', $site = 'netease') 109 | { 110 | if (!$value) { 111 | return; 112 | } 113 | $query = ('query' === $type) ? $value : ''; 114 | $songid = ('songid' === $type) ? $value : ''; 115 | $radio_search_urls = array( 116 | 'netease' => array( 117 | 'method' => 'POST', 118 | 'url' => 'http://music.163.com/api/linux/forward', 119 | 'referer' => 'http://music.163.com/', 120 | 'proxy' => false, 121 | 'body' => encode_netease_data(array( 122 | 'method' => 'POST', 123 | 'url' => 'http://music.163.com/api/cloudsearch/pc', 124 | 'params' => array( 125 | 's' => $query, 126 | 'type' => '1', 127 | 'offset' => '0', 128 | 'limit' => '10' 129 | ) 130 | )) 131 | ), 132 | '1ting' => array( 133 | 'method' => 'GET', 134 | 'url' => 'http://so.1ting.com/song/json', 135 | 'referer' => 'http://m.1ting.com/', 136 | 'proxy' => false, 137 | 'body' => array( 138 | 'q' => $query, 139 | 'page' => '1', 140 | 'size' => '10' 141 | ) 142 | ), 143 | 'baidu' => array( 144 | 'method' => 'GET', 145 | 'url' => 'http://sug.music.baidu.com/info/suggestion', 146 | 'referer' => 'http://music.baidu.com/search?key='.urlencode($query), 147 | 'proxy' => false, 148 | 'body' => array( 149 | 'word' => $query, 150 | 'format' => 'json', 151 | 'version' => '2', 152 | 'from' => '0' 153 | ) 154 | ), 155 | 'kugou' => array( 156 | 'method' => 'GET', 157 | 'url' => 'http://mobilecdn.kugou.com/api/v3/search/song', 158 | 'referer' => 'http://m.kugou.com/v2/static/html/search.html', 159 | 'proxy' => false, 160 | 'body' => array( 161 | 'keyword' => $query, 162 | 'format' => 'json', 163 | 'page' => '1', 164 | 'pagesize' => '10' 165 | ), 166 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 167 | ), 168 | 'kuwo' => array( 169 | 'method' => 'GET', 170 | 'url' => 'http://search.kuwo.cn/r.s', 171 | 'referer' => 'http://player.kuwo.cn/webmusic/play', 172 | 'proxy' => false, 173 | 'body' => array( 174 | 'all' => $query, 175 | 'ft' => 'music', 176 | 'itemset' => 'web_2013', 177 | 'pn' => '0', 178 | 'rn' => '10', 179 | 'rformat' => 'json', 180 | 'encoding' => 'utf8' 181 | ) 182 | ), 183 | 'qq' => array( 184 | 'method' => 'GET', 185 | 'url' => 'http://c.y.qq.com/soso/fcgi-bin/client_search_cp', 186 | 'referer' => 'http://y.qq.com/portal/search.html', 187 | 'proxy' => false, 188 | 'body' => array( 189 | 'w' => $query, 190 | 'p' => '1', 191 | 'n' => '10', 192 | 'format' => 'json' 193 | ), 194 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 195 | ), 196 | 'xiami' => array( 197 | 'method' => 'GET', 198 | 'url' => 'http://api.xiami.com/web', 199 | 'referer' => 'http://m.xiami.com/', 200 | 'proxy' => false, 201 | 'body' => array( 202 | 'key' => $query, 203 | 'v' => '2.0', 204 | 'app_key' => '1', 205 | 'r' => 'search/songs', 206 | 'page' => '1', 207 | 'limit' => '10' 208 | ), 209 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 210 | ), 211 | '5sing' => array( 212 | 'method' => 'GET', 213 | 'url' => 'http://search.5sing.kugou.com/home/QuickSearch', 214 | 'referer' => 'http://5sing.kugou.com/', 215 | 'proxy' => false, 216 | 'body' => array( 217 | 'keyword' => $query 218 | ) 219 | ), 220 | 'migu' => array( 221 | 'method' => 'GET', 222 | 'url' => 'http://m.music.migu.cn/music-h5/search/searchAll.json', 223 | 'referer' => 'http://m.music.migu.cn/search', 224 | 'proxy' => false, 225 | 'body' => array( 226 | 'keyWord' => $query, 227 | 'type' => 'song', 228 | 'pageNo' => '1', 229 | 'pageSize' => '10' 230 | ) 231 | ), 232 | 'lizhi' => array( 233 | 'method' => 'GET', 234 | 'url' => 'http://m.lizhi.fm/api/search_audio/'.urlencode($query).'/1', 235 | 'referer' => 'http://m.lizhi.fm', 236 | 'proxy' => false, 237 | 'body' => false, 238 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 239 | ), 240 | 'qingting' => array( 241 | 'method' => 'GET', 242 | 'url' => 'http://i.qingting.fm/wapi/search', 243 | 'referer' => 'http://www.qingting.fm', 244 | 'proxy' => false, 245 | 'body' => array( 246 | 'k' => $query, 247 | 'page' => '1', 248 | 'pagesize' => '10', 249 | 'include' => 'program_ondemand', 250 | 'groups' => 'program_ondemand' 251 | ) 252 | ), 253 | 'ximalaya' => array( 254 | 'method' => 'GET', 255 | 'url' => 'http://search.ximalaya.com/front/v1', 256 | 'referer' => 'http://www.ximalaya.com', 257 | 'proxy' => false, 258 | 'body' => array( 259 | 'kw' => $query, 260 | 'core' => 'all', 261 | 'page' => '1', 262 | 'rows' => '10', 263 | 'is_paid' => false 264 | ) 265 | ), 266 | 'soundcloud' => array( 267 | 'method' => 'GET', 268 | 'url' => 'https://api-v2.soundcloud.com/search/tracks', 269 | 'referer' => 'https://soundcloud.com/', 270 | 'proxy' => false, 271 | 'body' => array( 272 | 'q' => $query, 273 | 'limit' => '10', 274 | 'offset' => '0', 275 | 'facet' => 'genre', 276 | 'client_id' => MC_SC_CLIENT_ID 277 | ) 278 | ) 279 | ); 280 | $radio_song_urls = array( 281 | 'netease' => array( 282 | 'method' => 'POST', 283 | 'url' => 'http://music.163.com/api/linux/forward', 284 | 'referer' => 'http://music.163.com/', 285 | 'proxy' => false, 286 | 'body' => encode_netease_data(array( 287 | 'method' => 'GET', 288 | 'url' => 'http://music.163.com/api/song/detail', 289 | 'params' => array( 290 | 'id' => $songid, 291 | 'ids' => '['.$songid.']' 292 | ) 293 | )) 294 | ), 295 | '1ting' => array( 296 | 'method' => 'GET', 297 | 'url' => 'http://m.1ting.com/touch/api/song', 298 | 'referer' => 'http://m.1ting.com/#/song/'.$songid, 299 | 'proxy' => false, 300 | 'body' => array( 301 | 'ids' => $songid 302 | ) 303 | ), 304 | 'baidu' => array( 305 | 'method' => 'GET', 306 | 'url' => 'http://tingapi.ting.baidu.com/v2/restserver/ting', 307 | 'referer' => 'music.baidu.com/song/'.$songid, 308 | 'proxy' => false, 309 | 'body' => array( 310 | 'method' => 'baidu.ting.song.play', 311 | 'format' => 'json', 312 | 'songid' => $songid 313 | ) 314 | ), 315 | 'kugou' => array( 316 | 'method' => 'GET', 317 | 'url' => 'http://m.kugou.com/app/i/getSongInfo.php', 318 | 'referer' => 'http://m.kugou.com/play/info/'.$songid, 319 | 'proxy' => false, 320 | 'body' => array( 321 | 'cmd' => 'playInfo', 322 | 'hash' => $songid 323 | ), 324 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 325 | ), 326 | 'kuwo' => array( 327 | 'method' => 'GET', 328 | 'url' => 'http://player.kuwo.cn/webmusic/st/getNewMuiseByRid', 329 | 'referer' => 'http://player.kuwo.cn/webmusic/play', 330 | 'proxy' => false, 331 | 'body' => array( 332 | 'rid' => 'MUSIC_'.$songid 333 | ) 334 | ), 335 | 'qq' => array( 336 | 'method' => 'GET', 337 | 'url' => 'http://i.y.qq.com/s.plcloud/fcgi-bin/fcg_list_songinfo_cp.fcg', 338 | 'referer' => 'http://data.music.qq.com/playsong.html?songmid='.$songid, 339 | 'proxy' => false, 340 | 'body' => array( 341 | 'midlist' => $songid 342 | ), 343 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 344 | ), 345 | 'xiami' => array( 346 | 'method' => 'GET', 347 | 'url' => 'http://www.xiami.com/song/playlist/id/'.$songid.'/object_name/default/object_id/0/cat/json', 348 | 'referer' => 'http://m.xiami.com/song/'.$songid, 349 | 'proxy' => false, 350 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 351 | ), 352 | '5sing' => array( 353 | 'method' => 'GET', 354 | 'url' => 'http://5sing.kugou.com/'.$songid.'.html', 355 | 'referer' => 'http://5sing.kugou.com/'.$songid.'.html', 356 | 'range' => '0-2000', 357 | 'proxy' => false 358 | ), 359 | 'migu' => array( 360 | 'method' => 'GET', 361 | 'url' => 'http://music.migu.cn/webfront/player/findsong.do', 362 | 'referer' => 'http://music.migu.cn/#/song/'.$songid, 363 | 'proxy' => false, 364 | 'body' => array( 365 | 'itemid' => $songid, 366 | 'type' => 'song' 367 | ) 368 | ), 369 | 'lizhi' => array( 370 | 'method' => 'GET', 371 | 'url' => 'http://m.lizhi.fm/api/audios_with_radio', 372 | 'referer' => 'http://m.lizhi.fm', 373 | 'proxy' => false, 374 | 'body' => array( 375 | 'ids' => $songid 376 | ), 377 | 'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1' 378 | ), 379 | 'qingting' => array( 380 | 'method' => 'GET', 381 | 'url' => 'http://i.qingting.fm/wapi/channels/'.split_songid($songid, 0).'/programs/'.split_songid($songid, 1), 382 | 'referer' => 'http://www.qingting.fm', 383 | 'proxy' => false, 384 | 'body' => false 385 | ), 386 | 'ximalaya' => array( 387 | 'method' => 'GET', 388 | 'url' => 'http://mobile.ximalaya.com/v1/track/ca/playpage/'.$songid, 389 | 'referer' => 'http://www.ximalaya.com', 390 | 'proxy' => false, 391 | 'body' => false 392 | ), 393 | 'soundcloud' => array( 394 | 'method' => 'GET', 395 | 'url' => 'https://api.soundcloud.com/tracks/'.$songid.'.json', 396 | 'referer' => 'https://soundcloud.com/', 397 | 'proxy' => false, 398 | 'body' => array( 399 | 'client_id' => MC_SC_CLIENT_ID 400 | ) 401 | ) 402 | ); 403 | if ('query' === $type) { 404 | return $radio_search_urls[$site]; 405 | } 406 | if ('songid' === $type) { 407 | return $radio_song_urls[$site]; 408 | } 409 | return; 410 | } 411 | 412 | // 获取音频信息 - 关键词搜索 413 | function maicong_get_song_by_name($query, $site = 'netease') 414 | { 415 | if (!$query) { 416 | return; 417 | } 418 | $radio_search_url = maicong_song_urls($query, 'query', $site); 419 | if (empty($query) || empty($radio_search_url)) { 420 | return; 421 | } 422 | $radio_result = maicong_curl($radio_search_url); 423 | if (empty($radio_result)) { 424 | return; 425 | } 426 | $radio_songid = array(); 427 | switch ($site) { 428 | case '1ting': 429 | $radio_data = json_decode($radio_result, true); 430 | if (empty($radio_data['results'])) { 431 | return; 432 | } 433 | foreach ($radio_data['results'] as $key => $val) { 434 | $radio_songid[] = $val['song_id']; 435 | } 436 | break; 437 | case 'baidu': 438 | $radio_data = json_decode($radio_result, true); 439 | if (empty($radio_data['data']) || empty($radio_data['data']['song'])) { 440 | return; 441 | } 442 | foreach ($radio_data['data']['song'] as $key => $val) { 443 | if ($key > 4) { 444 | break; 445 | } 446 | $radio_songid[] = $val['songid']; 447 | } 448 | break; 449 | case 'kugou': 450 | $radio_data = json_decode($radio_result, true); 451 | if (empty($radio_data['data']) || empty($radio_data['data']['info'])) { 452 | return; 453 | } 454 | foreach ($radio_data['data']['info'] as $key => $val) { 455 | $radio_songid[] = $val['hash']; 456 | } 457 | break; 458 | case 'kuwo': 459 | $radio_result = str_replace('\'', '"', $radio_result); 460 | $radio_data = json_decode($radio_result, true); 461 | if (empty($radio_data['abslist'])) { 462 | return; 463 | } 464 | foreach ($radio_data['abslist'] as $key => $val) { 465 | $radio_songid[] = str_replace('MUSIC_', '', $val['MUSICRID']); 466 | } 467 | break; 468 | case 'qq': 469 | $radio_data = json_decode($radio_result, true); 470 | if (empty($radio_data['data']) || empty($radio_data['data']['song']) || empty($radio_data['data']['song']['list'])) { 471 | return; 472 | } 473 | foreach ($radio_data['data']['song']['list'] as $key => $val) { 474 | $radio_songid[] = $val['songmid']; 475 | } 476 | break; 477 | case 'xiami': 478 | $radio_data = json_decode($radio_result, true); 479 | if (empty($radio_data['data']) || empty($radio_data['data']['songs'])) { 480 | return; 481 | } 482 | foreach ($radio_data['data']['songs'] as $key => $val) { 483 | $radio_songid[] = $val['song_id']; 484 | } 485 | break; 486 | case '5sing': 487 | $radio_data = json_decode(substr($radio_result, 1, -1), true); 488 | if (empty($radio_data['songs'])) { 489 | return; 490 | } 491 | foreach ($radio_data['songs'] as $key => $val) { 492 | if ($key > 4) { 493 | break; 494 | } 495 | $radio_songid[] = $val['type'].'/'.$val['songId']; 496 | } 497 | break; 498 | case 'migu': 499 | $radio_data = json_decode($radio_result, true); 500 | if (empty($radio_data['data']) || empty($radio_data['data']['list'])) { 501 | return; 502 | } 503 | foreach ($radio_data['data']['list'] as $key => $val) { 504 | $radio_songid[] = $val['songId']; 505 | } 506 | break; 507 | case 'lizhi': 508 | $radio_data = json_decode($radio_result, true); 509 | if (empty($radio_data['audio']) || empty($radio_data['audio']['data'])) { 510 | return; 511 | } 512 | foreach ($radio_data['audio']['data'] as $key => $val) { 513 | $radio_songid[] = $val['audio']['id']; 514 | } 515 | break; 516 | case 'qingting': 517 | $radio_data = json_decode($radio_result, true); 518 | if (empty($radio_data['data']) || empty($radio_data['data']['data'])) { 519 | return; 520 | } 521 | foreach ($radio_data['data']['data'][0]['doclist']['docs'] as $key => $val) { 522 | $radio_songid[] = $val['parent_id'].'|'.$val['id']; 523 | } 524 | break; 525 | case 'ximalaya': 526 | $radio_data = json_decode($radio_result, true); 527 | if (empty($radio_data['track']) || empty($radio_data['track']['docs'])) { 528 | return; 529 | } 530 | foreach ($radio_data['track']['docs'] as $key => $val) { 531 | if (!$val['is_paid']) { // 过滤付费的 532 | $radio_songid[] = $val['id']; 533 | } 534 | } 535 | break; 536 | case 'soundcloud': 537 | $radio_data = json_decode($radio_result, true); 538 | if (empty($radio_data['collection'])) { 539 | return; 540 | } 541 | foreach ($radio_data['collection'] as $key => $val) { 542 | $radio_songid[] = $val['id']; 543 | } 544 | break; 545 | case 'netease': 546 | default: 547 | $radio_data = json_decode($radio_result, true); 548 | if (empty($radio_data['result']) || empty($radio_data['result']['songs'])) { 549 | return; 550 | } 551 | foreach ($radio_data['result']['songs'] as $key => $val) { 552 | $radio_songid[] = $val['id']; 553 | } 554 | break; 555 | } 556 | return maicong_get_song_by_id($radio_songid, $site, true); 557 | } 558 | 559 | // 获取音频信息 - 歌曲ID 560 | function maicong_get_song_by_id($songid, $site = 'netease', $multi = false) 561 | { 562 | if (empty($songid) || empty($site)) { 563 | return; 564 | } 565 | $radio_song_urls = array(); 566 | if ($multi) { 567 | if (!is_array($songid)) { 568 | return; 569 | } 570 | foreach ($songid as $key => $val) { 571 | $radio_song_urls[] = maicong_song_urls($val, 'songid', $site); 572 | } 573 | } else { 574 | $radio_song_urls[] = maicong_song_urls($songid, 'songid', $site); 575 | } 576 | if (empty($radio_song_urls) || !array_key_exists(0, $radio_song_urls)) { 577 | return; 578 | } 579 | $radio_result = array(); 580 | foreach ($radio_song_urls as $key => $val) { 581 | $radio_result[] = maicong_curl($val); 582 | } 583 | if (empty($radio_result) || !array_key_exists(0, $radio_result)) { 584 | return; 585 | } 586 | $radio_songs = array(); 587 | switch ($site) { 588 | case '1ting': 589 | foreach ($radio_result as $key => $val) { 590 | $radio_data = json_decode($val, true); 591 | $radio_detail = $radio_data; 592 | if (!empty($radio_detail)) { 593 | $radio_song_id = $radio_detail[0]['song_id']; 594 | $radio_songs[] = array( 595 | 'type' => '1ting', 596 | 'link' => 'http://www.1ting.com/player/b6/player_'.$radio_song_id.'.html', 597 | 'songid' => $radio_song_id, 598 | 'name' => $radio_detail[0]['song_name'], 599 | 'author' => $radio_detail[0]['singer_name'], 600 | 'music' => 'http://96.1ting.com'.str_replace('.wma', '.mp3', $radio_detail[0]['song_filepath']), 601 | 'pic' => $radio_detail[0]['album_cover'] 602 | ); 603 | } 604 | } 605 | break; 606 | case 'baidu': 607 | foreach ($radio_result as $key => $val) { 608 | $radio_data = json_decode($val, true); 609 | $radio_detail = $radio_data; 610 | if (!empty($radio_detail) && !empty($radio_detail['songinfo'])) { 611 | // 注: 百度不允许外链 ~ 自信解决吧 612 | $radio_song_id = $radio_detail['songinfo']['song_id']; 613 | $radio_songs[] = array( 614 | 'type' => 'baidu', 615 | 'link' => 'http://music.baidu.com/song/'.$radio_song_id, 616 | 'songid' => $radio_song_id, 617 | 'name' => $radio_detail['songinfo']['title'], 618 | 'author' => $radio_detail['songinfo']['author'], 619 | 'music' => $radio_detail['bitrate']['file_link'], 620 | 'pic' => $radio_detail['songinfo']['pic_big'] 621 | ); 622 | } 623 | } 624 | break; 625 | case 'kugou': 626 | foreach ($radio_result as $key => $val) { 627 | $radio_data = json_decode($val, true); 628 | $radio_detail = $radio_data; 629 | if (!empty($radio_detail) && $radio_data['status']) { 630 | $radio_name = explode(' - ', $radio_detail['fileName']); 631 | $radio_img = array( 632 | 'method' => 'GET', 633 | 'url' => 'http://mobilecdn.kugou.com/new/app/i/yueku.php', 634 | 'proxy' => false, 635 | 'body' => array( 636 | 'cmd' => '104', 637 | 'size' => '100', 638 | 'singer' => $radio_name[0] 639 | ) 640 | ); 641 | $radio_imginfo = json_decode(maicong_curl($radio_img), true); 642 | if (!empty($radio_imginfo)) { 643 | $radio_pic = $radio_imginfo['url']; 644 | } 645 | $radio_song_id = $radio_detail['hash']; 646 | $radio_songs[] = array( 647 | 'type' => 'kugou', 648 | 'link' => 'http://m.kugou.com/play/info/'.$radio_song_id, 649 | 'songid' => $radio_song_id, 650 | 'name' => $radio_name[1], 651 | 'author' => $radio_name[0], 652 | 'music' => $radio_detail['url'], 653 | 'pic' => $radio_pic 654 | ); 655 | } 656 | } 657 | break; 658 | case 'kuwo': 659 | foreach ($radio_result as $key => $val) { 660 | preg_match_all('/<([\w]+)>(.*?)<\/\\1>/i', $val, $radio_data); 661 | if (!empty($radio_data[1]) && !empty($radio_data[2])) { 662 | $radio_detail = array(); 663 | foreach ($radio_data[1] as $key => $val) { 664 | $radio_detail[$val] = $radio_data[2][$key]; 665 | } 666 | $radio_song_id = $radio_detail['music_id']; 667 | $radio_songs[] = array( 668 | 'type' => 'kuwo', 669 | 'link' => 'http://www.kuwo.cn/yinyue/'.$radio_song_id, 670 | 'songid' => $radio_song_id, 671 | 'name' => $radio_detail['name'], 672 | 'author' => $radio_detail['singer'], 673 | 'music' => 'http://'.$radio_detail['mp3dl'].'/resource/'.$radio_detail['mp3path'], 674 | 'pic' => $radio_detail['artist_pic'] 675 | ); 676 | } 677 | } 678 | break; 679 | case 'qq': 680 | foreach ($radio_result as $key => $val) { 681 | $radio_data = json_decode($val, true); 682 | $radio_detail = $radio_data['data']; 683 | if (!empty($radio_detail)) { 684 | $radio_song_id = $radio_detail[0]['songmid']; 685 | $radio_pic = $radio_detail[0]['albummid']; 686 | $radio_authors = array(); 687 | foreach ($radio_detail[0]['singer'] as $key => $val) { 688 | $radio_authors[] = $val['name']; 689 | } 690 | $radio_author = implode('/', $radio_authors); 691 | $radio_songs[] = array( 692 | 'type' => 'qq', 693 | 'link' => 'https://y.qq.com/n/yqq/song/'.$radio_song_id.'.html', 694 | 'songid' => $radio_song_id, 695 | 'name' => $radio_detail[0]['songname'], 696 | 'author' => $radio_author, 697 | 'music' => 'http://isure.stream.qqmusic.qq.com/C100'.$radio_song_id.'.m4a?fromtag=32', 698 | 'pic' => 'http://y.gtimg.cn/music/photo_new/T002R300x300M000'.$radio_pic.'.jpg' 699 | ); 700 | } 701 | } 702 | break; 703 | case 'xiami': 704 | foreach ($radio_result as $key => $val) { 705 | $radio_data = json_decode($val, true); 706 | $radio_detail = $radio_data['data']['trackList']; 707 | if (!empty($radio_detail)) { 708 | $radio_song_id = $radio_detail[0]['song_id']; 709 | $radio_songs[] = array( 710 | 'type' => 'xiami', 711 | 'link' => 'http://www.xiami.com/song/'.$radio_song_id, 712 | 'songid' => $radio_song_id, 713 | 'name' => $radio_detail[0]['title'], 714 | 'author' => $radio_detail[0]['artist'], 715 | 'music' => maicong_decode_xiami_location($radio_detail[0]['location']), 716 | 'pic' => $radio_detail[0]['album_pic'] 717 | ); 718 | } 719 | } 720 | break; 721 | case '5sing': 722 | foreach ($radio_result as $key => $val) { 723 | preg_match('/ticket"\: "(.*?)"/i', $val, $radio_match); 724 | if (!empty($radio_match[1])) { 725 | $radio_detail = json_decode(base64_decode($radio_match[1], true), true); 726 | if (!empty($radio_detail)) { 727 | $radio_song_id = $radio_detail['songType'].'/'.$radio_detail['songID']; 728 | $radio_author = $radio_detail['singer']; 729 | $radio_pic = $radio_detail['avatar']; 730 | if (empty($radio_author)) { 731 | preg_match('/(.*?)<\/title>/i', $val, $radio_match_author); 732 | if (!empty($radio_match_author[1])) { 733 | $radio_author_ep = explode(' - ', $radio_match_author[1]); 734 | $radio_author = $radio_author_ep[1]; 735 | } 736 | } 737 | if (empty($radio_pic)) { 738 | preg_match('/img\s+src="(.*?)"\s+width="180"/i', $val, $radio_match_pic); 739 | $radio_pic = !empty($radio_match_pic[1]) ? $radio_match_pic[1] : null; 740 | } 741 | $radio_songs[] = array( 742 | 'type' => '5sing', 743 | 'link' => 'http://5sing.kugou.com/'.$radio_song_id.'.html', 744 | 'songid' => $radio_song_id, 745 | 'name' => $radio_detail['songName'], 746 | 'author' => $radio_author, 747 | 'music' => $radio_detail['file'], 748 | 'pic' => $radio_pic 749 | ); 750 | } 751 | } 752 | } 753 | break; 754 | case 'migu': 755 | foreach ($radio_result as $key => $val) { 756 | $radio_data = json_decode($val, true); 757 | $radio_detail = $radio_data['msg']; 758 | if (!empty($radio_detail)) { 759 | $radio_song_id = $radio_detail[0]['songId']; 760 | $radio_songs[] = array( 761 | 'type' => 'migu', 762 | 'link' => 'http://music.migu.cn/#/song/'.$radio_song_id, 763 | 'songid' => $radio_song_id, 764 | 'name' => urldecode($radio_detail[0]['songName']), 765 | 'author' => $radio_detail[0]['singerName'], 766 | 'music' => $radio_detail[0]['mp3'], 767 | 'pic' => $radio_detail[0]['poster'] 768 | ); 769 | } 770 | } 771 | break; 772 | case 'lizhi': 773 | foreach ($radio_result as $key => $val) { 774 | $radio_data = json_decode($val, true); 775 | $radio_detail = $radio_data['0']; 776 | if (!empty($radio_detail)) { 777 | $radio_song_id = $radio_detail['audio']['id']; 778 | $radio_songs[] = array( 779 | 'type' => 'lizhi', 780 | 'link' => 'http://www.lizhi.fm/'.$radio_detail['radio']['band'].'/'.$radio_song_id, 781 | 'songid' => $radio_song_id, 782 | 'name' => urldecode($radio_detail['audio']['name']), 783 | 'author' => $radio_detail['radio']['name'], 784 | 'music' => $radio_detail['audio']['url'], 785 | 'pic' => 'http://m.lizhi.fm/radio_cover/'.$radio_detail['radio']['cover'] 786 | ); 787 | } 788 | } 789 | break; 790 | case 'qingting': 791 | foreach ($radio_result as $key => $val) { 792 | $radio_data = json_decode($val, true); 793 | $radio_detail = $radio_data['data']; 794 | if (!empty($radio_detail)) { 795 | $radio_channels = array( 796 | 'method' => 'GET', 797 | 'url' => 'http://i.qingting.fm/wapi/channels/'.$radio_detail['channel_id'], 798 | 'referer' => 'http://www.qingting.fm', 799 | 'proxy' => false, 800 | 'body' => false 801 | ); 802 | $radio_channels_info = json_decode(maicong_curl($radio_channels), true); 803 | if (!empty($radio_channels_info) && !empty($radio_channels_info['data'])) { 804 | $radio_author = $radio_channels_info['data']['name']; 805 | $radio_pic = $radio_channels_info['data']['img_url']; 806 | } 807 | $radio_songs[] = array( 808 | 'type' => 'qingting', 809 | 'link' => 'http://www.qingting.fm/channels/'.$radio_detail['channel_id'].'/programs/'.$radio_detail['id'], 810 | 'songid' => $radio_detail['channel_id'].'|'.$radio_detail['id'], 811 | 'name' => urldecode($radio_detail['name']), 812 | 'author' => $radio_author, 813 | 'music' => 'http://od.qingting.fm/'.$radio_detail['file_path'], 814 | 'pic' => $radio_pic 815 | ); 816 | } 817 | } 818 | break; 819 | case 'ximalaya': 820 | foreach ($radio_result as $key => $val) { 821 | $radio_detail = json_decode($val, true); 822 | if (!empty($radio_detail)) { 823 | $radio_song_info = $radio_detail['trackInfo']; 824 | $radio_songs[] = array( 825 | 'type' => 'ximalaya', 826 | 'link' => 'http://www.ximalaya.com/'.$radio_song_info['uid'].'/sound/'.$radio_song_info['trackId'], 827 | 'songid' => $radio_song_info['trackId'], 828 | 'name' => urldecode($radio_song_info['title']), 829 | 'author' => $radio_detail['userInfo']['nickname'], 830 | 'music' => $radio_song_info['playUrl64'], 831 | 'pic' => $radio_song_info['coverLarge'] 832 | ); 833 | } 834 | } 835 | break; 836 | case 'soundcloud': 837 | foreach ($radio_result as $key => $val) { 838 | $radio_detail = json_decode($val, true); 839 | if (!empty($radio_detail)) { 840 | $radio_streams = array( 841 | 'method' => 'GET', 842 | 'url' => 'https://api.soundcloud.com/i1/tracks/'.$radio_detail['id'].'/streams', 843 | 'referer' => 'https://soundcloud.com/', 844 | 'proxy' => false, 845 | 'body' => array( 846 | 'client_id' => MC_SC_CLIENT_ID 847 | ) 848 | ); 849 | $radio_streams_info = json_decode(maicong_curl($radio_streams), true); 850 | if (!empty($radio_streams_info)) { 851 | $radio_music_http = $radio_streams_info['http_mp3_128_url']; 852 | $radio_music_preview = $radio_streams_info['preview_mp3_128_url']; 853 | $radio_music = $radio_music_http ? $radio_music_http : $radio_music_preview; 854 | } 855 | $radio_pic_artwork = $radio_detail['artwork_url']; 856 | $radio_pic_avatar = $radio_detail['user']['avatar_url']; 857 | $radio_pic = $radio_pic_artwork ? $radio_pic_artwork : $radio_pic_avatar; 858 | $radio_songs[] = array( 859 | 'type' => 'soundcloud', 860 | 'link' => $radio_detail['permalink_url'], 861 | 'songid' => $radio_detail['id'], 862 | 'name' => $radio_detail['title'], 863 | 'author' => $radio_detail['user']['username'], 864 | 'music' => $radio_music, 865 | 'pic' => $radio_pic 866 | ); 867 | } 868 | } 869 | break; 870 | case 'netease': 871 | default: 872 | foreach ($radio_result as $key => $val) { 873 | $radio_data = json_decode($val, true); 874 | $radio_detail = $radio_data['songs']; 875 | if (!empty($radio_detail)) { 876 | $radio_song_id = $radio_detail[0]['id']; 877 | $radio_authors = array(); 878 | foreach ($radio_detail[0]['artists'] as $key => $val) { 879 | $radio_authors[] = $val['name']; 880 | } 881 | $radio_author = implode('/', $radio_authors); 882 | $radio_music_url = $radio_detail[0]['mp3Url']; 883 | if (!$radio_music_url) { 884 | $radio_streams = array( 885 | 'method' => 'POST', 886 | 'url' => 'http://music.163.com/api/linux/forward', 887 | 'referer' => 'http://music.163.com/', 888 | 'proxy' => false, 889 | 'body' => encode_netease_data(array( 890 | 'method' => 'POST', 891 | 'url' => 'http://music.163.com/api/song/enhance/player/url', 892 | 'params' => array( 893 | 'ids' => array($radio_song_id), 894 | 'br' => 320000, 895 | ) 896 | )) 897 | ); 898 | $radio_streams_info = json_decode(maicong_curl($radio_streams), true); 899 | if (!empty($radio_streams_info)) { 900 | $radio_music_url = $radio_streams_info['data'][0]['url']; 901 | } 902 | } 903 | $radio_songs[] = array( 904 | 'type' => 'netease', 905 | 'link' => 'http://music.163.com/#/song?id='.$radio_song_id, 906 | 'songid' => $radio_song_id, 907 | 'name' => $radio_detail[0]['name'], 908 | 'author' => $radio_author, 909 | 'music' => $radio_music_url, 910 | 'pic' => $radio_detail[0]['album']['picUrl'].'?param=100x100' 911 | ); 912 | } 913 | } 914 | break; 915 | } 916 | return !empty($radio_songs) ? $radio_songs : ''; 917 | } 918 | 919 | // 获取音频信息 - url 920 | function maicong_get_song_by_url($url) 921 | { 922 | preg_match('/music\.163\.com\/(#(\/m)?|m)\/song(\?id=|\/)(\d+)/i', $url, $match_netease); 923 | preg_match('/(www|m)\.1ting\.com\/(player\/b6\/player_|#\/song\/)(\d+)/i', $url, $match_1ting); 924 | preg_match('/music\.baidu\.com\/song\/(\d+)/i', $url, $match_baidu); 925 | preg_match('/m\.kugou\.com\/play\/info\/([a-z0-9]+)/i', $url, $match_kugou); 926 | preg_match('/www\.kuwo\.cn\/(yinyue|my)\/(\d+)/i', $url, $match_kuwo); 927 | preg_match('/(y\.qq\.com\/n\/yqq\/song\/|data\.music\.qq\.com\/playsong\.html\?songmid=)([a-zA-Z0-9]+)/i', $url, $match_qq); 928 | preg_match('/(www|m)\.xiami\.com\/song\/(\d+)/i', $url, $match_xiami); 929 | preg_match('/5sing\.kugou\.com\/(m\/detail\/|)([a-z]+)(-|\/)(\d+)/i', $url, $match_5sing); 930 | preg_match('/music\.migu\.cn\/#\/song\/(\d+)/i', $url, $match_migu); 931 | preg_match('/(www|m)\.lizhi\.fm\/(\d+)\/(\d+)/i', $url, $match_lizhi); 932 | preg_match('/(www|m)\.qingting\.fm\/channels\/(\d+)\/programs\/(\d+)/i', $url, $match_qingting); 933 | preg_match('/(www|m)\.ximalaya\.com\/(\d+)\/sound\/(\d+)/i', $url, $match_ximalaya); 934 | preg_match('/soundcloud\.com\/[\w\-]+\/[\w\-]+/i', $url, $match_soundcloud); 935 | if (!empty($match_netease)) { 936 | $songid = $match_netease[4]; 937 | $songtype = 'netease'; 938 | } elseif (!empty($match_1ting)) { 939 | $songid = $match_1ting[3]; 940 | $songtype = '1ting'; 941 | } elseif (!empty($match_baidu)) { 942 | $songid = $match_baidu[1]; 943 | $songtype = 'baidu'; 944 | } elseif (!empty($match_kugou)) { 945 | $songid = $match_kugou[1]; 946 | $songtype = 'kugou'; 947 | } elseif (!empty($match_kuwo)) { 948 | $songid = $match_kuwo[2]; 949 | $songtype = 'kuwo'; 950 | } elseif (!empty($match_qq)) { 951 | $songid = $match_qq[2]; 952 | $songtype = 'qq'; 953 | } elseif (!empty($match_xiami)) { 954 | $songid = $match_xiami[2]; 955 | $songtype = 'xiami'; 956 | } elseif (!empty($match_5sing)) { 957 | $songid = $match_5sing[2].'/'.$match_5sing[4]; 958 | $songtype = '5sing'; 959 | } elseif (!empty($match_migu)) { 960 | $songid = $match_migu[1]; 961 | $songtype = 'migu'; 962 | } elseif (!empty($match_lizhi)) { 963 | $songid = $match_lizhi[3]; 964 | $songtype = 'lizhi'; 965 | } elseif (!empty($match_qingting)) { 966 | $songid = $match_qingting[2].'|'.$match_qingting[3]; 967 | $songtype = 'qingting'; 968 | } elseif (!empty($match_ximalaya)) { 969 | $songid = $match_ximalaya[3]; 970 | $songtype = 'ximalaya'; 971 | } elseif (!empty($match_soundcloud)) { 972 | $match_resolve = array( 973 | 'method' => 'GET', 974 | 'url' => 'http://api.soundcloud.com/resolve.json', 975 | 'referer' => 'https://soundcloud.com/', 976 | 'proxy' => false, 977 | 'body' => array( 978 | 'url' => $match_soundcloud[0], 979 | 'client_id' => MC_SC_CLIENT_ID 980 | ) 981 | ); 982 | $match_request = maicong_curl($match_resolve); 983 | preg_match('/tracks\/(\d+)\.json/i', $match_request, $match_location); 984 | if (!empty($match_location)) { 985 | $songid = $match_location[1]; 986 | $songtype = 'soundcloud'; 987 | } 988 | } else { 989 | return; 990 | } 991 | return maicong_get_song_by_id($songid, $songtype); 992 | } 993 | 994 | // 解密虾米 location 995 | function maicong_decode_xiami_location($location) 996 | { 997 | $location = trim($location); 998 | $result = array(); 999 | $line = intval($location[0]); 1000 | $locLen = strlen($location); 1001 | $rows = intval(($locLen - 1) / $line); 1002 | $extra = ($locLen - 1) % $line; 1003 | $location = substr($location, 1); 1004 | for ($i = 0; $i < $extra; ++$i) { 1005 | $start = ($rows + 1) * $i; 1006 | $end = ($rows + 1) * ($i + 1); 1007 | $result[] = substr($location, $start, $end - $start); 1008 | } 1009 | for ($i = 0; $i < $line - $extra; ++$i) { 1010 | $start = ($rows + 1) * $extra + ($rows * $i); 1011 | $end = ($rows + 1) * $extra + ($rows * $i) + $rows; 1012 | $result[] = substr($location, $start, $end - $start); 1013 | } 1014 | $url = ''; 1015 | for ($i = 0; $i < $rows + 1; ++$i) { 1016 | for ($j = 0; $j < $line; ++$j) { 1017 | if ($j >= count($result) || $i >= strlen($result[$j])) { 1018 | continue; 1019 | } 1020 | $url .= $result[$j][$i]; 1021 | } 1022 | } 1023 | $url = urldecode($url); 1024 | $url = str_replace('^', '0', $url); 1025 | return $url; 1026 | } 1027 | 1028 | // 加密网易云音乐 api 参数 1029 | function encode_netease_data($data) 1030 | { 1031 | $_key = '7246674226682325323F5E6544673A51'; 1032 | $data = json_encode($data); 1033 | if (function_exists('openssl_encrypt')) { 1034 | $data = openssl_encrypt($data, 'aes-128-ecb', pack('H*', $_key)); 1035 | } else { 1036 | $_pad = 16 - (strlen($data) % 16); 1037 | $data = base64_encode(mcrypt_encrypt( 1038 | MCRYPT_RIJNDAEL_128, 1039 | hex2bin($_key), 1040 | $data.str_repeat(chr($_pad), $_pad), 1041 | MCRYPT_MODE_ECB 1042 | )); 1043 | } 1044 | $data = strtoupper(bin2hex(base64_decode($data))); 1045 | return array('eparams' => $data); 1046 | } 1047 | 1048 | // 分割 songid 并获取 1049 | function split_songid ($songid, $index = 0, $delimiter = '|') { 1050 | if (mb_strpos($songid, $delimiter, 0, 'UTF-8') > 0) { 1051 | $array = explode($delimiter, $songid); 1052 | if (count($array) > 1) { 1053 | return $array[$index]; 1054 | } 1055 | } 1056 | return; 1057 | } 1058 | 1059 | // Server 1060 | function server($key) 1061 | { 1062 | return isset($_SERVER[$key]) ? $_SERVER[$key] : null; 1063 | } 1064 | 1065 | // Post 1066 | function post($key) 1067 | { 1068 | return isset($_POST[$key]) ? $_POST[$key] : null; 1069 | } 1070 | 1071 | // Response 1072 | function response($data, $code = 200, $error = '') 1073 | { 1074 | header('Content-type:text/json; charset=utf-8'); 1075 | echo json_encode(array( 1076 | 'data' => $data, 1077 | 'code' => $code, 1078 | 'error' => $error 1079 | )); 1080 | exit(); 1081 | } 1082 | -------------------------------------------------------------------------------- /static/music.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 音乐搜索器 - JS 文件 4 | * 5 | * @author MaiCong <i@maicong.me> 6 | * @link https://github.com/maicong/music 7 | * @since 1.2.2 8 | * 9 | */ 10 | 11 | var AmazingAudioPlatforms = { 12 | flashInstalled: function() { 13 | var flashInstalled = false; 14 | try { 15 | if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) { 16 | flashInstalled = true; 17 | } 18 | } catch (e) { 19 | if (navigator.mimeTypes['application/x-shockwave-flash']) { 20 | flashInstalled = true; 21 | } 22 | } 23 | return flashInstalled; 24 | }, 25 | html5VideoSupported: function() { 26 | return !!document.createElement('video').canPlayType; 27 | }, 28 | isChrome: function() { 29 | return navigator.userAgent.match(/Chrome/i) != null; 30 | }, 31 | isFirefox: function() { 32 | return navigator.userAgent.match(/Firefox/i) != null; 33 | }, 34 | isOpera: function() { 35 | return navigator.userAgent.match(/Opera/i) != null; 36 | }, 37 | isSafari: function() { 38 | return navigator.userAgent.match(/Safari/i) != null; 39 | }, 40 | isAndroid: function() { 41 | return navigator.userAgent.match(/Android/i) != null; 42 | }, 43 | isIPad: function() { 44 | return navigator.userAgent.match(/iPad/i) != null; 45 | }, 46 | isIPhone: function() { 47 | return ( 48 | navigator.userAgent.match(/iPod/i) != null || 49 | navigator.userAgent.match(/iPhone/i) != null 50 | ); 51 | }, 52 | isIOS: function() { 53 | return this.isIPad() || this.isIPhone(); 54 | }, 55 | isMobile: function() { 56 | return this.isIPad() || this.isIPhone() || this.isAndroid(); 57 | }, 58 | isIE9: function() { 59 | return navigator.userAgent.match(/MSIE 9/i) != null && !this.isOpera(); 60 | }, 61 | isIE8: function() { 62 | return navigator.userAgent.match(/MSIE 8/i) != null && !this.isOpera(); 63 | }, 64 | isIE7: function() { 65 | return navigator.userAgent.match(/MSIE 7/i) != null && !this.isOpera(); 66 | }, 67 | isIE6: function() { 68 | return navigator.userAgent.match(/MSIE 6/i) != null && !this.isOpera(); 69 | }, 70 | isIE678: function() { 71 | return this.isIE6() || this.isIE7() || this.isIE8(); 72 | }, 73 | isIE6789: function() { 74 | return this.isIE6() || this.isIE7() || this.isIE8() || this.isIE9(); 75 | }, 76 | css33dTransformSupported: function() { 77 | return ( 78 | !this.isIE6() && 79 | !this.isIE7() && 80 | !this.isIE8() && 81 | !this.isIE9() && 82 | !this.isOpera() 83 | ); 84 | }, 85 | applyBrowserStyles: function(object, applyToValue) { 86 | var ret = {}; 87 | for (var key in object) { 88 | ret[key] = object[key]; 89 | ret['-webkit-' + key] = applyToValue 90 | ? '-webkit-' + object[key] 91 | : object[key]; 92 | ret['-moz-' + key] = applyToValue ? '-moz-' + object[key] : object[key]; 93 | ret['-ms-' + key] = applyToValue ? '-ms-' + object[key] : object[key]; 94 | ret['-o-' + key] = applyToValue ? '-o-' + object[key] : object[key]; 95 | } 96 | return ret; 97 | } 98 | }; 99 | (function($) { 100 | $.fn.amazingaudioplayer = function(options) { 101 | var PlayerSkin = function(amazingPlayer, container, options, id) { 102 | this.amazingPlayer = amazingPlayer; 103 | this.container = container; 104 | this.options = options; 105 | this.id = id; 106 | this.volumeSaved = 1; 107 | var instance = this; 108 | var isTouch = 'ontouchstart' in window; 109 | var eStart = isTouch ? 'touchstart' : 'mousedown'; 110 | var eMove = isTouch ? 'touchmove' : 'mousemove'; 111 | var eCancel = isTouch ? 'touchcancel' : 'mouseup'; 112 | var formatSeconds = function(secs) { 113 | var hours = Math.floor(secs / 3600), 114 | minutes = Math.floor(secs % 3600 / 60), 115 | seconds = Math.ceil(secs % 3600 % 60); 116 | return ( 117 | (hours === 0 118 | ? '' 119 | : hours > 0 && hours.toString().length < 2 120 | ? '0' + hours + ':' 121 | : hours + ':') + 122 | (minutes.toString().length < 2 ? '0' + minutes : minutes) + 123 | ':' + 124 | (seconds.toString().length < 2 ? '0' + seconds : seconds) 125 | ); 126 | }; 127 | if (this.options.showimage) { 128 | this.$image = $("<div class='amazingaudioplayer-image'></div>"); 129 | this.$image.appendTo(this.container); 130 | this.container.bind('amazingaudioplayer.updateinfo', function( 131 | event, 132 | data 133 | ) { 134 | if (data.image.length > 0) { 135 | instance.$image.html("<img src='" + data.image + "' />"); 136 | } else { 137 | instance.$image.empty(); 138 | } 139 | }); 140 | } 141 | if (this.options.showtitle || this.options.showinfo) { 142 | this.$text = $("<div class='amazingaudioplayer-text'></div>"); 143 | this.$text.appendTo(this.container); 144 | if (this.options.showtitle) { 145 | this.$title = $("<div class='amazingaudioplayer-title'></div>"); 146 | this.$title.appendTo(this.$text); 147 | this.container.bind('amazingaudioplayer.updateinfo', function( 148 | event, 149 | data 150 | ) { 151 | var t = instance.options.titleformat.replace( 152 | /%TITLE%/g, 153 | data.title 154 | ); 155 | t = t.replace(/%ALBUM%/g, data.album); 156 | t = t.replace(/%ARTIST%/g, data.artist); 157 | t = t.replace(/%INFO%/g, data.info); 158 | t = t.replace(/%DURATION%/g, duration); 159 | t = t.replace(/%ID%/g, data.id); 160 | if (data.source.length > 0) { 161 | t = t.replace(/%AUDIO%/g, data.source[0].src); 162 | t = t.replace(/%AUDIOURL%/g, encodeURI(data.source[0].src)); 163 | } 164 | instance.$title.html(t); 165 | }); 166 | } 167 | if (this.options.showinfo) { 168 | this.$info = $("<div class='amazingaudioplayer-info'></div>"); 169 | this.$info.appendTo(this.$text); 170 | this.container.bind('amazingaudioplayer.updateinfo', function( 171 | event, 172 | data 173 | ) { 174 | var duration = data.duration ? formatSeconds(data.duration) : ''; 175 | var t = instance.options.infoformat.replace(/%TITLE%/g, data.title); 176 | t = t.replace(/%ALBUM%/g, data.album); 177 | t = t.replace(/%ARTIST%/g, data.artist); 178 | t = t.replace(/%INFO%/g, data.info); 179 | t = t.replace(/%DURATION%/g, duration); 180 | t = t.replace(/%ID%/g, data.id); 181 | if (data.source.length > 0) { 182 | t = t.replace(/%AUDIO%/g, data.source[0].src); 183 | t = t.replace(/%AUDIOURL%/g, encodeURI(data.source[0].src)); 184 | } 185 | instance.$info.html(t); 186 | }); 187 | } 188 | } 189 | var $bar = $("<div class='amazingaudioplayer-bar'></div>"); 190 | $bar.appendTo(this.container); 191 | var $playpause = $("<div class='amazingaudioplayer-playpause'></div>"); 192 | var $play = $( 193 | "<div class='amazingaudioplayer-play amazingaudioplayer-icon'><i class='am-icon-play'></i></div>" 194 | ); 195 | var $pause = $( 196 | "<div class='amazingaudioplayer-pause amazingaudioplayer-icon display-none'><i class='am-icon-pause'></i></div>" 197 | ); 198 | $playpause.appendTo($bar); 199 | $play.appendTo($playpause); 200 | $pause.appendTo($playpause); 201 | $play.click(function() { 202 | instance.amazingPlayer.playAudio(); 203 | }); 204 | $pause.click(function() { 205 | instance.amazingPlayer.pauseAudio(); 206 | }); 207 | this.container.bind('amazingaudioplayer.played', function( 208 | event, 209 | currentItem 210 | ) { 211 | $play.addClass('display-none').removeClass('display-block'); 212 | $pause.addClass('display-block').removeClass('display-none'); 213 | }); 214 | this.container.bind('amazingaudioplayer.paused', function( 215 | event, 216 | currentItem 217 | ) { 218 | $play.addClass('display-block').removeClass('display-none'); 219 | $pause.addClass('display-none').removeClass('display-block'); 220 | }); 221 | this.container.bind('amazingaudioplayer.stopped', function( 222 | event, 223 | currentItem 224 | ) { 225 | $play.addClass('display-block').removeClass('display-none'); 226 | $pause.addClass('display-none').removeClass('display-block'); 227 | }); 228 | if (this.options.showprevnext) { 229 | var $prev = $( 230 | "<div class='amazingaudioplayer-prev amazingaudioplayer-icon'><i class='am-icon-step-backward'></i></div>" 231 | ); 232 | var $next = $( 233 | "<div class='amazingaudioplayer-next amazingaudioplayer-icon'><i class='am-icon-step-forward'></i></div>" 234 | ); 235 | $prev.appendTo($bar); 236 | $next.appendTo($bar); 237 | $prev.click(function() { 238 | instance.amazingPlayer.audioRun( 239 | -2, 240 | instance.amazingPlayer.audioPlayer.isPlaying 241 | ); 242 | }); 243 | $next.click(function() { 244 | instance.amazingPlayer.audioRun( 245 | -1, 246 | instance.amazingPlayer.audioPlayer.isPlaying 247 | ); 248 | }); 249 | } 250 | if (this.options.showloop) { 251 | var $loop = $( 252 | "<div class='amazingaudioplayer-loop amazingaudioplayer-icon'><i class='am-icon-reorder'></i></div>" 253 | ); 254 | $loop.appendTo($bar); 255 | $loop.click(function() { 256 | if (instance.options.loop >= 2) { 257 | instance.options.loop = 0; 258 | } else { 259 | instance.options.loop++; 260 | } 261 | switch (instance.options.loop) { 262 | case 0: 263 | $loop.html("<i class='am-icon-reorder'></i>"); 264 | break; 265 | case 1: 266 | $loop.html("<i class='am-icon-retweet'></i>"); 267 | break; 268 | case 2: 269 | $loop.html("<i class='am-icon-history'></i>"); 270 | break; 271 | } 272 | }); 273 | } 274 | if ( 275 | this.options.showvolume && 276 | !AmazingAudioPlatforms.isIOS() && 277 | !AmazingAudioPlatforms.isAndroid() 278 | ) { 279 | this.$volume = $("<div class='amazingaudioplayer-volume'></div>"); 280 | this.$volume.appendTo($bar); 281 | this.$volumeButton = $( 282 | "<div class='amazingaudioplayer-volume-button amazingaudioplayer-icon'><i class='am-icon-volume-up'></i></div>" 283 | ); 284 | this.$volumeButton.appendTo(this.$volume); 285 | this.$volumeButton.click(function() { 286 | var volume = parseFloat( 287 | instance.amazingPlayer.audioPlayer.getVolume() 288 | ).toFixed(1); 289 | if (volume > 0) { 290 | instance.volumeSaved = volume; 291 | volume = 0; 292 | instance.$volumeButton.html("<i class='am-icon-volume-off'></i>"); 293 | } else { 294 | volume = instance.volumeSaved; 295 | instance.$volumeButton.html("<i class='am-icon-volume-up'></i>"); 296 | } 297 | if (volume > 0 && volume < 0.5) { 298 | instance.$volumeButton.html("<i class='am-icon-volume-down'></i>"); 299 | } 300 | instance.amazingPlayer.audioPlayer.setVolume(volume); 301 | if (instance.options.showvolumebar) { 302 | instance.$volumeBarAdjustActive.css({ 303 | height: Math.round(volume * 100) + '%' 304 | }); 305 | } 306 | }); 307 | if (this.options.showvolumebar) { 308 | this.$volumeBar = $( 309 | "<div class='amazingaudioplayer-volume-bar'></div>" 310 | ); 311 | this.$volumeBar.appendTo(this.$volume); 312 | this.$volumeBarAdjust = $( 313 | "<div class='amazingaudioplayer-volume-bar-adjust'></div>" 314 | ); 315 | this.$volumeBarAdjust.appendTo(this.$volumeBar); 316 | this.$volumeBarAdjustActive = $( 317 | "<div class='amazingaudioplayer-volume-bar-adjust-active'></div>" 318 | ); 319 | this.$volumeBarAdjustActive.appendTo(this.$volumeBarAdjust); 320 | this.$volumeBarAdjust 321 | .bind(eStart, function(e) { 322 | var e0 = isTouch ? e.originalEvent.touches[0] : e; 323 | var vol = parseFloat( 324 | 1 - 325 | (e0.pageY - instance.$volumeBarAdjust.offset().top) / 326 | instance.$volumeBarAdjust.height() 327 | ).toFixed(1); 328 | vol = vol > 1 ? 1 : vol < 0 ? 0 : vol; 329 | instance.$volumeBarAdjustActive.css({ 330 | height: Math.round(vol * 100) + '%' 331 | }); 332 | instance.amazingPlayer.audioPlayer.setVolume(vol); 333 | instance.$volumeBarAdjust.bind(eMove, function(e) { 334 | var e0 = isTouch ? e.originalEvent.touches[0] : e; 335 | var vol = parseFloat( 336 | 1 - 337 | (e0.pageY - instance.$volumeBarAdjust.offset().top) / 338 | instance.$volumeBarAdjust.height() 339 | ).toFixed(1); 340 | vol = vol > 1 ? 1 : vol < 0 ? 0 : vol; 341 | if (vol <= 0) { 342 | instance.$volumeButton.html( 343 | "<i class='am-icon-volume-off'></i>" 344 | ); 345 | } else if (vol > 0 && vol < 0.5) { 346 | instance.$volumeButton.html( 347 | "<i class='am-icon-volume-down'></i>" 348 | ); 349 | } else { 350 | instance.$volumeButton.html( 351 | "<i class='am-icon-volume-up'></i>" 352 | ); 353 | } 354 | instance.$volumeBarAdjustActive.css({ 355 | height: Math.round(vol * 100) + '%' 356 | }); 357 | instance.amazingPlayer.audioPlayer.setVolume(vol); 358 | }); 359 | }) 360 | .bind(eCancel, function() { 361 | instance.$volumeBarAdjust.unbind(eMove); 362 | }); 363 | this.hideVolumeBarTimeout = null; 364 | this.$volume.hover( 365 | function() { 366 | clearTimeout(instance.hideVolumeBarTimeout); 367 | if (AmazingAudioPlatforms.isIE678()) { 368 | instance.$volumeBar.show(); 369 | } else { 370 | instance.$volumeBar.fadeIn(); 371 | } 372 | }, 373 | function() { 374 | clearTimeout(instance.hideVolumeBarTimeout); 375 | instance.hideVolumeBarTimeout = setTimeout(function() { 376 | if (AmazingAudioPlatforms.isIE678()) { 377 | instance.$volumeBar.hide(); 378 | } else { 379 | instance.$volumeBar.fadeOut(); 380 | } 381 | }, 500); 382 | } 383 | ); 384 | } 385 | this.container.bind('amazingaudioplayer.setvolume', function( 386 | event, 387 | volume 388 | ) { 389 | volume = volume > 1 ? 1 : volume < 0 ? 0 : volume; 390 | if (instance.options.showvolumebar) { 391 | instance.$volumeBarAdjustActive.css({ 392 | height: Math.round(volume * 100) + '%' 393 | }); 394 | } 395 | }); 396 | } 397 | if (this.options.showtime) { 398 | var $time = $("<div class='amazingaudioplayer-time'></div>"); 399 | $time.appendTo($bar); 400 | this.container.bind('amazingaudioplayer.playprogress', function( 401 | event, 402 | data 403 | ) { 404 | var current = isNaN(data.current) ? 0 : data.current; 405 | var duration = 406 | isNaN(data.duration) || !isFinite(data.duration) 407 | ? 0 408 | : data.duration; 409 | var left = formatSeconds(Math.ceil(duration - current / 1e3)); 410 | current = formatSeconds(Math.ceil(current / 1e3)); 411 | duration = formatSeconds(Math.ceil(duration / 1e3)); 412 | var t; 413 | if (data.live) { 414 | t = instance.options.timeformatlive.replace('%CURRENT%', current); 415 | } else { 416 | t = instance.options.timeformat 417 | .replace('%CURRENT%', current) 418 | .replace('%DURATION%', duration) 419 | .replace('%LEFT%', left); 420 | } 421 | $time.html(t); 422 | }); 423 | this.container.bind('amazingaudioplayer.played', function( 424 | event, 425 | currentItem 426 | ) { 427 | if (instance.options.showloading) { 428 | $time.html(instance.options.loadingformat); 429 | } 430 | }); 431 | } 432 | if (this.options.showprogress) { 433 | var $progress = $("<div class='amazingaudioplayer-progress'></div>"); 434 | var $progressLoaded = $( 435 | "<div class='amazingaudioplayer-progress-loaded'></div>" 436 | ); 437 | var $progressPlayed = $( 438 | "<div class='amazingaudioplayer-progress-played'></div>" 439 | ); 440 | $progressLoaded.appendTo($progress); 441 | $progressPlayed.appendTo($progress); 442 | $progress.appendTo($bar); 443 | $progress 444 | .bind(eStart, function(e) { 445 | var e0 = isTouch ? e.originalEvent.touches[0] : e; 446 | var pos = (e0.pageX - $progress.offset().left) / $progress.width(); 447 | instance.amazingPlayer.setTime(pos); 448 | $progress.bind(eMove, function(e) { 449 | var e0 = isTouch ? e.originalEvent.touches[0] : e; 450 | var pos = 451 | (e0.pageX - $progress.offset().left) / $progress.width(); 452 | instance.amazingPlayer.setTime(pos); 453 | }); 454 | }) 455 | .bind(eCancel, function() { 456 | $progress.unbind(eMove); 457 | }); 458 | this.container.bind('amazingaudioplayer.loadprogress', function( 459 | event, 460 | progress 461 | ) { 462 | $progressLoaded.css({ 463 | width: progress + '%' 464 | }); 465 | }); 466 | this.container.bind('amazingaudioplayer.playprogress', function( 467 | event, 468 | data 469 | ) { 470 | if (data.live) { 471 | return; 472 | } 473 | var progress = 0; 474 | if ( 475 | !isNaN(data.duration) && 476 | isFinite(data.duration) && 477 | data.duration > 0 478 | ) { 479 | progress = Math.ceil(data.current * 100 / data.duration); 480 | } 481 | $progressPlayed.css({ 482 | width: progress + '%' 483 | }); 484 | }); 485 | } 486 | if (this.options.showtracklist) { 487 | this.$tracklistwrapper = $( 488 | "<div class='amazingaudioplayer-tracklist'></div>" 489 | ); 490 | this.$tracklistwrapper.appendTo(this.container); 491 | this.$tracklistcontainer = $( 492 | "<div class='amazingaudioplayer-tracklist-container'></div>" 493 | ); 494 | this.$tracklistcontainer.appendTo(this.$tracklistwrapper); 495 | this.$tracklist = $( 496 | "<div class='amazingaudioplayer-tracks-wrapper'></div>" 497 | ); 498 | this.$tracklist.appendTo(this.$tracklistcontainer); 499 | this.$tracks = $("<ul class='amazingaudioplayer-tracks'></ul>"); 500 | this.$tracks.appendTo(this.$tracklist); 501 | this.container.bind('amazingaudioplayer.switched', function( 502 | event, 503 | data 504 | ) { 505 | if (data.previous >= 0) { 506 | instance.trackitems[data.previous].removeClass( 507 | 'amazingaudioplayer-track-item-active' 508 | ); 509 | } 510 | if (data.current >= 0) { 511 | instance.trackitems[data.current].addClass( 512 | 'amazingaudioplayer-track-item-active' 513 | ); 514 | } 515 | }); 516 | this.tracklistItemHeight = 0; 517 | this.trackitems = []; 518 | for (var i = 0; i < this.amazingPlayer.elemLength; i++) { 519 | var $track = $("<li class='amazingaudioplayer-track-item'></li>"); 520 | var data = this.amazingPlayer.elemArray[i]; 521 | var duration = data.duration ? formatSeconds(data.duration) : ''; 522 | var t = this.options.tracklistitemformat.replace( 523 | /%TITLE%/g, 524 | data.title 525 | ); 526 | t = t.replace(/%ALBUM%/g, data.album); 527 | t = t.replace(/%ARTIST%/g, data.artist); 528 | t = t.replace(/%INFO%/g, data.info); 529 | t = t.replace(/%DURATION%/g, duration); 530 | t = t.replace(/%ID%/g, data.id); 531 | t = t.replace('%ORDER%', data.id); 532 | if (data.source.length > 0) { 533 | t = t.replace(/%AUDIO%/g, data.source[0].src); 534 | t = t.replace(/%AUDIOURL%/g, encodeURI(data.source[0].src)); 535 | } 536 | $track.data('order', i); 537 | $track.html(t); 538 | $track.appendTo(this.$tracks); 539 | this.tracklistItemHeight = $track.height(); 540 | this.trackitems.push($track); 541 | $track.click(function() { 542 | instance.amazingPlayer.audioRun($(this).data('order'), true); 543 | }); 544 | $track.hover( 545 | function() { 546 | $(this).addClass('amazingaudioplayer-track-item-active'); 547 | }, 548 | function() { 549 | if ( 550 | $(this).data('order') !== instance.amazingPlayer.currentItem 551 | ) { 552 | $(this).removeClass('amazingaudioplayer-track-item-active'); 553 | } 554 | } 555 | ); 556 | } 557 | } 558 | }; 559 | var FlashHTML5Player = function(amazingPlayer, flashPlayerEngine) { 560 | this.amazingPlayer = amazingPlayer; 561 | this.container = this.amazingPlayer.container; 562 | this.id = this.amazingPlayer.id; 563 | this.flashPlayerEngine = flashPlayerEngine; 564 | this.html5Object = null; 565 | this.flashObject = null; 566 | this.isHtml5 = false; 567 | this.isPlaying = false; 568 | this.html5LoadUpdate = null; 569 | this.audioItem = null; 570 | var a = document.createElement('audio'); 571 | this.supportMp3 = !!( 572 | a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, '') 573 | ); 574 | this.supportOgg = !!( 575 | a.canPlayType && 576 | a.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, '') 577 | ); 578 | this.loadFlashTimeout = 0; 579 | }; 580 | FlashHTML5Player.prototype = { 581 | initFlash: function() { 582 | var objectId = 'amazingflashaudioplayer-' + this.id; 583 | var flashCodes = 584 | "<div class='amazingaudioplayer-flash-container' style='position:absolute;top:0px;left:0px;'><div id='" + 585 | objectId + 586 | "' style='position:absolute;top:0px;left:0px;'></div></div>"; 587 | this.container.append(flashCodes); 588 | AmazingSWFObject.embedSWF( 589 | this.flashPlayerEngine, 590 | objectId, 591 | '1', 592 | '1', 593 | '9.0.0', 594 | false, 595 | { 596 | playerid: this.id 597 | }, 598 | { 599 | wmode: 'transparent', 600 | allowscriptaccess: 'always', 601 | allownetworking: 'all' 602 | }, 603 | {} 604 | ); 605 | this.flashAudioLoaded = false; 606 | this.flashAudioLoadedSucceed = false; 607 | this.playAudioAfterLoadedSucceed = false; 608 | this.html5AudioLoaded = false; 609 | }, 610 | initHtml5: function() { 611 | var html5Object = $( 612 | "<audio class='display-none' preload='" + 613 | (this.amazingPlayer.options.preloadaudio ? 'auto' : 'none') + 614 | "'></audio>" 615 | ); 616 | html5Object.appendTo(this.container); 617 | var html5Audio = html5Object.get(0); 618 | var instance = this; 619 | html5Audio.addEventListener('ended', function() { 620 | instance.amazingPlayer.onAudioEnded(); 621 | }); 622 | html5Audio.addEventListener('timeupdate', function() { 623 | instance.amazingPlayer.playProgress( 624 | html5Audio.currentTime * 1e3, 625 | html5Audio.duration * 1e3 626 | ); 627 | }); 628 | html5Audio.addEventListener('durationchange', function() { 629 | if (instance.isPlaying) html5Audio.play(); 630 | }); 631 | return html5Object; 632 | }, 633 | load: function(audioItem) { 634 | this.audioItem = audioItem; 635 | var audioSource = audioItem.source; 636 | var i; 637 | this.isHtml5 = false; 638 | if (!AmazingAudioPlatforms.isIE6789()) 639 | for (i = 0; i < audioSource.length; i++) 640 | if ( 641 | (audioSource[i].type == 'audio/mpeg' && this.supportMp3) || 642 | (audioSource[i].type == 'audio/ogg' && this.supportOgg) 643 | ) { 644 | this.isHtml5 = true; 645 | break; 646 | } 647 | if ( 648 | this.amazingPlayer.options.forcefirefoxflash && 649 | AmazingAudioPlatforms.isFirefox() && 650 | !AmazingAudioPlatforms.isMobile() 651 | ) 652 | this.isHtml5 = false; 653 | if (this.isHtml5) { 654 | if (!this.html5Object) this.html5Object = this.initHtml5(); 655 | this.html5Object.get(0).pause(); 656 | this.html5Object.empty(); 657 | this.html5Object.currentTime = 0; 658 | this.amazingPlayer.playProgress(0, 0); 659 | for (i = 0; i < audioSource.length; i++) 660 | if ( 661 | (audioSource[i].type == 'audio/mpeg' && this.supportMp3) || 662 | (audioSource[i].type == 'audio/ogg' && this.supportOgg) 663 | ) 664 | this.html5Object.append( 665 | "<source src='" + 666 | audioSource[i].src + 667 | "' type='" + 668 | audioSource[i].type + 669 | "'></source>" 670 | ); 671 | this.amazingPlayer.playProgress(0, 0); 672 | this.html5AudioLoaded = false; 673 | if (this.amazingPlayer.options.preloadaudio) this.html5LoadAudio(); 674 | } else { 675 | if (!this.flashObject) this.initFlash(); 676 | this.amazingPlayer.playProgress(0, 0); 677 | this.flashAudioLoaded = false; 678 | this.flashAudioLoadedSucceed = false; 679 | this.playAudioAfterLoadedSucceed = false; 680 | if (this.amazingPlayer.options.preloadaudio) 681 | this.flashLoadAudio(this.getMp3Src(), false); 682 | } 683 | }, 684 | html5LoadAudio: function() { 685 | this.html5AudioLoaded = true; 686 | this.html5Object.get(0).load(); 687 | var html5Audio = this.html5Object.get(0); 688 | var instance = this; 689 | this.html5LoadUpdate = setInterval(function() { 690 | if ( 691 | html5Audio.buffered && 692 | html5Audio.buffered.length > 0 && 693 | !isNaN(html5Audio.buffered.end(0)) && 694 | !isNaN(html5Audio.duration) 695 | ) { 696 | var percent = Math.ceil( 697 | html5Audio.buffered.end(0) * 100 / html5Audio.duration 698 | ); 699 | instance.amazingPlayer.loadProgress(percent); 700 | if (percent >= 100) clearInterval(instance.html5LoadUpdate); 701 | instance.amazingPlayer.playProgress( 702 | html5Audio.currentTime * 1e3, 703 | html5Audio.duration * 1e3 704 | ); 705 | } 706 | }, 100); 707 | }, 708 | flashLoadAudio: function(mp3Src, playAudio) { 709 | this.flashAudioLoaded = true; 710 | var instance = this; 711 | if (!AmazingFlashAudioPlayerReady[this.id]) { 712 | this.loadFlashTimeout += 100; 713 | if (this.loadFlashTimeout < 6e3) { 714 | setTimeout(function() { 715 | instance.flashLoadAudio(mp3Src, playAudio); 716 | }, 100); 717 | return; 718 | } 719 | } else { 720 | if (!this.flashObject) 721 | this.flashObject = AmazingSWFObject.getObjectById( 722 | 'amazingflashaudioplayer-' + this.id 723 | ); 724 | this.flashObject.loadAudio(mp3Src); 725 | this.flashAudioLoadedSucceed = true; 726 | if (playAudio || this.playAudioAfterLoadedSucceed) 727 | this.flashObject.playAudio(); 728 | this.playAudioAfterLoadedSucceed = false; 729 | } 730 | }, 731 | play: function() { 732 | if (this.isHtml5) { 733 | if (!this.html5AudioLoaded) this.html5LoadAudio(); 734 | this.html5Object.get(0).play(); 735 | } else if (this.flashAudioLoadedSucceed) this.flashObject.playAudio(); 736 | else if (this.flashAudioLoaded) this.playAudioAfterLoadedSucceed = true; 737 | else this.flashLoadAudio(this.getMp3Src(), true); 738 | this.isPlaying = true; 739 | }, 740 | getMp3Src: function() { 741 | var audioSource = this.audioItem.source; 742 | var mp3Src = ''; 743 | for (var i = 0; i < audioSource.length; i++) 744 | if (audioSource[i].type == 'audio/mpeg') mp3Src = audioSource[i].src; 745 | return mp3Src; 746 | }, 747 | pause: function() { 748 | if (this.isHtml5) this.html5Object.get(0).pause(); 749 | else this.flashObject.pauseAudio(); 750 | this.isPlaying = false; 751 | }, 752 | stop: function() { 753 | if (this.isHtml5) { 754 | this.html5Object.get(0).pause(); 755 | this.html5Object.get(0).currentTime = 0; 756 | } else this.flashObject.stopAudio(); 757 | this.isPlaying = false; 758 | }, 759 | setTime: function(pos, duration) { 760 | if (this.isHtml5) 761 | if ( 762 | !isNaN(this.html5Object.get(0).duration) && 763 | isFinite(this.html5Object.get(0).duration) && 764 | this.html5Object.get(0).duration > 0 765 | ) 766 | this.html5Object.get(0).currentTime = 767 | this.html5Object.get(0).duration * pos; 768 | else this.html5Object.get(0).currentTime = duration * pos; 769 | else this.flashObject.setTime(pos); 770 | }, 771 | getVolume: function() { 772 | if (this.isHtml5) return this.html5Object.get(0).volume; 773 | else return this.flashObject.getVolume(); 774 | }, 775 | setVolume: function(val) { 776 | if (this.isHtml5) this.html5Object.get(0).volume = val; 777 | else this.flashObject.setVolume(val); 778 | } 779 | }; 780 | var AmazingAudioPlayer = function(container, options, id) { 781 | this.container = container; 782 | this.options = options; 783 | this.id = id; 784 | $('.amazingaudioplayer-engine').css({ 785 | display: 'none' 786 | }); 787 | this.currentItem = -1; 788 | this.elemArray = []; 789 | this.elemLength = 0; 790 | this.audioPlayer = new FlashHTML5Player(this, 'player.swf'); 791 | this.initData(this.init); 792 | }; 793 | AmazingAudioPlayer.prototype = { 794 | initData: function(onSuccess) { 795 | this.readTags(); 796 | onSuccess(this); 797 | }, 798 | readTags: function() { 799 | var instance = this; 800 | $('.amazingaudioplayer-audios', this.container) 801 | .find('a') 802 | .each(function() { 803 | var $this = $(this); 804 | var audioSource = []; 805 | var audioId = instance.elemArray.length + 1; 806 | audioSource.push({ 807 | src: $(this).data('src'), 808 | type: $(this).data('type').toLowerCase() 809 | }); 810 | instance.elemArray.push({ 811 | id: audioId, 812 | source: audioSource, 813 | title: $this.data('title') + '', 814 | artist: $this.data('artist') + '', 815 | album: $this.data('album') + '', 816 | info: $this.data('info') + '', 817 | duration: $this.data('duration') ? $this.data('duration') : '', 818 | image: $this.data('image') + '', 819 | live: $this.data('live') ? true : false 820 | }); 821 | }); 822 | instance.elemLength = instance.elemArray.length; 823 | }, 824 | init: function(instance) { 825 | var i; 826 | if (instance.elemLength <= 0) { 827 | return; 828 | } 829 | if (instance.options.random) { 830 | for (i = instance.elemLength - 1; i > 0; i--) { 831 | if (i === 1 && Math.random() < 0.5) { 832 | break; 833 | } 834 | var index = Math.floor(Math.random() * i); 835 | var temp = instance.elemArray[index]; 836 | instance.elemArray[index] = instance.elemArray[i]; 837 | instance.elemArray[i] = temp; 838 | } 839 | for (i = 0; i < instance.elemLength; i++) { 840 | instance.elemArray[i].id = i + 1; 841 | } 842 | } 843 | instance.isPlaying = false; 844 | instance.loopCount = 0; 845 | instance.createSkin(); 846 | var params = instance.getParams(); 847 | var firstId = 0; 848 | if ( 849 | 'firstaudioid' in params && 850 | !isNaN(params.firstaudioid) && 851 | params.firstaudioid >= 0 && 852 | params.firstaudioid < instance.elemLength 853 | ) { 854 | firstId = params.firstaudioid; 855 | } 856 | instance.audioRun(firstId, false); 857 | if ('autoplayaudio' in params) { 858 | if (params.autoplayaudio === '1') { 859 | instance.options.autoplay = true; 860 | } else if (params.autoplayaudio === '0') { 861 | instance.options.autoplay = false; 862 | } 863 | } 864 | if ( 865 | instance.options.autoplay && 866 | !AmazingAudioPlatforms.isIOS() && 867 | !AmazingAudioPlatforms.isAndroid() 868 | ) { 869 | window.setTimeout(function() { 870 | instance.playAudio(); 871 | }, instance.options.autoplaytimeout); 872 | } 873 | if (instance.options.defaultvolume >= 0) { 874 | instance.setVolume( 875 | parseFloat(instance.options.defaultvolume / 100).toFixed(1) 876 | ); 877 | } 878 | instance.container.bind('amazingaudioplayer.stop', function(event, id) { 879 | if (id !== instance.id && instance.audioPlayer.isPlaying) { 880 | instance.pauseAudio(); 881 | } 882 | }); 883 | }, 884 | createSkin: function() { 885 | return new PlayerSkin(this, this.container, this.options, this.id); 886 | }, 887 | getParams: function() { 888 | var result = {}; 889 | var params = window.location.search.substring(1).split('&'); 890 | for (var i = 0; i < params.length; i++) { 891 | var value = params[i].split('='); 892 | if (value && value.length === 2) { 893 | result[value[0].toLowerCase()] = unescape(value[1]); 894 | } 895 | } 896 | return result; 897 | }, 898 | audioRun: function(index, autoPlay) { 899 | if (index < -2 || index >= this.elemLength) { 900 | return; 901 | } 902 | var nextItem; 903 | if (index === -2) { 904 | nextItem = 905 | this.currentItem <= 0 ? this.elemLength - 1 : this.currentItem - 1; 906 | } else if (index === -1) { 907 | nextItem = 908 | this.currentItem >= this.elemLength - 1 ? 0 : this.currentItem + 1; 909 | } else { 910 | nextItem = index; 911 | } 912 | 913 | this.container.trigger('amazingaudioplayer.switched', { 914 | previous: this.currentItem, 915 | current: nextItem 916 | }); 917 | this.currentItem = nextItem; 918 | this.container.trigger( 919 | 'amazingaudioplayer.updateinfo', 920 | this.elemArray[this.currentItem] 921 | ); 922 | this.audioPlayer.load(this.elemArray[this.currentItem]); 923 | if (autoPlay) { 924 | this.playAudio(); 925 | } 926 | }, 927 | onAudioEnded: function() { 928 | this.container.trigger('amazingaudioplayer.ended', this.currentItem); 929 | switch (this.options.loop) { 930 | case 0: 931 | if ( 932 | !this.options.noncontinous && 933 | this.currentItem < this.elemLength - 1 934 | ) { 935 | this.audioRun(-1, true); 936 | } else { 937 | this.stopAudio(); 938 | } 939 | break; 940 | case 1: 941 | this.audioRun(-1, true); 942 | break; 943 | case 2: 944 | this.audioRun(this.currentItem, true); 945 | break; 946 | } 947 | }, 948 | playAudio: function() { 949 | this.audioPlayer.play(); 950 | this.container.trigger('amazingaudioplayer.played', this.currentItem); 951 | if (this.options.stopotherplayers) { 952 | if (amazingAudioPlayerObjects && amazingAudioPlayerObjects.objects) { 953 | for (var i = 0; i < amazingAudioPlayerObjects.objects.length; i++) { 954 | if (amazingAudioPlayerObjects.objects[i].id === this.id) { 955 | continue; 956 | } 957 | amazingAudioPlayerObjects.objects[i].container.trigger( 958 | 'amazingaudioplayer.stop', 959 | this.id 960 | ); 961 | } 962 | } 963 | } 964 | }, 965 | pauseAudio: function() { 966 | this.audioPlayer.pause(); 967 | this.container.trigger('amazingaudioplayer.paused', this.currentItem); 968 | }, 969 | stopAudio: function() { 970 | this.audioPlayer.stop(); 971 | this.container.trigger('amazingaudioplayer.stopped', this.currentItem); 972 | this.container.trigger('amazingaudioplayer.playprogress', { 973 | current: 0, 974 | duration: 0, 975 | live: this.elemArray[this.currentItem].live 976 | }); 977 | }, 978 | setVolume: function(volume) { 979 | this.audioPlayer.setVolume(volume); 980 | this.container.trigger('amazingaudioplayer.setvolume', volume); 981 | }, 982 | loadProgress: function(progress) { 983 | this.container.trigger('amazingaudioplayer.loadprogress', progress); 984 | }, 985 | playProgress: function(current, duration) { 986 | if (current === 0 && duration === 1e5) { 987 | return; 988 | } 989 | var d0 = 990 | this.elemArray[this.currentItem].duration * 1e3 > duration || 991 | isNaN(duration) || 992 | !isFinite(duration) 993 | ? this.elemArray[this.currentItem].duration * 1e3 994 | : duration; 995 | this.container.trigger('amazingaudioplayer.playprogress', { 996 | current: current, 997 | duration: d0, 998 | live: this.elemArray[this.currentItem].live 999 | }); 1000 | }, 1001 | setTime: function(pos) { 1002 | this.audioPlayer.setTime( 1003 | pos, 1004 | this.elemArray[this.currentItem].duration 1005 | ); 1006 | } 1007 | }; 1008 | var bts = function(string) { 1009 | var ret = ''; 1010 | var bytes = string.split(','); 1011 | for (var i = 0; i < bytes.length; i++) { 1012 | ret += String.fromCharCode(bytes[i]); 1013 | } 1014 | return ret; 1015 | }; 1016 | options = options || {}; 1017 | for (var key in options) { 1018 | if (key.toLowerCase() !== key) { 1019 | options[key.toLowerCase()] = options[key]; 1020 | delete options[key]; 1021 | } 1022 | } 1023 | this.each(function() { 1024 | this.options = $.extend({}, options); 1025 | if ( 1026 | $(this).data('skin') && 1027 | typeof AMAZINGAUDIOPLAYER_SKIN_OPTIONS !== 'undefined' 1028 | ) { 1029 | if ($(this).data('skin') in AMAZINGAUDIOPLAYER_SKIN_OPTIONS) { 1030 | this.options = $.extend( 1031 | {}, 1032 | AMAZINGAUDIOPLAYER_SKIN_OPTIONS[$(this).data('skin')], 1033 | this.options 1034 | ); 1035 | } 1036 | } 1037 | var instance = this; 1038 | $.each($(this).data(), function(key, value) { 1039 | instance.options[key.toLowerCase()] = value; 1040 | }); 1041 | if ( 1042 | typeof amazingaudioplayer_options !== 'undefined' && 1043 | amazingaudioplayer_options 1044 | ) { 1045 | this.options = $.extend(this.options, amazingaudioplayer_options); 1046 | } 1047 | if ($('div#amazingaudioplayer_options').length) { 1048 | $.each($('div#amazingaudioplayer_options').data(), function( 1049 | key, 1050 | value 1051 | ) { 1052 | instance.options[key.toLowerCase()] = value; 1053 | }); 1054 | } 1055 | var searchoptions = {}; 1056 | var searchstring = window.location.search.substring(1).split('&'); 1057 | for (var i = 0; i < searchstring.length; i++) { 1058 | var keyvalue = searchstring[i].split('='); 1059 | if (keyvalue && keyvalue.length === 2) { 1060 | var key = keyvalue[0].toLowerCase(); 1061 | var value = unescape(keyvalue[1]).toLowerCase(); 1062 | if (value === 'true') { 1063 | searchoptions[key] = true; 1064 | } else if (value === 'false') { 1065 | searchoptions[key] = false; 1066 | } else { 1067 | searchoptions[key] = value; 1068 | } 1069 | } 1070 | } 1071 | this.options = $.extend(this.options, searchoptions); 1072 | var defaultOptions = { 1073 | autoplay: true, 1074 | autoplaytimeout: 1e3, 1075 | loop: 0, 1076 | random: false, 1077 | stopotherplayers: true, 1078 | forcefirefoxflash: false, 1079 | noncontinous: false, 1080 | preloadaudio: true, 1081 | defaultvolume: 60, 1082 | showprevnext: true, 1083 | showloop: true, 1084 | showprogress: true, 1085 | showtime: true, 1086 | timeformat: '%CURRENT% / %DURATION%', 1087 | timeformatlive: '%CURRENT% / LIVE', 1088 | showloading: true, 1089 | loadingformat: 'Loading...', 1090 | showvolume: true, 1091 | showvolumebar: true, 1092 | showtitle: true, 1093 | titleformat: '%TITLE%', 1094 | showinfo: true, 1095 | infoformat: '%ARTIST%', 1096 | showimage: true, 1097 | imagewidth: 100, 1098 | imageheight: 100, 1099 | imagefullwidth: false, 1100 | showtracklist: true, 1101 | tracklistitem: 10, 1102 | tracklistitemformat: '%ID%. %TITLE% <span>%ARTIST%</span>' 1103 | }; 1104 | this.options = $.extend(defaultOptions, this.options); 1105 | this.options.htmlfolder = window.location.href.substr( 1106 | 0, 1107 | window.location.href.lastIndexOf('/') + 1 1108 | ); 1109 | var audioplayerid; 1110 | if ('audioplayerid' in this.options) 1111 | audioplayerid = this.options.audioplayerid; 1112 | else { 1113 | audioplayerid = amazingaudioplayerId; 1114 | amazingaudioplayerId++; 1115 | } 1116 | var object = new AmazingAudioPlayer($(this), this.options, audioplayerid); 1117 | $(this).data('object', object); 1118 | $(this).data('id', audioplayerid); 1119 | amazingAudioPlayerObjects.addObject(object); 1120 | }); 1121 | }; 1122 | })(jQuery); 1123 | if (typeof amazingaudioplayerId === 'undefined') var amazingaudioplayerId = 0; 1124 | if (typeof amazingAudioPlayerObjects === 'undefined') 1125 | var amazingAudioPlayerObjects = new function() { 1126 | this.objects = []; 1127 | this.addObject = function(obj) { 1128 | this.objects.push(obj); 1129 | }; 1130 | }(); 1131 | if (typeof AmazingFlashAudioPlayerReady === 'undefined') { 1132 | var AmazingFlashAudioPlayerReady = []; 1133 | 1134 | function onAmazingFlashAudioPlayerReady(playerid) { 1135 | AmazingFlashAudioPlayerReady[playerid] = true; 1136 | } 1137 | 1138 | function amazingFlashAudioPlayerEventHandler(event, playerid, param, param1) { 1139 | var id = playerid; 1140 | for (var i = 0; i < amazingAudioPlayerObjects.objects.length; i++) 1141 | if (amazingAudioPlayerObjects.objects[i].id == playerid) { 1142 | id = i; 1143 | break; 1144 | } 1145 | switch (event) { 1146 | case 'completed': 1147 | amazingAudioPlayerObjects.objects[id].onAudioEnded(); 1148 | break; 1149 | case 'loadprogress': 1150 | amazingAudioPlayerObjects.objects[id].loadProgress(param); 1151 | break; 1152 | case 'playprogress': 1153 | amazingAudioPlayerObjects.objects[id].playProgress(param, param1); 1154 | break; 1155 | } 1156 | } 1157 | } 1158 | var AmazingSWFObject = (function() { 1159 | var UNDEF = 'undefined', 1160 | OBJECT = 'object', 1161 | SHOCKWAVE_FLASH = 'Shockwave Flash', 1162 | SHOCKWAVE_FLASH_AX = 'ShockwaveFlash.ShockwaveFlash', 1163 | FLASH_MIME_TYPE = 'application/x-shockwave-flash', 1164 | EXPRESS_INSTALL_ID = 'SWFObjectExprInst', 1165 | ON_READY_STATE_CHANGE = 'onreadystatechange', 1166 | win = window, 1167 | doc = document, 1168 | nav = navigator, 1169 | plugin = false, 1170 | domLoadFnArr = [main], 1171 | regObjArr = [], 1172 | objIdArr = [], 1173 | listenersArr = [], 1174 | storedAltContent, 1175 | storedAltContentId, 1176 | storedCallbackFn, 1177 | storedCallbackObj, 1178 | isDomLoaded = false, 1179 | isExpressInstallActive = false, 1180 | dynamicStylesheet, 1181 | dynamicStylesheetMedia, 1182 | autoHideShow = true, 1183 | ua = (function() { 1184 | var w3cdom = 1185 | typeof doc.getElementById != UNDEF && 1186 | typeof doc.getElementsByTagName != UNDEF && 1187 | typeof doc.createElement != UNDEF, 1188 | u = nav.userAgent.toLowerCase(), 1189 | p = nav.platform.toLowerCase(), 1190 | windows = p ? /win/.test(p) : /win/.test(u), 1191 | mac = p ? /mac/.test(p) : /mac/.test(u), 1192 | webkit = /webkit/.test(u) 1193 | ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, '$1')) 1194 | : false, 1195 | ie = !+'\v1', 1196 | playerVersion = [0, 0, 0], 1197 | d = null; 1198 | if ( 1199 | typeof nav.plugins != UNDEF && 1200 | typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT 1201 | ) { 1202 | d = nav.plugins[SHOCKWAVE_FLASH].description; 1203 | if ( 1204 | d && 1205 | !( 1206 | typeof nav.mimeTypes != UNDEF && 1207 | nav.mimeTypes[FLASH_MIME_TYPE] && 1208 | !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin 1209 | ) 1210 | ) { 1211 | plugin = true; 1212 | ie = false; 1213 | d = d.replace(/^.*\s+(\S+\s+\S+$)/, '$1'); 1214 | playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, '$1'), 10); 1215 | playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, '$1'), 10); 1216 | playerVersion[2] = /[a-zA-Z]/.test(d) 1217 | ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, '$1'), 10) 1218 | : 0; 1219 | } 1220 | } else if (typeof win.ActiveXObject != UNDEF) 1221 | try { 1222 | var a = new ActiveXObject(SHOCKWAVE_FLASH_AX); 1223 | if (a) { 1224 | d = a.GetVariable('$version'); 1225 | if (d) { 1226 | ie = true; 1227 | d = d.split(' ')[1].split(','); 1228 | playerVersion = [ 1229 | parseInt(d[0], 10), 1230 | parseInt(d[1], 10), 1231 | parseInt(d[2], 10) 1232 | ]; 1233 | } 1234 | } 1235 | } catch (e) {} 1236 | return { 1237 | w3: w3cdom, 1238 | pv: playerVersion, 1239 | wk: webkit, 1240 | ie: ie, 1241 | win: windows, 1242 | mac: mac 1243 | }; 1244 | })(), 1245 | onDomLoad = (function() { 1246 | if (!ua.w3) return; 1247 | if ( 1248 | (typeof doc.readyState != UNDEF && doc.readyState == 'complete') || 1249 | (typeof doc.readyState == UNDEF && 1250 | (doc.getElementsByTagName('body')[0] || doc.body)) 1251 | ) 1252 | callDomLoadFunctions(); 1253 | if (!isDomLoaded) { 1254 | if (typeof doc.addEventListener != UNDEF) 1255 | doc.addEventListener('DOMContentLoaded', callDomLoadFunctions, false); 1256 | if (ua.ie && ua.win) { 1257 | doc.attachEvent(ON_READY_STATE_CHANGE, function() { 1258 | if (doc.readyState == 'complete') { 1259 | doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee); 1260 | callDomLoadFunctions(); 1261 | } 1262 | }); 1263 | if (win == top) 1264 | (function() { 1265 | if (isDomLoaded) return; 1266 | try { 1267 | doc.documentElement.doScroll('left'); 1268 | } catch (e) { 1269 | setTimeout(arguments.callee, 0); 1270 | return; 1271 | } 1272 | callDomLoadFunctions(); 1273 | })(); 1274 | } 1275 | if (ua.wk) 1276 | (function() { 1277 | if (isDomLoaded) return; 1278 | if (!/loaded|complete/.test(doc.readyState)) { 1279 | setTimeout(arguments.callee, 0); 1280 | return; 1281 | } 1282 | callDomLoadFunctions(); 1283 | })(); 1284 | addLoadEvent(callDomLoadFunctions); 1285 | } 1286 | })(); 1287 | 1288 | function callDomLoadFunctions() { 1289 | if (isDomLoaded) return; 1290 | try { 1291 | var t = doc 1292 | .getElementsByTagName('body')[0] 1293 | .appendChild(createElement('span')); 1294 | t.parentNode.removeChild(t); 1295 | } catch (e) { 1296 | return; 1297 | } 1298 | isDomLoaded = true; 1299 | var dl = domLoadFnArr.length; 1300 | for (var i = 0; i < dl; i++) domLoadFnArr[i](); 1301 | } 1302 | 1303 | function addDomLoadEvent(fn) { 1304 | if (isDomLoaded) fn(); 1305 | else domLoadFnArr[domLoadFnArr.length] = fn; 1306 | } 1307 | 1308 | function addLoadEvent(fn) { 1309 | if (typeof win.addEventListener != UNDEF) 1310 | win.addEventListener('load', fn, false); 1311 | else if (typeof doc.addEventListener != UNDEF) 1312 | doc.addEventListener('load', fn, false); 1313 | else if (typeof win.attachEvent != UNDEF) addListener(win, 'onload', fn); 1314 | else if (typeof win.onload == 'function') { 1315 | var fnOld = win.onload; 1316 | win.onload = function() { 1317 | fnOld(); 1318 | fn(); 1319 | }; 1320 | } else win.onload = fn; 1321 | } 1322 | 1323 | function main() { 1324 | if (plugin) testPlayerVersion(); 1325 | else matchVersions(); 1326 | } 1327 | 1328 | function testPlayerVersion() { 1329 | var b = doc.getElementsByTagName('body')[0]; 1330 | var o = createElement(OBJECT); 1331 | o.setAttribute('type', FLASH_MIME_TYPE); 1332 | var t = b.appendChild(o); 1333 | if (t) { 1334 | var counter = 0; 1335 | (function() { 1336 | if (typeof t.GetVariable != UNDEF) { 1337 | var d = t.GetVariable('$version'); 1338 | if (d) { 1339 | d = d.split(' ')[1].split(','); 1340 | ua.pv = [ 1341 | parseInt(d[0], 10), 1342 | parseInt(d[1], 10), 1343 | parseInt(d[2], 10) 1344 | ]; 1345 | } 1346 | } else if (counter < 10) { 1347 | counter++; 1348 | setTimeout(arguments.callee, 10); 1349 | return; 1350 | } 1351 | b.removeChild(o); 1352 | t = null; 1353 | matchVersions(); 1354 | })(); 1355 | } else matchVersions(); 1356 | } 1357 | 1358 | function matchVersions() { 1359 | var rl = regObjArr.length; 1360 | if (rl > 0) 1361 | for (var i = 0; i < rl; i++) { 1362 | var id = regObjArr[i].id; 1363 | var cb = regObjArr[i].callbackFn; 1364 | var cbObj = { 1365 | success: false, 1366 | id: id 1367 | }; 1368 | if (ua.pv[0] > 0) { 1369 | var obj = getElementById(id); 1370 | if (obj) 1371 | if ( 1372 | hasPlayerVersion(regObjArr[i].swfVersion) && 1373 | !(ua.wk && ua.wk < 312) 1374 | ) { 1375 | setVisibility(id, true); 1376 | if (cb) { 1377 | cbObj.success = true; 1378 | cbObj.ref = getObjectById(id); 1379 | cb(cbObj); 1380 | } 1381 | } else if (regObjArr[i].expressInstall && canExpressInstall()) { 1382 | var att = {}; 1383 | att.data = regObjArr[i].expressInstall; 1384 | att.width = obj.getAttribute('width') || '0'; 1385 | att.height = obj.getAttribute('height') || '0'; 1386 | if (obj.getAttribute('class')) 1387 | att.styleclass = obj.getAttribute('class'); 1388 | if (obj.getAttribute('align')) 1389 | att.align = obj.getAttribute('align'); 1390 | var par = {}; 1391 | var p = obj.getElementsByTagName('param'); 1392 | var pl = p.length; 1393 | for (var j = 0; j < pl; j++) 1394 | if (p[j].getAttribute('name').toLowerCase() != 'movie') 1395 | par[p[j].getAttribute('name')] = p[j].getAttribute('value'); 1396 | showExpressInstall(att, par, id, cb); 1397 | } else { 1398 | displayAltContent(obj); 1399 | if (cb) cb(cbObj); 1400 | } 1401 | } else { 1402 | setVisibility(id, true); 1403 | if (cb) { 1404 | var o = getObjectById(id); 1405 | if (o && typeof o.SetVariable != UNDEF) { 1406 | cbObj.success = true; 1407 | cbObj.ref = o; 1408 | } 1409 | cb(cbObj); 1410 | } 1411 | } 1412 | } 1413 | } 1414 | 1415 | function getObjectById(objectIdStr) { 1416 | var r = null; 1417 | var o = getElementById(objectIdStr); 1418 | if (o && o.nodeName == 'OBJECT') 1419 | if (typeof o.SetVariable != UNDEF) r = o; 1420 | else { 1421 | var n = o.getElementsByTagName(OBJECT)[0]; 1422 | if (n) r = n; 1423 | } 1424 | return r; 1425 | } 1426 | 1427 | function canExpressInstall() { 1428 | return ( 1429 | !isExpressInstallActive && 1430 | hasPlayerVersion('6.0.65') && 1431 | (ua.win || ua.mac) && 1432 | !(ua.wk && ua.wk < 312) 1433 | ); 1434 | } 1435 | 1436 | function showExpressInstall(att, par, replaceElemIdStr, callbackFn) { 1437 | isExpressInstallActive = true; 1438 | storedCallbackFn = callbackFn || null; 1439 | storedCallbackObj = { 1440 | success: false, 1441 | id: replaceElemIdStr 1442 | }; 1443 | var obj = getElementById(replaceElemIdStr); 1444 | if (obj) { 1445 | if (obj.nodeName == 'OBJECT') { 1446 | storedAltContent = abstractAltContent(obj); 1447 | storedAltContentId = null; 1448 | } else { 1449 | storedAltContent = obj; 1450 | storedAltContentId = replaceElemIdStr; 1451 | } 1452 | att.id = EXPRESS_INSTALL_ID; 1453 | if ( 1454 | typeof att.width == UNDEF || 1455 | (!/%$/.test(att.width) && parseInt(att.width, 10) < 310) 1456 | ) 1457 | att.width = '310'; 1458 | if ( 1459 | typeof att.height == UNDEF || 1460 | (!/%$/.test(att.height) && parseInt(att.height, 10) < 137) 1461 | ) 1462 | att.height = '137'; 1463 | doc.title = doc.title.slice(0, 47) + ' - Flash Player Installation'; 1464 | var pt = ua.ie && ua.win ? 'ActiveX' : 'PlugIn', 1465 | fv = 1466 | 'MMredirectURL=' + 1467 | win.location.toString().replace(/&/g, '%26') + 1468 | '&MMplayerType=' + 1469 | pt + 1470 | '&MMdoctitle=' + 1471 | doc.title; 1472 | if (typeof par.flashvars != UNDEF) par.flashvars += '&' + fv; 1473 | else par.flashvars = fv; 1474 | if (ua.ie && ua.win && obj.readyState != 4) { 1475 | var newObj = createElement('div'); 1476 | replaceElemIdStr += 'SWFObjectNew'; 1477 | newObj.setAttribute('id', replaceElemIdStr); 1478 | obj.parentNode.insertBefore(newObj, obj); 1479 | obj.style.display = 'none'; 1480 | (function() { 1481 | if (obj.readyState == 4) obj.parentNode.removeChild(obj); 1482 | else setTimeout(arguments.callee, 10); 1483 | })(); 1484 | } 1485 | createSWF(att, par, replaceElemIdStr); 1486 | } 1487 | } 1488 | 1489 | function displayAltContent(obj) { 1490 | if (ua.ie && ua.win && obj.readyState != 4) { 1491 | var el = createElement('div'); 1492 | obj.parentNode.insertBefore(el, obj); 1493 | el.parentNode.replaceChild(abstractAltContent(obj), el); 1494 | obj.style.display = 'none'; 1495 | (function() { 1496 | if (obj.readyState == 4) obj.parentNode.removeChild(obj); 1497 | else setTimeout(arguments.callee, 10); 1498 | })(); 1499 | } else obj.parentNode.replaceChild(abstractAltContent(obj), obj); 1500 | } 1501 | 1502 | function abstractAltContent(obj) { 1503 | var ac = createElement('div'); 1504 | if (ua.win && ua.ie) ac.innerHTML = obj.innerHTML; 1505 | else { 1506 | var nestedObj = obj.getElementsByTagName(OBJECT)[0]; 1507 | if (nestedObj) { 1508 | var c = nestedObj.childNodes; 1509 | if (c) { 1510 | var cl = c.length; 1511 | for (var i = 0; i < cl; i++) 1512 | if ( 1513 | !(c[i].nodeType == 1 && c[i].nodeName == 'PARAM') && 1514 | !(c[i].nodeType == 8) 1515 | ) 1516 | ac.appendChild(c[i].cloneNode(true)); 1517 | } 1518 | } 1519 | } 1520 | return ac; 1521 | } 1522 | 1523 | function createSWF(attObj, parObj, id) { 1524 | var r, 1525 | el = getElementById(id); 1526 | if (ua.wk && ua.wk < 312) return r; 1527 | if (el) { 1528 | if (typeof attObj.id == UNDEF) attObj.id = id; 1529 | if (ua.ie && ua.win) { 1530 | var att = ''; 1531 | for (var i in attObj) 1532 | if (attObj[i] != Object.prototype[i]) 1533 | if (i.toLowerCase() == 'data') parObj.movie = attObj[i]; 1534 | else if (i.toLowerCase() == 'styleclass') 1535 | att += ' class="' + attObj[i] + '"'; 1536 | else if (i.toLowerCase() != 'classid') 1537 | att += ' ' + i + '="' + attObj[i] + '"'; 1538 | var par = ''; 1539 | for (var j in parObj) 1540 | if (parObj[j] != Object.prototype[j]) 1541 | par += '<param name="' + j + '" value="' + parObj[j] + '" />'; 1542 | el.outerHTML = 1543 | '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + 1544 | att + 1545 | '>' + 1546 | par + 1547 | '</object>'; 1548 | objIdArr[objIdArr.length] = attObj.id; 1549 | r = getElementById(attObj.id); 1550 | } else { 1551 | var o = createElement(OBJECT); 1552 | o.setAttribute('type', FLASH_MIME_TYPE); 1553 | for (var m in attObj) 1554 | if (attObj[m] != Object.prototype[m]) 1555 | if (m.toLowerCase() == 'styleclass') 1556 | o.setAttribute('class', attObj[m]); 1557 | else if (m.toLowerCase() != 'classid') o.setAttribute(m, attObj[m]); 1558 | for (var n in parObj) 1559 | if (parObj[n] != Object.prototype[n] && n.toLowerCase() != 'movie') 1560 | createObjParam(o, n, parObj[n]); 1561 | el.parentNode.replaceChild(o, el); 1562 | r = o; 1563 | } 1564 | } 1565 | return r; 1566 | } 1567 | 1568 | function createObjParam(el, pName, pValue) { 1569 | var p = createElement('param'); 1570 | p.setAttribute('name', pName); 1571 | p.setAttribute('value', pValue); 1572 | el.appendChild(p); 1573 | } 1574 | 1575 | function removeSWF(id) { 1576 | var obj = getElementById(id); 1577 | if (obj && obj.nodeName == 'OBJECT') 1578 | if (ua.ie && ua.win) { 1579 | obj.style.display = 'none'; 1580 | (function() { 1581 | if (obj.readyState == 4) removeObjectInIE(id); 1582 | else setTimeout(arguments.callee, 10); 1583 | })(); 1584 | } else obj.parentNode.removeChild(obj); 1585 | } 1586 | 1587 | function removeObjectInIE(id) { 1588 | var obj = getElementById(id); 1589 | if (obj) { 1590 | for (var i in obj) if (typeof obj[i] == 'function') obj[i] = null; 1591 | obj.parentNode.removeChild(obj); 1592 | } 1593 | } 1594 | 1595 | function getElementById(id) { 1596 | var el = null; 1597 | try { 1598 | el = doc.getElementById(id); 1599 | } catch (e) {} 1600 | return el; 1601 | } 1602 | 1603 | function createElement(el) { 1604 | return doc.createElement(el); 1605 | } 1606 | 1607 | function addListener(target, eventType, fn) { 1608 | target.attachEvent(eventType, fn); 1609 | listenersArr[listenersArr.length] = [target, eventType, fn]; 1610 | } 1611 | 1612 | function hasPlayerVersion(rv) { 1613 | var pv = ua.pv, 1614 | v = rv.split('.'); 1615 | v[0] = parseInt(v[0], 10); 1616 | v[1] = parseInt(v[1], 10) || 0; 1617 | v[2] = parseInt(v[2], 10) || 0; 1618 | return pv[0] > v[0] || 1619 | (pv[0] == v[0] && pv[1] > v[1]) || 1620 | (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2]) 1621 | ? true 1622 | : false; 1623 | } 1624 | 1625 | function createCSS(sel, decl, media, newStyle) { 1626 | if (ua.ie && ua.mac) return; 1627 | var h = doc.getElementsByTagName('head')[0]; 1628 | if (!h) return; 1629 | var m = media && typeof media == 'string' ? media : 'screen'; 1630 | if (newStyle) { 1631 | dynamicStylesheet = null; 1632 | dynamicStylesheetMedia = null; 1633 | } 1634 | if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 1635 | var s = createElement('style'); 1636 | s.setAttribute('type', 'text/css'); 1637 | s.setAttribute('media', m); 1638 | dynamicStylesheet = h.appendChild(s); 1639 | if ( 1640 | ua.ie && 1641 | ua.win && 1642 | typeof doc.styleSheets != UNDEF && 1643 | doc.styleSheets.length > 0 1644 | ) 1645 | dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1]; 1646 | dynamicStylesheetMedia = m; 1647 | } 1648 | if (ua.ie && ua.win) { 1649 | if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) 1650 | dynamicStylesheet.addRule(sel, decl); 1651 | } else if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) 1652 | dynamicStylesheet.appendChild( 1653 | doc.createTextNode(sel + ' {' + decl + '}') 1654 | ); 1655 | } 1656 | 1657 | function setVisibility(id, isVisible) { 1658 | if (!autoHideShow) return; 1659 | var v = isVisible ? 'visible' : 'hidden'; 1660 | if (isDomLoaded && getElementById(id)) 1661 | getElementById(id).style.visibility = v; 1662 | else createCSS('#' + id, 'visibility:' + v); 1663 | } 1664 | 1665 | function urlEncodeIfNecessary(s) { 1666 | var regex = /[\\\"<>\.;]/; 1667 | var hasBadChars = regex.exec(s) != null; 1668 | return hasBadChars && typeof encodeURIComponent != UNDEF 1669 | ? encodeURIComponent(s) 1670 | : s; 1671 | } 1672 | var cleanup = (function() { 1673 | if (ua.ie && ua.win) 1674 | window.attachEvent('onunload', function() { 1675 | var ll = listenersArr.length; 1676 | for (var i = 0; i < ll; i++) 1677 | listenersArr[i][0].detachEvent( 1678 | listenersArr[i][1], 1679 | listenersArr[i][2] 1680 | ); 1681 | var il = objIdArr.length; 1682 | for (var j = 0; j < il; j++) removeSWF(objIdArr[j]); 1683 | for (var k in ua) ua[k] = null; 1684 | ua = null; 1685 | for (var l in AmazingSWFObject) AmazingSWFObject[l] = null; 1686 | AmazingSWFObject = null; 1687 | }); 1688 | })(); 1689 | return { 1690 | registerObject: function( 1691 | objectIdStr, 1692 | swfVersionStr, 1693 | xiSwfUrlStr, 1694 | callbackFn 1695 | ) { 1696 | if (ua.w3 && objectIdStr && swfVersionStr) { 1697 | var regObj = {}; 1698 | regObj.id = objectIdStr; 1699 | regObj.swfVersion = swfVersionStr; 1700 | regObj.expressInstall = xiSwfUrlStr; 1701 | regObj.callbackFn = callbackFn; 1702 | regObjArr[regObjArr.length] = regObj; 1703 | setVisibility(objectIdStr, false); 1704 | } else if (callbackFn) 1705 | callbackFn({ 1706 | success: false, 1707 | id: objectIdStr 1708 | }); 1709 | }, 1710 | getObjectById: function(objectIdStr) { 1711 | if (ua.w3) return getObjectById(objectIdStr); 1712 | }, 1713 | embedSWF: function( 1714 | swfUrlStr, 1715 | replaceElemIdStr, 1716 | widthStr, 1717 | heightStr, 1718 | swfVersionStr, 1719 | xiSwfUrlStr, 1720 | flashvarsObj, 1721 | parObj, 1722 | attObj, 1723 | callbackFn 1724 | ) { 1725 | var callbackObj = { 1726 | success: false, 1727 | id: replaceElemIdStr 1728 | }; 1729 | if ( 1730 | ua.w3 && 1731 | !(ua.wk && ua.wk < 312) && 1732 | swfUrlStr && 1733 | replaceElemIdStr && 1734 | widthStr && 1735 | heightStr && 1736 | swfVersionStr 1737 | ) { 1738 | setVisibility(replaceElemIdStr, false); 1739 | addDomLoadEvent(function() { 1740 | widthStr += ''; 1741 | heightStr += ''; 1742 | var att = {}; 1743 | if (attObj && typeof attObj === OBJECT) 1744 | for (var i in attObj) att[i] = attObj[i]; 1745 | att.data = swfUrlStr; 1746 | att.width = widthStr; 1747 | att.height = heightStr; 1748 | var par = {}; 1749 | if (parObj && typeof parObj === OBJECT) 1750 | for (var j in parObj) par[j] = parObj[j]; 1751 | if (flashvarsObj && typeof flashvarsObj === OBJECT) 1752 | for (var k in flashvarsObj) 1753 | if (typeof par.flashvars != UNDEF) 1754 | par.flashvars += '&' + k + '=' + flashvarsObj[k]; 1755 | else par.flashvars = k + '=' + flashvarsObj[k]; 1756 | if (hasPlayerVersion(swfVersionStr)) { 1757 | var obj = createSWF(att, par, replaceElemIdStr); 1758 | if (att.id == replaceElemIdStr) 1759 | setVisibility(replaceElemIdStr, true); 1760 | callbackObj.success = true; 1761 | callbackObj.ref = obj; 1762 | } else if (xiSwfUrlStr && canExpressInstall()) { 1763 | att.data = xiSwfUrlStr; 1764 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 1765 | return; 1766 | } else setVisibility(replaceElemIdStr, true); 1767 | if (callbackFn) callbackFn(callbackObj); 1768 | }); 1769 | } else if (callbackFn) callbackFn(callbackObj); 1770 | }, 1771 | switchOffAutoHideShow: function() { 1772 | autoHideShow = false; 1773 | }, 1774 | ua: ua, 1775 | getFlashPlayerVersion: function() { 1776 | return { 1777 | major: ua.pv[0], 1778 | minor: ua.pv[1], 1779 | release: ua.pv[2] 1780 | }; 1781 | }, 1782 | hasFlashPlayerVersion: hasPlayerVersion, 1783 | createSWF: function(attObj, parObj, replaceElemIdStr) { 1784 | if (ua.w3) return createSWF(attObj, parObj, replaceElemIdStr); 1785 | else return undefined; 1786 | }, 1787 | showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) { 1788 | if (ua.w3 && canExpressInstall()) 1789 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 1790 | }, 1791 | removeSWF: function(objElemIdStr) { 1792 | if (ua.w3) removeSWF(objElemIdStr); 1793 | }, 1794 | createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) { 1795 | if (ua.w3) createCSS(selStr, declStr, mediaStr, newStyleBoolean); 1796 | }, 1797 | addDomLoadEvent: addDomLoadEvent, 1798 | addLoadEvent: addLoadEvent, 1799 | getQueryParamValue: function(param) { 1800 | var q = doc.location.search || doc.location.hash; 1801 | if (q) { 1802 | if (/\?/.test(q)) q = q.split('?')[1]; 1803 | if (param == null) return urlEncodeIfNecessary(q); 1804 | var pairs = q.split('&'); 1805 | for (var i = 0; i < pairs.length; i++) 1806 | if (pairs[i].substring(0, pairs[i].indexOf('=')) == param) 1807 | return urlEncodeIfNecessary( 1808 | pairs[i].substring(pairs[i].indexOf('=') + 1) 1809 | ); 1810 | } 1811 | return ''; 1812 | }, 1813 | expressInstallCallback: function() { 1814 | if (isExpressInstallActive) { 1815 | var obj = getElementById(EXPRESS_INSTALL_ID); 1816 | if (obj && storedAltContent) { 1817 | obj.parentNode.replaceChild(storedAltContent, obj); 1818 | if (storedAltContentId) { 1819 | setVisibility(storedAltContentId, true); 1820 | if (ua.ie && ua.win) storedAltContent.style.display = 'block'; 1821 | } 1822 | if (storedCallbackFn) storedCallbackFn(storedCallbackObj); 1823 | } 1824 | isExpressInstallActive = false; 1825 | } 1826 | } 1827 | }; 1828 | })(); 1829 | 1830 | $(function() { 1831 | function json2str(json) { 1832 | try { 1833 | return JSON.stringify(json); 1834 | } catch (e) { 1835 | return; 1836 | } 1837 | } 1838 | $('#form-tabs li').on('click', function() { 1839 | var holder = { 1840 | name: '例如: 不要说话 陈奕迅', 1841 | id: '例如: 25906124', 1842 | url: '例如: http://music.163.com/#/song?id=25906124', 1843 | 'pattern-name': '^.+$', 1844 | 'pattern-id': '^[\\w\\/\\|]+$', 1845 | 'pattern-url': '^https?:\\/\\/\\S+$' 1846 | }; 1847 | var filter = $(this).data('filter'); 1848 | $(this).addClass('am-active').siblings('li').removeClass('am-active'); 1849 | $('#music_input') 1850 | .data('filter', filter) 1851 | .attr({ 1852 | placeholder: holder[filter], 1853 | pattern: holder['pattern-' + filter] 1854 | }) 1855 | .removeClass('am-field-valid am-field-error am-active') 1856 | .closest('.am-form-group') 1857 | .removeClass('am-form-success am-form-error') 1858 | .find('.am-alert') 1859 | .hide(); 1860 | if (filter === 'url') { 1861 | $('.music-type').hide(); 1862 | } else { 1863 | $('.music-type').show(); 1864 | } 1865 | }); 1866 | $('#form-vld').validator({ 1867 | onValid: function(validity) { 1868 | $(validity.field).closest('.am-form-group').find('.am-alert').hide(); 1869 | }, 1870 | onInValid: function(validity) { 1871 | var $field = $(validity.field); 1872 | var $group = $field.closest('.am-form-group'); 1873 | var $alert = $group.find('.am-alert'); 1874 | var msgs = { 1875 | name: '将 名称 和 作者 一起输入可提高匹配度', 1876 | id: '输入错误,请查看下面的帮助', 1877 | url: '输入错误,请查看下面的帮助' 1878 | }; 1879 | var msg = 1880 | msgs[$field.data('filter')] || this.getValidationMessage(validity); 1881 | if (!$alert.length) { 1882 | $alert = $( 1883 | '<div class="am-alert am-alert-danger am-animation-shake"></div>' 1884 | ) 1885 | .hide() 1886 | .appendTo($group); 1887 | } 1888 | $alert.html(msg).show(); 1889 | }, 1890 | submit: function(validity) { 1891 | validity.preventDefault(); 1892 | if (this.isFormValid()) { 1893 | var post_data = { 1894 | music_input: $.trim($('#music_input').val()), 1895 | music_filter: $('#music_input').data('filter'), 1896 | music_type: $('input[name="music_type"]:checked').val() 1897 | }; 1898 | if ($('#music_input').data('filter') === 'url') { 1899 | post_data.music_type = '_'; 1900 | } 1901 | return $.ajax({ 1902 | type: 'POST', 1903 | url: location.href.split('?')[0], 1904 | timeout: 30000, 1905 | data: post_data, 1906 | dataType: 'json', 1907 | beforeSend: function() { 1908 | $('#music_input').attr('disabled', true); 1909 | $('#submit').button('loading'); 1910 | }, 1911 | success: function(result) { 1912 | if (result.code === 200 && result.data) { 1913 | var mname = result.data[0].name ? result.data[0].name : '暂无'; 1914 | var mauthor = result.data[0].author 1915 | ? result.data[0].author 1916 | : '暂无'; 1917 | $('#form-vld').slideUp(); 1918 | $('.music-main').slideDown(); 1919 | $('#music-link').val(result.data[0].link); 1920 | $('#music-src').val(result.data[0].music); 1921 | $('#music-name').val(mname); 1922 | $('#music-author').val(mauthor); 1923 | var html = 1924 | '<div id="player" class="audio-player"><div class="amazingaudioplayer-audios">'; 1925 | for (var i = 0; i < result.data.length; i++) { 1926 | var rname = result.data[i].name ? result.data[i].name : '暂无'; 1927 | var rauthor = result.data[i].author 1928 | ? result.data[i].author 1929 | : '暂无'; 1930 | var rpic = result.data[i].pic 1931 | ? result.data[i].pic 1932 | : location.href + 'static/nopic.jpg'; 1933 | html += 1934 | '<a data-artist="' + 1935 | rauthor + 1936 | '" data-title="' + 1937 | rname + 1938 | '" data-album="' + 1939 | rname + 1940 | '" data-info="" data-image="' + 1941 | rpic + 1942 | '" data-link="' + 1943 | result.data[i].link + 1944 | '" data-src="' + 1945 | result.data[i].music + 1946 | '" data-type="audio/mpeg"></a>'; 1947 | } 1948 | html += '</div>'; 1949 | $('#music-show').html(html); 1950 | $('#player').amazingaudioplayer(); 1951 | $( 1952 | '.amazingaudioplayer-prev, .amazingaudioplayer-next, .amazingaudioplayer-track-item' 1953 | ).on('click', function() { 1954 | var index = $('.amazingaudioplayer-track-item-active').index(); 1955 | var mlink = $('.amazingaudioplayer-audios a') 1956 | .eq(index) 1957 | .data('link'); 1958 | var mmusic = $('.amazingaudioplayer-audios a') 1959 | .eq(index) 1960 | .data('src'); 1961 | var mname = $('.amazingaudioplayer-audios a') 1962 | .eq(index) 1963 | .data('title'); 1964 | var mauthor = $('.amazingaudioplayer-audios a') 1965 | .eq(index) 1966 | .data('artist'); 1967 | $('#music-link').val(mlink); 1968 | $('#music-src').val(mmusic); 1969 | $('#music-name').val(mname); 1970 | $('#music-author').val(mauthor); 1971 | }); 1972 | } else { 1973 | $('#music_input') 1974 | .closest('.am-form-group') 1975 | .find('.am-alert') 1976 | .html(result.error || '(°ー°〃) 服务器好像罢工了') 1977 | .show(); 1978 | } 1979 | }, 1980 | error: function(e, t) { 1981 | var errtext = '(°ー°〃) 出了点小问题,请重试'; 1982 | if (t === 'timeout') { 1983 | errtext = '(°ー°〃) 请求超时了,可能是您的网络慢'; 1984 | } 1985 | $('#music_input') 1986 | .closest('.am-form-group') 1987 | .find('.am-alert') 1988 | .html(errtext) 1989 | .show(); 1990 | }, 1991 | complete: function() { 1992 | $('#music_input').attr('disabled', false); 1993 | $('#submit').button('reset'); 1994 | } 1995 | }); 1996 | } 1997 | } 1998 | }); 1999 | $('.music-main input').focus(function() { 2000 | $(this).select(); 2001 | }); 2002 | $('.music-tips .more').on('click', function() { 2003 | $(this).hide(); 2004 | $('.music-tips p').show(); 2005 | }); 2006 | $('#getit').on('click', function() { 2007 | $('audio')[0].pause(); 2008 | $('#form-vld').slideDown(); 2009 | $('.music-main').slideUp(); 2010 | $('.music-main input').val(''); 2011 | $('#music-show').html(''); 2012 | }); 2013 | }); 2014 | --------------------------------------------------------------------------------