├── .gitignore ├── README.md ├── dist └── wp-player │ ├── assets │ ├── css │ │ ├── wp-player-plugin.css │ │ └── wp-player.css │ ├── images │ │ ├── default.png │ │ ├── playing.gif │ │ ├── wp_player_bg.png │ │ ├── wp_player_bg2x.png │ │ └── wp_player_bg_8.png │ └── js │ │ ├── libs │ │ └── soundmanager │ │ │ ├── soundmanager2.js │ │ │ └── soundmanager2.swf │ │ ├── plugin-uploader.js │ │ └── wp-player.js │ ├── include │ ├── Meting.php │ ├── metaboxes.php │ └── player.php │ ├── readme.txt │ └── wp-player.php ├── gulpfile.js ├── package.json └── src ├── assets ├── css │ ├── wp-player-plugin.css │ └── wp-player.css ├── images │ ├── default.png │ ├── playing.gif │ ├── wp_player_bg.png │ ├── wp_player_bg2x.png │ └── wp_player_bg_8.png └── js │ ├── libs │ └── soundmanager │ │ ├── soundmanager2.js │ │ └── soundmanager2.swf │ ├── plugin-uploader.js │ └── wp-player.js ├── include ├── Meting.php ├── metaboxes.php └── player.php ├── readme.txt └── wp-player.php /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules* 2 | .DS_Store 3 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WP-Player V2.6.2 2 | ========= 3 | 4 | WP-Player 一个迷你歌曲播放器,支持多歌曲播放,支持使用网易云音乐, 虾米音乐, QQ音乐, 百度音乐歌曲地址, 也支持自定义上传音乐。 5 | 6 | ## Demo参考 7 | 8 | 9 | ## 源码说明 10 | 1. `./src/` 为源码目录 11 | 2. `./dist/` 为打包后输出目录 12 | 3. 请使用 `./dist/wp-player/` 文件夹下文件,此目录为插件目录可以打成 `zip` 包上传至 `wordpress` 后台 13 | 14 | ## 源码打包 15 | ``` bash 16 | # install dependencies 17 | npm install 18 | 19 | # build for production with minification 20 | npm run build 21 | ``` 22 | 23 | ### 声明 24 | 本插件仅供个人学习研究使用,请勿作为各种商业用户,音乐版权归各音乐平台所有。 25 | 26 | ### Update Ver 2.6.2 (2021-12-30) [@timk-lalala](https://github.com/timk-lalala) 27 | 1. 修复 网易云音乐某些链接从http重写https的问题 28 | 29 | ### Update Ver 2.6.1 (2017-06-12) 30 | 1. 修复 PHP 语法报错问题 31 | 32 | ### Update Ver 2.6.0 (2017-06-07) 33 | 1. 新增 QQ音乐 百度音乐平台。 34 | 2. 新增 当前歌曲不能播放,跳转至下一曲。 35 | 3. 新增 随机播放歌曲功能。 36 | 4. 新增 $('[data-wp-player="wp-player"]').WPPlayer('reload'); 方法,让单页面用户 可重新初始化播放器。 37 | 5. 新增 $('[data-wp-player="wp-player"]').WPPlayer('destroy'); 方法,用于销毁播放器; 38 | 6. 新增 歌曲列表自动滚动到中间位置,在也不用为找不到当前歌曲烦恼。 39 | 7. 修复虾米,网易获取音乐失败问题。 40 | 8. 修复样式问题,改善收缩列表动画问题 41 | 9. 美化歌曲列表滚动条样式 42 | 10. 更新 SoundManager 版本至最新版本 43 | 11. 在此感谢 @metowolf 开发的 Meting 框架,为获取音乐提供了更简单的方式 44 | 12. 项目地址:https://github.com/metowolf/Meting 45 | 13. 此版本项目结够改动比较大,请删除插件重新安装最好 46 | 47 | ### Update Ver 2.5.1 (2015-02-06) 48 | 1. 紧急修复因2.5.0版本导致网易云音乐不能播放问题 49 | 50 | ### Update Ver 2.5.0 (2015-02-06) 51 | 1. 新增自定义上传歌曲支持多歌曲。 52 | 2. 歌曲按一行一个填写,歌曲内容列表按歌曲名显示。 53 | 3. 因考虑自定义上传将会有多条记录,所以才用一行一首歌曲来填写。 54 | 4. 修正歌曲只有两首时,上一首,下一首按钮无用情况。 55 | 5. 现阶段功能上已基本完成,年前将只会进行Bug修复,暂不会开发新功能。 56 | 6. 如还想用2.4.2 老版本 请戳:https://github.com/webjyh/WP-Player/releases 57 | 58 | ### Update Ver 2.4.2 (2015-01-29) 59 | 1. 修正因某些主题使用字体图标导致样式错位 60 | 2. 修正某些主题下歌单不显示的问题 61 | 3. 修正若干样式排版问题 62 | 4. 下个版本将会入手自定义上传多歌曲功能 63 | 64 | ### Update Ver 2.4.1 (2015-01-13) 65 | 1. 解决因关闭歌词功能导致的JS错误。 66 | 2. 修正移动端最小宽度问题。 67 | 68 | ### Update Ver 2.4.0 (2015-01-11) 69 | 1. 新增移动端播放适配(暂不支持移动端自动播放歌曲功能)。 70 | 2. 因移动端的兼容性问题,自动播放功能将无法使用。 71 | 3. 因歌词功能消耗较大,在移动端下将被禁用。 72 | 4. 在 iPhone 6、iPhone 5s、iPhone 5、iOS 8.x+系统 测试通过。 73 | 5. 在 Android 4.1+ 系统测试过能。 74 | 6. 因移动端机型混杂,各大浏览器厂商也更多,难免会有意料之外的Bug。 75 | 7. 修正移动端样式问题。 76 | 8. 如想用 v2.3.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 77 | 78 | ### Update Ver 2.3.1 (2015-01-08) 79 | 1. 紧急修复暂无歌词Bug 80 | 2. 修正图片缓存问题 81 | 82 | ### Update Ver 2.3.0 (2015-01-08) 83 | 1. 新增歌词预览功能(支持虾米和网易) 84 | 2. 因歌词预览功能比较耗费资源,可在单独添加播放器时,打开或关闭此功能。 85 | 3. 因获取歌词功能接口的一些特殊性,如在后台选择中未出现歌词功能,则表示当前站点暂不支持。 86 | 4. 因其调取接口获取歌词在处理歌词时间上难免会有些误差(请不要太在意这些细节) 87 | 5. 修正一些样式错误。 88 | 6. 如想用 v2.2.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 89 | 90 | ### Update Ver 2.2.0 (2015-01-01) 91 | 1. 新增网易云音乐网址的调用(支持单音乐页面、专辑页面、艺人页面、精选集[即歌单]页面) 92 | 2. 因网易的接口一些特殊性,如在后台选择网站类型中没有出现网易音乐,则您当前的站点暂不支持网易云音乐。 93 | 3. 其次要感谢牧风的音乐播放插件,作为参考实现了网易接口的思路。 94 | 4. 在次还要感谢此文作者 https://github.com/yanunon/NeteaseCloudMusic/wiki/网易云音乐API分析 95 | 5. 修正播放器请求容错处理方案。 96 | 6. 去除短代码中 00:00 字样。 97 | 7. 修正播放器样式问题。 98 | 8. 如想用 v2.1.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 99 | 100 | ### Update Ver 2.1.0 (2014-12-27) 101 | 1. 因发现最近播放器在解析虾米地址时,出现不稳定的情况,采用最新发现的虾米接口。 102 | 2. 新接口将是直接调取虾米网接口,速度更快且稳定。 103 | 3. 为其保险起见,怕日后虾米封其接口,如获取失败,将移交给新浪云解析。 104 | 4. 去除播放器HTML中的 Loading 字样,为其前台显示更美观。 105 | 5. 修正播放器样式问题。 106 | 6. 修正某些情况下导致图片无法显示的情况。 107 | 7. 如想用 v2.0.1 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 108 | 109 | ### Update Ver 2.0.1 (2014-12-24) 110 | 1. 修正因接口调制后台而导致无法抓取虾米ID的问题 111 | 2. 后台无法抓取将采用 新浪云来解析 112 | 3. 修正播放器样式问题。 113 | 114 | ### Update Ver 2.0.0 (2014-12-23) 115 | 1. 播放器新版扁平皮肤 116 | 2. 支持虾米多歌曲播放 117 | 3. 支持单音乐页面、专辑页面、艺人页面、精选集页面 118 | 4. 重构虾米地址填写解析;现只需复制网址,便可自动解析虾米ID。 119 | 5. 将解析虾米地址移交至插件本身 120 | 6. 重构播放器JS,采用SoundManger2来管理 121 | 7. 支持IE6+,FireFox,Chrome; 122 | 8. 废除短代码 loop 参数 123 | 9. 关闭后台无用选项设置 124 | 125 | ### Update Ver 1.3.4 (2014-08-24) 126 | 1. 修正 弱干 Bug 127 | 2. 由百度云平台解析 换至 新浪云平台 128 | 3. 百度云平台解析至 2014-10月底废除,请各位小伙伴赶紧更新 129 | 130 | ### Update Ver 1.3.2 (2014-02-19) 131 | 1. 修正jQuery后台选项无用的Bug 132 | 133 | ### Update Ver 1.3.1 (2014-02-17) 134 | 1. 插件提交到官方 WordPress plugins 库 135 | 2. 因提交到官方所以删除一些无用文件 136 | 3. 由原来自带的jQuery库 修改调用WordPress自带jQuery库 137 | 138 | ### Update Ver 1.3.0 (2014-02-14) 139 | 1. 增加百度云API,使解析虾米音乐地址更稳定 140 | 2. 细节调整 141 | 3. 修复Bug 142 | 4. 代码重构 143 | 5. 初次使用请到插件设置页面,设置虾米解析API。 144 | 145 | ### Update Ver 1.2.0 146 | 1. 增加皮肤选择 147 | 2. 新增扁平化皮肤 具体效果查看本页面播放器 148 | 3. 增加插件设定按钮 149 | 4. 扁平化皮肤 只支持 Chrome 和 FireFox 游览器 150 | 151 | ### Update Ver 1.1.0 152 | 1. 因虾米API变动,解决获取歌曲地址问题! 153 | 2. 添加根据虾米ID自动获取歌曲信息 154 | 3. MeatBox 更加简洁化 155 | 156 | 157 | ##填写方法: 158 | 1. WP-Player 支持网易云音乐, 虾米音乐, QQ音乐, 百度音乐平台 159 | 2. 如在网易云音乐打开喜欢的歌曲页面,复制歌曲页面的网址如:http://music.163.com/#/song?id=191213 160 | 3. 并将复制的网址填写到后面的表单内。音乐类型将根据网址自动做出选择。 161 | 4. 点击获取音乐ID按钮,此时音乐ID出现在表单中。 162 | 5. 将短代码 [player autoplay="1" random="1"] 填入您的文章内容中。 163 | 6. 短代码中 autoplay 表示是否自动播放;参数"0"表示否;"1"表示是; 164 | 7. 短代码中 random 表示是否随机播放;参数"0"表示否;"1"表示是; 165 | 8. 支持播放歌单:单音乐页面、专辑页面、艺人页面、精选集页面。 166 | 9. PS:本插件需要您的服务器或主机支持 PHP 5.4+ and Curl, OpenSSL 模块已安装。 167 | 10. Tips:本插件仅供个人学习研究使用,请勿作为各种商业用户,音乐版权归各音乐平台所有 168 | PS:一篇文章只能插入一个播放器,因为用了MetaBox获取参数,只能一篇文章使用一个。 169 | 170 | 171 | ## 使用方法: 172 | 173 | WordPress 插件使用短代码来实现调用播放器 174 | ```html 175 | [player] 176 | [player autoplay="1" random="1"] 177 | ``` 178 | -------------------------------------------------------------------------------- /dist/wp-player/assets/css/wp-player-plugin.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name WP-Player Admin CSS 3 | * @desc WP-Player MetaBox 样式 4 | * @author M.J 5 | * @date 2014-12-19 6 | * @update 2022-1-5 7 | * @URL http://webjyh.com 8 | * @Github https://github.com/webjyh/WP-Player 9 | * @version 2.6.2 10 | */.wp-player-wrap{padding:10px}.wp-player-wrap .wp-player-tabs{margin:0;border-bottom:1px solid #EEE;height:36px}.wp-player-wrap .wp-player-tabs li{display:inline-block;margin:0}.wp-player-wrap .wp-player-tabs li a{display:inline-block;padding:0 15px;height:36px;line-height:36px;color:#333;text-decoration:none;margin-right:10px;border:1px solid #FFF;border-bottom:0}.wp-player-wrap .wp-player-tabs li.current a{border-color:#EEE;background:#FFF;font-weight:700}.wp-player-wrap .wp-player-row{border:1px solid #EEE;padding:10px 15px;border-top:none}.wp-player-wrap .wp-player-row .red{color:red}.wp-player-wrap .wp-player-inner{display:none}.wp-player-wrap .wp-player-inner.current{display:block}.wp-player-wrap .wp-player-text{height:28px;width:50%}.wp-player-wrap .wp-player-select{vertical-align:top}.wp-player-wrap .wp-player-textarea{margin-bottom:10px}.wp-player-wrap .wp-player-textarea textarea{width:60%;min-height:120px;margin-bottom:5px;margin-right:5px}.wp-player-wrap .wp-player-textarea p.desc{margin:0;color:#666}@media screen and (min-width:1200px){.wp-player-wrap .wp-player-text{width:35%}}@media screen and (min-width:1300px){.wp-player-wrap .wp-player-text{width:45%}}@media screen and (min-width:1400px){.wp-player-wrap .wp-player-text{width:50%}}@media screen and (min-width:1500px){.wp-player-wrap .wp-player-text{width:55%}} -------------------------------------------------------------------------------- /dist/wp-player/assets/css/wp-player.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name WP-Player CSS 3 | * @desc WP-Player 样式表 4 | * @author M.J 5 | * @date 2014-12-21 6 | * @update 2022-1-5 7 | * @URL http://webjyh.com 8 | * @Github https://github.com/webjyh/WP-Player 9 | * @version 2.6.2 10 | * 11 | */.wp-player{overflow:hidden;background:#FFF;width:350px;min-width:300px;margin:10px auto;border:1px solid #DDD;box-shadow:0 0 10px rgba(0,0,0,.15);box-sizing:content-box}.wp-player *{-webkit-user-select:none;-webkit-overflow-scrolling:touch;-webkit-tap-highlight-color:transparent;outline:0;border-radius:0;box-shadow:none;font-family:"Microsoft Yahei",arial;box-sizing:content-box;font-size:12px;margin:0;padding:0;background:0 0;border:0;text-indent:0;line-height:1.4}.wp-player .wp-player-author,.wp-player .wp-player-list ul li,.wp-player .wp-player-list ul li a,.wp-player .wp-player-list-order,.wp-player .wp-player-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.wp-player .wp-player-controls a,.wp-player .wp-player-list-btn,.wp-player .wp-player-lyrics-btn,.wp-player .wp-player-play-current{background:url(../images/wp_player_bg.png) -9999px -9999px no-repeat!important}@media screen and (-webkit-min-device-pixel-ratio:2),screen and (max-moz-device-pixel-ratio:2){.wp-player .wp-player-controls a,.wp-player .wp-player-list-btn,.wp-player .wp-player-lyrics-btn,.wp-player .wp-player-play-current{background-image:url(../images/wp_player_bg2x.png)!important;background-size:58px auto!important}}.wp-player .wp-player-box{height:90px;-webkit-user-select:none;user-select:none}.wp-player .wp-player-thumb{position:relative;float:left;width:90px;height:90px;overflow:hidden}.wp-player .wp-player-thumb img{padding:0!important;margin:0!important;border-radius:0!important;box-shadow:none!important;border:0!important;display:block;width:90px;height:90px;vertical-align:top}.wp-player .wp-player-playing{display:none;position:absolute;z-index:2;top:0;left:0;width:90px;height:90px;background:#000;background:rgba(0,0,0,.4);filter:alpha(opacity=40)}.wp-player .wp-player-playing span{display:block;position:absolute;top:50%;left:50%;margin:-5px 0 0 -5px;z-index:3;width:11px;height:11px;background:url(../images/playing.gif) no-repeat!important}.wp-player .wp-player-panel{margin-left:100px;padding-top:0;padding-right:10px}.wp-player .wp-player-title{font-size:14px;height:24px;line-height:24px;color:#555}.wp-player .wp-player-author{line-height:1.4;color:#999;margin-bottom:5px}.wp-player .wp-player-progress{height:4px;margin-bottom:7px;background:#e7e9eb;border-radius:5px}.wp-player .wp-player-seek-bar{width:0;height:100%;background:#DDD;cursor:pointer;border-radius:5px}.wp-player .wp-player-play-bar{position:relative;width:0;height:100%;background:#00cacf;border-radius:5px;-webkit-transition:all .3s;transition:all .3s}.wp-player .wp-player-play-current{display:block;position:absolute;top:-3px;right:-5px;width:10px;height:10px;background-position:0 -57px!important}.wp-player .wp-player-controls-holder{position:relative;height:28px;overflow:hidden}.wp-player .wp-player-time{position:absolute;top:0;left:0;width:45px;height:28px;line-height:28px;color:#9a9a9a;text-align:center}.wp-player .wp-player-lyrics-btn{cursor:pointer;position:absolute;top:9px;right:25px;width:14px;height:14px;background-position:-20px -56px!important}.wp-player .wp-player-list-btn{cursor:pointer;position:absolute;top:10px;right:0;width:18px;height:10px;background-position:-40px -57px!important}.wp-player .wp-player-controls{position:absolute;top:0;left:50%;margin-left:-50px;width:100px;height:28px}.wp-player .wp-player-controls a{outline:0!important;margin:0!important;padding:0!important;border:0!important;text-decoration:none!important;position:absolute;display:block}.wp-player a.wp-player-next,.wp-player a.wp-player-previous{top:9px;left:0;width:16px;height:10px;box-shadow:none!important;background-position:0 -6px!important}.wp-player a.wp-player-next{left:auto;right:0;background-position:-42px -6px!important}.wp-player a.wp-player-play,.wp-player a.wp-player-stop{top:0;left:36px;width:28px;height:28px;background-position:0 -21px!important;box-shadow:none!important}.wp-player a.wp-player-stop{display:none;background-position:-30px -21px!important}.wp-player .wp-player-main{position:relative}.wp-player .wp-player-list{border-top:1px solid #DDD;-webkit-overflow-scrolling:touch;max-height:330px;overflow:auto;-webkit-transition:height .6s;transition:height .6s}.wp-player .wp-player-list::-webkit-scrollbar{height:8px;width:8px}.wp-player .wp-player-list::-webkit-scrollbar-button{height:0;width:0}.wp-player .wp-player-list::-webkit-scrollbar-track:horizontal,.wp-player .wp-player-list::-webkit-scrollbar-track:vertical{background-clip:padding-box;background-color:#fff}.wp-player .wp-player-list::-webkit-scrollbar-thumb{-webkit-box-shadow:inset 1px 1px 0 rgba(0,0,0,.1),inset 0 -1px 0 rgba(0,0,0,.07);background-clip:padding-box;background-color:rgba(0,0,0,.2);min-height:28px;padding-top:100}.wp-player .wp-player-list::-webkit-scrollbar-thumb:hover{-webkit-box-shadow:inset 1px 1px 1px rgba(0,0,0,.25);background-color:rgba(0,0,0,.4)}.wp-player .wp-player-list::-webkit-scrollbar-thumb:active{-webkit-box-shadow:inset 1px 1px 3px rgba(0,0,0,.35);background-color:rgba(0,0,0,.5)}.wp-player .wp-player-list::-webkit-scrollbar-thumb:horizontal,.wp-player .wp-player-list::-webkit-scrollbar-thumb:vertical,.wp-player .wp-player-list::-webkit-scrollbar-track:horizontal,.wp-player .wp-player-list::-webkit-scrollbar-track:vertical{border-width:0}.wp-player .wp-player-list::-webkit-scrollbar-track:hover{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.1);background-color:rgba(0,0,0,.05)}.wp-player .wp-player-list::-webkit-scrollbar-track:active{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.14),inset -1px -1px 0 rgba(0,0,0,.07);background-color:rgba(0,0,0,.05)}.wp-player .wp-player-list ul{margin:0;padding:0;border:0;list-style:none}.wp-player .wp-player-list ul li{list-style-type:none!important;background:#FFF;margin:0!important;border:0!important;cursor:pointer;list-style:none;height:22px;line-height:22px;padding:4px 0}.wp-player .wp-player-list ul li:after,.wp-player .wp-player-list ul li:before,.wp-player .wp-player-list ul li:hover:after,.wp-player .wp-player-list ul li:hover:before{content:''!important;font-family:"Microsoft Yahei"!important;margin:0!important}.wp-player .wp-player-list ul li a{outline:0!important;box-shadow:none!important;border:0;background:0 0!important;height:22px;overflow:hidden;line-height:22px;padding:0 10px;display:block;color:#333;border-left:4px solid #FFF;text-decoration:none}.wp-player .wp-player-list ul li.odd{line-height:22px;background:#f7f7f7}.wp-player .wp-player-list ul li.odd a{line-height:22px;border-color:#f7f7f7}.wp-player .wp-player-list ul li a:hover,.wp-player .wp-player-list ul li.current a{border-left:4px solid #00cacf}.wp-player .wp-player-list-hide{height:0!important;border-top:0!important}.wp-player .wp-player-list-title{line-height:22px}.wp-player .wp-player-list-author{line-height:22px;float:right;padding-left:10px}.wp-player .wp-player-list-order{line-height:22px;float:left;color:#9a9a9a;width:25px;height:100%}.wp-player .wp-player-lyrics{border-top:1px solid #DDD;max-height:330px;overflow:hidden}.wp-player .wp-player-lyrics ul{display:none;margin:0;padding:0;border:0;list-style:none;-webkit-transition:all .3s linear;transition:all .3s linear}.wp-player .wp-player-lyrics ul li{list-style-type:none!important;background:#FFF;margin:0!important;line-height:1.5!important;border:0!important;padding:5px 10px!important;color:#666;font-size:12px;text-align:center;-webkit-transition:color .5s linear;transition:color .5s linear;height:17px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.wp-player .wp-player-lyrics ul li:after,.wp-player .wp-player-lyrics ul li:before{content:''!important;font-family:"Microsoft Yahei"!important;margin:0!important}.wp-player .wp-player-lyrics ul li.current{font-size:14px;color:#00cacf}@media screen and (max-width:720px){.wp-player .wp-player-thumb,.wp-player-lyrics ul,.wp-player-lyrics-btn{display:none}.wp-player{width:auto;min-width:210px}.wp-player .wp-player-panel{margin:0;padding-left:10px;width:auto}.wp-player .wp-player-list ul li{padding:6px 0;height:26px;line-height:26px}.wp-player .wp-player-list ul li a{height:26px;line-height:26px;font-size:14px}.wp-player .wp-player-list-author,.wp-player .wp-player-list-order,.wp-player .wp-player-list-title{line-height:26px}} -------------------------------------------------------------------------------- /dist/wp-player/assets/images/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/dist/wp-player/assets/images/default.png -------------------------------------------------------------------------------- /dist/wp-player/assets/images/playing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/dist/wp-player/assets/images/playing.gif -------------------------------------------------------------------------------- /dist/wp-player/assets/images/wp_player_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/dist/wp-player/assets/images/wp_player_bg.png -------------------------------------------------------------------------------- /dist/wp-player/assets/images/wp_player_bg2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/dist/wp-player/assets/images/wp_player_bg2x.png -------------------------------------------------------------------------------- /dist/wp-player/assets/images/wp_player_bg_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/dist/wp-player/assets/images/wp_player_bg_8.png -------------------------------------------------------------------------------- /dist/wp-player/assets/js/libs/soundmanager/soundmanager2.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/dist/wp-player/assets/js/libs/soundmanager/soundmanager2.swf -------------------------------------------------------------------------------- /dist/wp-player/assets/js/plugin-uploader.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name Wp-Player Admin JS 3 | * @desc MetaBox JavaScript 4 | * @depend jQuery 5 | * @author M.J 6 | * @date 2014-12-19 7 | * @update 2022-1-5 8 | * @URL http://webjyh.com 9 | * @Github https://github.com/webjyh/WP-Player 10 | * @version 2.6.2 11 | * 12 | */ 13 | jQuery(document).ready(function(){var a=window.send_to_editor;jQuery(".WP-Player-File").on("click",function(){var r=jQuery(this).prev(),t=r.attr("id");return tb_show("","media-upload.php?media-upload.php?type=image&TB_iframe=true"),!(window.send_to_editor=function(e){var i=jQuery(e).attr("href"),e=r.val();tb_remove(),jQuery("#"+t).val(e+"\r"+i),window.send_to_editor=a})}),jQuery("#wp-player-tabs > li").on("click",function(){var e=jQuery(this).index();jQuery(this).addClass("current").siblings().removeClass("current"),jQuery("#wp-player-row > div").hide().eq(e).fadeIn()}),jQuery("#wp_player_get_xiami_id").on("click",function(){var e=jQuery("#wp_player_music_type"),i=jQuery("#mp3_xiami"),r=jQuery("#mp3_xiami_type"),t=i.val(),a={};if(""==t)return i.focus(),!1;var n=-1s[d].time&&(c=s[i],s[i]=s[d],s[d]=c);for(this.lyric={},i=0;i"+s[i].lyric+"",this.lyric[s[i].time]=i;a.lyricList=f(o).appendTo(a.lyrics.children("ul"));var p=a.lyrics.children("ul").height(),t=Math.floor(this.lyricH/2),a=p-t;this.offset={min:Math.floor(t/this.line),max:Math.floor(a/this.line)}},setLyric:function(t){var i=this.DOM,s=this.offset,e=Math.floor(t/1e3),t=this.lyric&&this.lyric[e],e=0;void 0!==t&&i.lyricList&&this.mark!=t&&(t>=s.min&&(e=t-s.min),t>=s.max&&(e=s.max-s.min),i.lyricList.removeClass("current").eq(t).addClass("current"),i.lyrics.children("ul").css("margin-top",-e*this.line),this.mark=t)},emptyLyric:function(){var t=this.DOM;this.lyric=null,t.lyrics.children("ul").css("margin-top",0).html("")},noLyric:function(t){var i=this.DOM,t=void 0===t?"暂无歌词":t;this.lyric=null,i.lyrics.children("ul").html("
  • "+t+"
  • ")},addEvent:function(){var e,a,i=this.DOM,s=this,t=this.isMobile?"touchend":"click";i.listbtn.on(t,function(){var t=f(this).hasClass("wp-player-open");i.lyrics.children("ul").stop(!0,!0).hide(),f(this)[t?"removeClass":"addClass"]("wp-player-open"),i.list.show()[t?"removeClass":"addClass"]("wp-player-list-hide")}),this.attr.lyric&&i.lyricsbtn.on(t,function(){i.listbtn.addClass("wp-player-open"),i.list.hide(),i.lyrics.children("ul").stop(!0,!0).fadeIn()});function n(t){var i=void 0===t?f(this):f(t).parents("li"),t=parseInt(i.attr("data-index"),10),i=i.hasClass("current")&&0s.data.length-1?s.index=0:s.index=t,i&&!s.sound.paused?s.sound.pause():i&&s.sound.paused?s.sound.resume():(s.sound&&s.sound.pause(),s.reset().setList(),s.data[s.index]&&s.data[s.index].url?s.createSound(s.index):s.getSongInfo(s.index,!0))}return this.isMobile?(i.list[0].addEventListener("touchstart",function(t){var i=t.target.nodeName;"A"!==i&&"SPAN"!==i||(t=t.touches[0],e=t.clientX,a=t.clientY)},!1),i.list[0].addEventListener("touchend",function(t){var i,s=t.target.nodeName;"A"!==s&&"SPAN"!==s||(s=(i=t.changedTouches[0]).clientX,i=i.clientY,Math.abs(e-s)<6&&Math.abs(a-i)<6&&(n(t.target),a=e=null))},!1)):i.list.on("click","li",function(){n.call(this)}),this},soundEvent:function(){var t=this.DOM,i=this,s=this.isMobile?"touchend":"click";return this.isMobile||t.seekbar.off().on(s,function(t){i.seekbar(t)}),t.play.off().on(s,function(){i.play()}),t.stop.off().on(s,function(){i.stop()}),1this.sound.duration&&(t=this.sound.duration),this.sound.setPosition(t),i.lyricList&&i.lyricList.removeClass("current")},play:function(){this.sound[this.sound.playState<1?"play":"resume"]()},stop:function(){this.sound.pause()},prevSound:function(){1==this.attr.random?this.index=this.random():--this.index<0&&(this.index=this.data.length-1),this.sound&&this.sound.pause(),this.reset().setList(),this.data[this.index]&&this.data[this.index].url?this.createSound(this.index):this.getSongInfo(this.index,!0)},nextSound:function(){var t=this.data.length-1;1==this.attr.random?this.index=this.random():++this.index>t&&(this.index=0),this.sound&&this.sound.pause(),this.reset().setList(),this.data[this.index]&&this.data[this.index].url?this.createSound(this.index):this.getSongInfo(this.index,!0)},setPlay:function(){var t=this.DOM;return t.playing.stop(!0,!0)[this.IE6||this.isMobile?"show":"fadeIn"](),t.play.hide(),t.stop.show(),this},setStop:function(){var t=this.DOM;return t.playing.stop(!0,!0)[this.IE6||this.isMobile?"hide":"fadeOut"](),t.play.show(),t.stop.hide(),this},random:function(){return this.data&&1!==this.data.length&&Math.floor(Math.random()*this.data.length)||0},reset:function(){var t=this.DOM;return this.setStop(),t.seekbar.width(0),t.playbar.width(0),this},setList:function(){var t=this.DOM,i=this.index,s=t.list.find("li").eq(0).outerHeight(),e=Math.floor(t.list.height()/s),a=Math.floor(e/2),n=a,r=this.data.length-a;return this.data.length>e&&(i<=n&&t.list.scrollTop(0),n{author}{serial}{title}',f.fn.WPPlayer=function(i){return this.each(function(){var t=f(this);"string"==typeof i?t.data("WPPlayer")&&t.data("WPPlayer")[i]():t.data("WPPlayer",new r(this,i))})}}(jQuery,soundManager),jQuery('[data-wp-player="wp-player"]').WPPlayer(wp_player_params); -------------------------------------------------------------------------------- /dist/wp-player/include/Meting.php: -------------------------------------------------------------------------------- 1 | 8 | * Released under the MIT license 9 | */ 10 | //namespace Metowolf; 11 | class Meting 12 | { 13 | protected $_SITE; 14 | protected $_TEMP; 15 | protected $_RETRY = 3; 16 | protected $_FORMAT = false; 17 | 18 | public function __construct($v = 'netease') 19 | { 20 | $this->site($v); 21 | } 22 | 23 | public function site($v) 24 | { 25 | $this->_SITE=$v; 26 | return $this; 27 | } 28 | 29 | public function format($v = true) 30 | { 31 | $this->_FORMAT=$v; 32 | return $this; 33 | } 34 | 35 | private function curl($API) 36 | { 37 | if (isset($API['encode'])) { 38 | $API=call_user_func_array(array($this,$API['encode']), array($API)); 39 | } 40 | $BASE=$this->curlset(); 41 | $curl=curl_init(); 42 | if ($API['method']=='POST') { 43 | if (is_array($API['body'])) { 44 | $API['body']=http_build_query($API['body']); 45 | } 46 | curl_setopt($curl, CURLOPT_POST, 1); 47 | curl_setopt($curl, CURLOPT_POSTFIELDS, $API['body']); 48 | } elseif ($API['method']=='GET') { 49 | if (isset($API['body'])) { 50 | $API['url']=$API['url'].'?'.http_build_query($API['body']); 51 | } 52 | } 53 | curl_setopt($curl, CURLOPT_HEADER, 0); 54 | curl_setopt($curl, CURLOPT_TIMEOUT, 20); 55 | curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); 56 | curl_setopt($curl, CURLOPT_IPRESOLVE, 1); 57 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 58 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); 59 | curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); 60 | curl_setopt($curl, CURLOPT_URL, $API['url']); 61 | curl_setopt($curl, CURLOPT_COOKIE, $BASE['cookie']); 62 | curl_setopt($curl, CURLOPT_REFERER, $BASE['referer']); 63 | curl_setopt($curl, CURLOPT_USERAGENT, $BASE['useragent']); 64 | for ($i=0;$i<=$this->_RETRY;$i++) { 65 | $data=curl_exec($curl); 66 | $info=curl_getinfo($curl); 67 | $error=curl_errno($curl); 68 | $status=$error?curl_error($curl):''; 69 | if (!$error) { 70 | break; 71 | } 72 | } 73 | curl_close($curl); 74 | if ($error) { 75 | return json_encode( 76 | array( 77 | 'error' => $error, 78 | 'info' => $info, 79 | 'status' => $status, 80 | ) 81 | ); 82 | } 83 | if ($this->_FORMAT&&isset($API['decode'])) { 84 | $data=call_user_func_array(array($this,$API['decode']), array($data)); 85 | } 86 | if ($this->_FORMAT&&isset($API['format'])) { 87 | $data=json_decode($data, 1); 88 | $data=$this->clean($data, $API['format']); 89 | $data=json_encode($data); 90 | } 91 | return $data; 92 | } 93 | 94 | private function pickup($array, $rule) 95 | { 96 | $t=explode('#', $rule); 97 | foreach ($t as $vo) { 98 | if (is_null($array)) { 99 | return null; 100 | } 101 | $array=$array[$vo]; 102 | } 103 | return $array; 104 | } 105 | 106 | private function clean($raw, $rule) 107 | { 108 | if (!empty($rule)) { 109 | $raw=$this->pickup($raw, $rule); 110 | } 111 | if (is_null($raw)) { 112 | $raw=array(); 113 | } elseif (!isset($raw[0])) { 114 | $raw=array($raw); 115 | } 116 | $result=array_map(array($this,'format_'.$this->_SITE), $raw); 117 | return $result; 118 | } 119 | 120 | public function search($keyword, $page=1, $limit=30) 121 | { 122 | switch ($this->_SITE) { 123 | case 'netease': 124 | $API=array( 125 | 'method' => 'POST', 126 | 'url' => 'http://music.163.com/api/linux/forward', 127 | 'body' => array( 128 | 'method' => 'POST', 129 | 'params' => array( 130 | 's' => $keyword, 131 | 'type' => 1, 132 | 'limit' => $limit, 133 | 'total' => 'true', 134 | 'offset' => $page-1, 135 | ), 136 | 'url' => 'http://music.163.com/api/cloudsearch/pc', 137 | ), 138 | 'encode' => 'netease_AESECB', 139 | 'format' => 'result#songs', 140 | ); 141 | break; 142 | case 'tencent': 143 | $API=array( 144 | 'method' => 'GET', 145 | 'url' => 'https://c.y.qq.com/soso/fcgi-bin/search_cp', 146 | 'body' => array( 147 | 'p' => $page, 148 | 'n' => $limit, 149 | 'w' => $keyword, 150 | 'aggr' => 1, 151 | 'lossless' => 1, 152 | 'cr' => 1, 153 | ), 154 | 'decode' => 'jsonp2json', 155 | 'format' => 'data#song#list', 156 | ); 157 | break; 158 | case 'xiami': 159 | $API=array( 160 | 'method' => 'GET', 161 | 'url' => 'http://api.xiami.com/web', 162 | 'body' => array( 163 | 'v' => '2.0', 164 | 'app_key' => '1', 165 | 'key' => $keyword, 166 | 'page' => $page, 167 | 'limit' => $limit, 168 | 'r' => 'search/songs', 169 | ), 170 | 'format' => 'data#songs', 171 | ); 172 | break; 173 | case 'kugou': 174 | $API=array( 175 | 'method' => 'GET', 176 | 'url' => 'http://ioscdn.kugou.com/api/v3/search/song', 177 | 'body' => array( 178 | 'iscorrect' => 1, 179 | 'pagesize' => $limit, 180 | 'plat' => 2, 181 | 'tag' => 1, 182 | 'sver' => 5, 183 | 'showtype' => 10, 184 | 'page' => $page, 185 | 'keyword' => $keyword, 186 | 'version' => 8550 187 | ), 188 | 'format' => 'data#info', 189 | ); 190 | break; 191 | case 'baidu': 192 | $API=array( 193 | 'method' => 'GET', 194 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 195 | 'body' => array( 196 | 'method' => 'baidu.ting.search.merge', 197 | 'isNew' => 1, 198 | 'query' => $keyword, 199 | 'page_size' => $limit, 200 | 'page_no' => $page, 201 | 'type' => 0, 202 | 'format' => 'json', 203 | 'from' => 'ios', 204 | 'channel' => '(null)', 205 | 'cuid' => 'appstore', 206 | 'from' => 'ios', 207 | 'version' => '5.9.5', 208 | ), 209 | 'format' => 'result#song_info#song_list', 210 | ); 211 | break; 212 | } 213 | return $this->curl($API); 214 | } 215 | 216 | public function song($id) 217 | { 218 | switch ($this->_SITE) { 219 | case 'netease': 220 | $API=array( 221 | 'method' => 'POST', 222 | 'url' => 'http://music.163.com/api/linux/forward', 223 | 'body' => array( 224 | 'method' => 'POST', 225 | 'params' => array( 226 | 'c' => '[{"id":'.$id.'}]', 227 | ), 228 | 'url' => 'http://music.163.com/api/v3/song/detail', 229 | ), 230 | 'encode' => 'netease_AESECB', 231 | 'format' => 'songs', 232 | ); 233 | break; 234 | case 'tencent': 235 | $API=array( 236 | 'method' => 'GET', 237 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg', 238 | 'body' => array( 239 | 'songmid' => $id, 240 | 'format' => 'json', 241 | ), 242 | 'decode' => 'tencent_singlesong', 243 | 'format' => 'data', 244 | ); 245 | break; 246 | case 'xiami': 247 | $API=array( 248 | 'method' => 'GET', 249 | 'url' => 'http://api.xiami.com/web', 250 | 'body' => array( 251 | 'v' => '2.0', 252 | 'app_key' => '1', 253 | 'id' => $id, 254 | 'r' => 'song/detail', 255 | ), 256 | 'format' => 'data#song', 257 | ); 258 | break; 259 | case 'kugou': 260 | $API=array( 261 | 'method' => 'POST', 262 | 'url' => 'http://m.kugou.com/app/i/getSongInfo.php?', 263 | 'body' => array( 264 | "cmd" => "playInfo", 265 | "hash" => $id, 266 | "from" => "mkugou", 267 | ), 268 | 'format' => '', 269 | ); 270 | break; 271 | case 'baidu': 272 | $API=array( 273 | 'method' => 'GET', 274 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 275 | 'body' => array( 276 | 'method' => 'baidu.ting.song.play', 277 | 'songid' => $id, 278 | 'format' => 'json', 279 | 'from' => 'ios', 280 | 'channel' => '(null)', 281 | 'cuid' => 'appstore', 282 | 'from' => 'ios', 283 | 'version' => '5.9.5', 284 | ), 285 | 'format' => 'songinfo', 286 | ); 287 | break; 288 | } 289 | return $this->curl($API); 290 | } 291 | 292 | public function album($id) 293 | { 294 | switch ($this->_SITE) { 295 | case 'netease': 296 | $API=array( 297 | 'method' => 'POST', 298 | 'url' => 'http://music.163.com/api/linux/forward', 299 | 'body' => array( 300 | 'method' => 'GET', 301 | 'params' => array( 302 | 'id' => $id, 303 | ), 304 | 'url' => 'http://music.163.com/api/v1/album/'.$id, 305 | ), 306 | 'encode' => 'netease_AESECB', 307 | 'format' => 'songs', 308 | ); 309 | break; 310 | case 'tencent': 311 | $API=array( 312 | 'method' => 'GET', 313 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_album_info_cp.fcg', 314 | 'body' => array( 315 | 'albummid' => $id, 316 | ), 317 | 'format' => 'data#list', 318 | ); 319 | break; 320 | case 'xiami': 321 | $API=array( 322 | 'method' => 'GET', 323 | 'url' => 'http://api.xiami.com/web', 324 | 'body' => array( 325 | 'v' => '2.0', 326 | 'app_key' => '1', 327 | 'id' => $id, 328 | 'r' => 'album/detail', 329 | ), 330 | 'format' => 'data#songs', 331 | ); 332 | break; 333 | case 'kugou': 334 | $API=array( 335 | 'method' => 'GET', 336 | 'url' => 'http://mobilecdn.kugou.com/api/v3/album/song', 337 | 'body' => array( 338 | 'albumid' => $id, 339 | 'plat' => 2, 340 | 'page' => 1, 341 | 'pagesize' => -1, 342 | 'version' => 8550, 343 | ), 344 | 'format' => 'data#info', 345 | ); 346 | break; 347 | case 'baidu': 348 | $API=array( 349 | 'method' => 'GET', 350 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 351 | 'body' => array( 352 | 'method' => 'baidu.ting.album.getAlbumInfo', 353 | 'album_id' => $id, 354 | 'format' => 'json', 355 | 'from' => 'ios', 356 | 'channel' => '(null)', 357 | 'cuid' => 'appstore', 358 | 'from' => 'ios', 359 | 'version' => '5.9.5', 360 | ), 361 | 'format' => 'songlist', 362 | ); 363 | break; 364 | } 365 | return $this->curl($API); 366 | } 367 | 368 | public function artist($id, $limit=50) 369 | { 370 | switch ($this->_SITE) { 371 | case 'netease': 372 | $API=array( 373 | 'method' => 'POST', 374 | 'url' => 'http://music.163.com/api/linux/forward', 375 | 'body' => array( 376 | 'method' => 'GET', 377 | 'params' => array( 378 | 'top' => $limit, 379 | "id" => $id, 380 | "ext" => "true", 381 | ), 382 | 'url' => 'http://music.163.com/api/v1/artist/'.$id, 383 | ), 384 | 'encode' => 'netease_AESECB', 385 | 'format' => 'hotSongs', 386 | ); 387 | break; 388 | case 'tencent': 389 | $API=array( 390 | 'method' => 'GET', 391 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg', 392 | 'body' => array( 393 | 'singermid' => $id, 394 | 'begin' => 0, 395 | 'num' => $limit, 396 | ), 397 | 'format' => 'data#list', 398 | ); 399 | break; 400 | case 'xiami': 401 | $API=array( 402 | 'method' => 'GET', 403 | 'url' => 'http://api.xiami.com/web', 404 | 'body' => array( 405 | 'v' => '2.0', 406 | 'app_key' => '1', 407 | 'id' => $id, 408 | 'limit' => $limit, 409 | 'page' => 1, 410 | 'r' => 'artist/hot-songs', 411 | ), 412 | 'format' => 'data', 413 | ); 414 | break; 415 | case 'kugou': 416 | $API=array( 417 | 'method' => 'GET', 418 | 'url' => 'http://mobilecdn.kugou.com/api/v3/singer/song', 419 | 'body' => array( 420 | 'singerid' => $id, 421 | 'page' => 1, 422 | 'plat' => 0, 423 | 'pagesize' => $limit, 424 | 'version' => 8400, 425 | ), 426 | 'format' => 'data#info', 427 | ); 428 | break; 429 | case 'baidu': 430 | $API=array( 431 | 'method' => 'GET', 432 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 433 | 'body' => array( 434 | 'method' => 'baidu.ting.artist.getSongList', 435 | 'tinguid' => $id, 436 | 'limits' => $limit, 437 | 'format' => 'json', 438 | 'from' => 'ios', 439 | 'channel' => '(null)', 440 | 'cuid' => 'appstore', 441 | 'from' => 'ios', 442 | 'version' => '5.9.5', 443 | ), 444 | 'format' => 'songlist', 445 | ); 446 | break; 447 | } 448 | return $this->curl($API); 449 | } 450 | 451 | public function playlist($id) 452 | { 453 | switch ($this->_SITE) { 454 | case 'netease': 455 | $API=array( 456 | 'method' => 'POST', 457 | 'url' => 'http://music.163.com/api/linux/forward', 458 | 'body' => array( 459 | 'method' => 'POST', 460 | 'params' => array( 461 | 'id' => $id, 462 | "n" => 1000, 463 | ), 464 | 'url' => 'http://music.163.com/api/v3/playlist/detail', 465 | ), 466 | 'encode' => 'netease_AESECB', 467 | 'format' => 'playlist#tracks', 468 | ); 469 | break; 470 | case 'tencent': 471 | $API=array( 472 | 'method' => 'GET', 473 | 'url' => 'https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg', 474 | 'body' => array( 475 | 'disstid' => $id, 476 | 'utf8' => 1, 477 | 'type' => 1, 478 | ), 479 | 'decode' => 'jsonp2json', 480 | 'format' => 'cdlist#0#songlist', 481 | ); 482 | break; 483 | case 'xiami': 484 | $API=array( 485 | 'method' => 'GET', 486 | 'url' => 'http://api.xiami.com/web', 487 | 'body' => array( 488 | 'v' => '2.0', 489 | 'app_key' => '1', 490 | 'id' => $id, 491 | 'r' => 'collect/detail', 492 | ), 493 | 'format' => 'data#songs', 494 | ); 495 | break; 496 | case 'kugou': 497 | $API=array( 498 | 'method' => 'GET', 499 | 'url' => 'http://mobilecdn.kugou.com/api/v3/special/song', 500 | 'body' => array( 501 | 'specialid' => $id, 502 | 'page' => 1, 503 | 'plat' => 2, 504 | 'pagesize' => -1, 505 | 'version' => 8400, 506 | ), 507 | 'format' => 'data#info', 508 | ); 509 | break; 510 | case 'baidu': 511 | $API=array( 512 | 'method' => 'GET', 513 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 514 | 'body' => array( 515 | 'method' => 'baidu.ting.diy.gedanInfo', 516 | 'listid' => $id, 517 | 'format' => 'json', 518 | 'from' => 'ios', 519 | 'channel' => '(null)', 520 | 'cuid' => 'appstore', 521 | 'from' => 'ios', 522 | 'version' => '5.9.5', 523 | ), 524 | 'format' => 'content', 525 | ); 526 | break; 527 | } 528 | return $this->curl($API); 529 | } 530 | 531 | public function url($id, $br=320) 532 | { 533 | switch ($this->_SITE) { 534 | case 'netease': 535 | $API=array( 536 | 'method' => 'POST', 537 | 'url' => 'http://music.163.com/api/linux/forward', 538 | 'body' => array( 539 | 'method' => 'POST', 540 | 'params' => array( 541 | 'ids' => array($id), 542 | 'br' => $br*1000, 543 | ), 544 | 'url' => 'http://music.163.com/api/song/enhance/player/url', 545 | ), 546 | 'encode' => 'netease_AESECB', 547 | 'decode' => 'netease_url', 548 | ); 549 | break; 550 | case 'tencent': 551 | $API=array( 552 | 'method' => 'GET', 553 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg', 554 | 'body' => array( 555 | 'songmid' => $id, 556 | 'format' => 'json', 557 | ), 558 | 'decode' => 'tencent_url', 559 | ); 560 | break; 561 | case 'xiami': 562 | $API=array( 563 | 'method' => 'GET', 564 | 'url' => 'http://www.xiami.com/song/gethqsong/sid/'.$id, 565 | 'body' => array( 566 | 'v' => '2.0', 567 | 'app_key' => '1', 568 | 'id' => $id, 569 | 'r' => 'song/detail', 570 | ), 571 | 'decode' => 'xiami_url', 572 | ); 573 | break; 574 | case 'kugou': 575 | $API=array( 576 | 'method' => 'POST', 577 | 'url' => 'http://media.store.kugou.com/v1/get_res_privilege', 578 | 'body' => json_encode(array( 579 | "relate" => 1, 580 | "userid" => 0, 581 | "vip" => 0, 582 | "appid" => 1005, 583 | "token" => "", 584 | "behavior" => "download", 585 | "clientver" => "8493", 586 | "resource" => array(array( 587 | "id" => 0, 588 | "type" => "audio", 589 | "hash" => $id, 590 | ))) 591 | ), 592 | 'decode' => 'kugou_url', 593 | ); 594 | break; 595 | case 'baidu': 596 | $API=array( 597 | 'method' => 'GET', 598 | 'url' => 'http://music.baidu.com/data/music/fmlink', 599 | 'body' => array( 600 | 'songIds' => $id, 601 | 'rate' => $br, 602 | 'type' => 'mp3', 603 | ), 604 | 'decode' => 'baidu_url', 605 | ); 606 | break; 607 | } 608 | $this->_temp['br']=$br; 609 | return $this->curl($API); 610 | } 611 | 612 | public function lyric($id) 613 | { 614 | switch ($this->_SITE) { 615 | case 'netease': 616 | $API=array( 617 | 'method' => 'POST', 618 | 'url' => 'http://music.163.com/api/linux/forward', 619 | 'body' => array( 620 | 'method' => 'POST', 621 | 'params' => array( 622 | 'id' => $id, 623 | 'os' => 'linux', 624 | 'lv' => -1, 625 | 'kv' => -1, 626 | 'tv' => -1, 627 | ), 628 | 'url' => 'http://music.163.com/api/song/lyric', 629 | ), 630 | 'encode' => 'netease_AESECB', 631 | 'decode' => 'netease_lyric', 632 | ); 633 | break; 634 | case 'tencent': 635 | $API=array( 636 | 'method' => 'GET', 637 | 'url' => 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg', 638 | 'body' => array( 639 | 'songmid' => $id, 640 | 'g_tk' => 5381, 641 | ), 642 | 'decode' => 'tencent_lyric', 643 | ); 644 | break; 645 | case 'xiami': 646 | $API=array( 647 | 'method' => 'GET', 648 | 'url' => 'http://api.xiami.com/web', 649 | 'body' => array( 650 | 'v' => '2.0', 651 | 'app_key' => '1', 652 | 'id' => $id, 653 | 'r' => 'song/detail', 654 | ), 655 | 'decode' => 'xiami_lyric', 656 | ); 657 | break; 658 | case 'kugou': 659 | $API=array( 660 | 'method' => 'GET', 661 | 'url' => 'http://m.kugou.com/app/i/krc.php', 662 | 'body' => array( 663 | 'keyword' => '%20-%20', 664 | 'timelength' => 1000000, 665 | 'cmd' => 100, 666 | 'hash' => $id, 667 | ), 668 | 'decode' => 'kugou_lyric' 669 | ); 670 | break; 671 | case 'baidu': 672 | $API=array( 673 | 'method' => 'GET', 674 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 675 | 'body' => array( 676 | 'method' => 'baidu.ting.song.lry', 677 | 'songid' => $id, 678 | 'format' => 'json', 679 | 'from' => 'ios', 680 | 'channel' => '(null)', 681 | 'cuid' => 'appstore', 682 | 'from' => 'ios', 683 | 'version' => '5.9.5', 684 | ), 685 | 'decode' => 'baidu_lyric' 686 | ); 687 | break; 688 | } 689 | return $this->curl($API); 690 | } 691 | 692 | public function pic($id, $size=300) 693 | { 694 | switch ($this->_SITE) { 695 | case 'netease': 696 | $url='https://p3.music.126.net/'.$this->netease_pickey($id).'/'.$id.'.jpg?param='.$size.'z'.$size.'&quality=100'; 697 | break; 698 | case 'tencent': 699 | $url='https://y.gtimg.cn/music/photo_new/T002R'.$size.'x'.$size.'M000'.$id.'.jpg?max_age=2592000'; 700 | break; 701 | case 'xiami': 702 | $format=$this->_FORMAT; 703 | $data=$this->format(false)->song($id); 704 | $this->format($format); 705 | $data=json_decode($data, 1); 706 | $url=$data['data']['song']['logo']; 707 | $url=str_replace(array('_1.','http:','img.'), array('.','https:','pic.'), $url).'@'.$size.'h_'.$size.'w_100q_1c.jpg'; 708 | break; 709 | case 'kugou': 710 | $format=$this->_FORMAT; 711 | $data=$this->format(false)->song($id); 712 | $this->format($format); 713 | $data=json_decode($data, 1); 714 | $url=$data['imgUrl']; 715 | $url=str_replace('{size}', '400', $url); 716 | break; 717 | case 'baidu': 718 | $format=$this->_FORMAT; 719 | $data=$this->format(false)->song($id); 720 | $this->format($format); 721 | $data=json_decode($data, 1); 722 | $url=$data['songinfo']['pic_big'] ? $data['songinfo']['pic_big'] : $data['songinfo']['pic_small']; 723 | break; 724 | } 725 | return json_encode(array('url'=>$url)); 726 | } 727 | 728 | private function curlset() 729 | { 730 | $BASE=array( 731 | 'netease'=>array( 732 | 'referer' => 'https://music.163.com/', 733 | 'cookie' => 'os=linux; appver=1.0.0.1026; osver=Ubuntu%2016.10; MUSIC_U=78d411095f4b022667bc8ec49e9a44cca088df057d987f5feaf066d37458e41c4a7d9447977352cf27ea9fee03f6ec4441049cea1c6bb9b6; __remember_me=true', 734 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 735 | ), 736 | 'tencent'=>array( 737 | 'referer' => 'http://y.qq.com/portal/player.html', 738 | 'cookie' => 'qqmusic_uin=12345678; qqmusic_key=12345678; qqmusic_fromtag=30; ts_last=y.qq.com/portal/player.html;', 739 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 740 | ), 741 | 'xiami'=>array( 742 | 'referer' => 'http://h.xiami.com/', 743 | 'cookie' => 'user_from=2;XMPLAYER_addSongsToggler=0;XMPLAYER_isOpen=0;_xiamitoken=123456789;', 744 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 745 | ), 746 | 'kugou'=>array( 747 | 'referer' => 'http://www.kugou.com/webkugouplayer/flash/webKugou.swf', 748 | 'cookie' => '_WCMID=123456789', 749 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 750 | ), 751 | 'baidu'=>array( 752 | 'referer' => 'http://ting.baidu.com/', 753 | 'cookie' => 'BAIDUID=123456789', 754 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 755 | ), 756 | ); 757 | return $BASE[$this->_SITE]; 758 | } 759 | 760 | /** 761 | * 乱七八糟的函数,加密解密... 762 | * 正在努力重构这些代码 TAT 763 | */ 764 | private function netease_AESECB($API) 765 | { 766 | $KEY='7246674226682325323F5E6544673A51'; 767 | $body=json_encode($API['body']); 768 | if (function_exists('openssl_encrypt')) { 769 | $body=openssl_encrypt($body, 'aes-128-ecb', pack('H*', $KEY)); 770 | } else { 771 | $PAD=16-(strlen($body)%16); 772 | $body=base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, hex2bin($KEY), $body.str_repeat(chr($PAD), $PAD), MCRYPT_MODE_ECB)); 773 | } 774 | $body=strtoupper(bin2hex(base64_decode($body))); 775 | 776 | $API['body']=array( 777 | 'eparams'=>$body, 778 | ); 779 | return $API; 780 | } 781 | private function jsonp2json($jsonp) 782 | { 783 | if ($jsonp[0] !== '[' && $jsonp[0] !== '{') { 784 | $jsonp = substr($jsonp, strpos($jsonp, '(')); 785 | } 786 | return trim($jsonp, '();'); 787 | } 788 | private function tencent_singlesong($result) 789 | { 790 | $result=json_decode($result, 1); 791 | $data=$result['data'][0]; 792 | $t=array( 793 | 'songmid' => $data['mid'], 794 | 'songname' => $data['name'], 795 | 'albummid' => $data['album']['mid'], 796 | ); 797 | foreach ($t as $key=>$vo) { 798 | $result['data'][0][$key]=$vo; 799 | } 800 | return json_encode($result); 801 | } 802 | private function netease_pickey($id) 803 | { 804 | $magic=str_split('3go8&$8*3*3h0k(2)2'); 805 | $song_id=str_split($id); 806 | for ($i=0;$i str_replace('http://', 'https://', $data['data'][0]['uf']['url']), 823 | 'br' =>$data['data'][0]['uf']['br']/1000, 824 | ); 825 | } 826 | else{ 827 | $url=array( 828 | 'url' => str_replace('http://', 'https://', $data['data'][0]['url']), 829 | 'br' => $data['data'][0]['br']/1000, 830 | ); 831 | } 832 | return json_encode($url); 833 | } 834 | private function tencent_url($result) 835 | { 836 | $data=json_decode($result, 1); 837 | $GUID=mt_rand()%10000000000; 838 | $API=array( 839 | 'method' => 'GET', 840 | 'url' => 'https://c.y.qq.com/base/fcgi-bin/fcg_musicexpress.fcg', 841 | 'body' => array( 842 | 'json' => 3, 843 | 'guid' => $GUID, 844 | ), 845 | 'decode' => 'jsonp2json', 846 | ); 847 | $KEY=json_decode($this->curl($API), 1); 848 | $KEY=$KEY['key']; 849 | 850 | $type=array( 851 | 'size_320mp3' => array(320,'M800','mp3'), 852 | 'size_128mp3' => array(128,'M500','mp3'), 853 | 'size_96aac' => array(96 ,'C400','m4a'), 854 | 'size_48aac' => array(48 ,'C200','m4a'), 855 | ); 856 | foreach ($type as $key=>$vo) { 857 | if ($data['data'][0]['file'][$key]&&$vo[0]<=$this->_temp['br']) { 858 | $url=array( 859 | 'url' => 'http://dl.stream.qqmusic.qq.com/'.$vo[1].$data['data'][0]['file']['media_mid'].'.'.$vo[2].'?vkey='.$KEY.'&guid='.$GUID.'&uid=0&fromtag=30', 860 | 'br' => $vo[0], 861 | ); 862 | break; 863 | } 864 | } 865 | return json_encode($url); 866 | } 867 | private function xiami_url($result) 868 | { 869 | $data=json_decode($result, 1); 870 | if(isset($data['location'])) { 871 | $location = $data['location']; 872 | $num = (int)$location[0]; 873 | $str = substr($location, 1); 874 | $len = floor(strlen($str)/$num); 875 | $sub = strlen($str) % $num; 876 | $qrc = array(); 877 | $tmp = 0; 878 | $urlt = ''; 879 | for(;$tmp<$sub;$tmp++){ 880 | $qrc[$tmp] = substr($str, $tmp*($len+1), $len+1); 881 | } 882 | for(;$tmp<$num;$tmp++){ 883 | $qrc[$tmp] = substr($str, $len*$tmp+$sub, $len); 884 | } 885 | for($tmpa=0;$tmpa<$len+1;$tmpa++){ 886 | for($tmpb=0;$tmpb<$num;$tmpb++){ 887 | if(isset($qrc[$tmpb][$tmpa])) { $urlt.=$qrc[$tmpb][$tmpa]; 888 | } 889 | } 890 | } 891 | for($tmp=0;$tmp<$sub;$tmp++){ 892 | //if(isset($qrc[$tmp][$len])) (string)$urlt.=(string)$qrc[$tmp][$len]; 893 | } 894 | $urlt=str_replace('^', '0', urldecode($urlt)); 895 | $url=array( 896 | 'url' => urldecode($urlt), 897 | 'br' => 320, 898 | ); 899 | } 900 | else{ 901 | $url=array( 902 | 'url' => "error",//str_replace('http:', 'https:', $data['data']['song']['listen_file']), 903 | 'br' => 0, 904 | ); 905 | } 906 | return json_encode($url); 907 | } 908 | private function kugou_url($result) 909 | { 910 | $data=json_decode($result, 1); 911 | 912 | $max=0; 913 | $url=array(); 914 | foreach ($data['data'][0]['relate_goods'] as $vo) { 915 | if ($vo['info']['bitrate']<=$this->_temp['br']&&$vo['info']['bitrate']>$max) { 916 | $API=array( 917 | 'method' => 'GET', 918 | 'url' => 'http://trackercdn.kugou.com/i/v2/', 919 | 'body' => array( 920 | 'hash' => $vo['hash'], 921 | 'key' => md5($vo['hash'].'kgcloudv2'), 922 | 'pid' => 1, 923 | 'behavior' => 'play', 924 | 'cmd' => '23', 925 | 'version' => 8400, 926 | ), 927 | ); 928 | $t=json_decode($this->curl($API), 1); 929 | if (isset($t['url'])) { 930 | $max=$t['bitRate']/1000; 931 | $url=array( 932 | 'url' => $t['url'], 933 | 'br' => $t['bitRate']/1000, 934 | ); 935 | } 936 | } 937 | } 938 | return json_encode($url); 939 | } 940 | private function baidu_url($result) 941 | { 942 | $data=json_decode($result, 1); 943 | $url=array( 944 | 'url' => $data['data']['songList'][0]['songLink'], 945 | 'br' => $data['data']['songList'][0]['rate'], 946 | ); 947 | $url['url']=str_replace('http://yinyueshiting.baidu.com', 'https://gss0.bdstatic.com/y0s1hSulBw92lNKgpU_Z2jR7b2w6buu', $url['url']); 948 | return json_encode($url); 949 | } 950 | /** 951 | * 歌词处理模块 952 | * 用于规范化歌词输出 953 | */ 954 | private function netease_lyric($result) 955 | { 956 | if (!$this->_FORMAT) { 957 | return $result; 958 | } 959 | $result=json_decode($result, 1); 960 | $data=array( 961 | 'lyric' => (@$result['lrc']['lyric'])? @$result['lrc']['lyric'] : '', 962 | 'tlyric' => (@$result['tlyric']['lyric']) ? @$result['tlyric']['lyric'] : '', 963 | ); 964 | return json_encode($data); 965 | } 966 | private function tencent_lyric($result) 967 | { 968 | $result=$this->jsonp2json($result); 969 | if (!$this->_FORMAT) { 970 | return $result; 971 | } 972 | $result=json_decode($result, 1); 973 | $data=array( 974 | 'lyric' => isset($result['lyric'])?base64_decode($result['lyric']):'', 975 | 'tlyric' => isset($result['trans'])?base64_decode($result['trans']):'', 976 | ); 977 | return json_encode($data); 978 | } 979 | private function xiami_lyric($result) 980 | { 981 | if (!$this->_FORMAT) { 982 | return $result; 983 | } 984 | $result=json_decode($result, 1); 985 | $API=array('method'=>'GET','url'=>$result['data']['song']['lyric']); 986 | $data=$this->curl($API); 987 | $data=preg_replace('/<[^>]+>/', '', $data); 988 | $arr=array( 989 | 'lyric' => $data, 990 | ); 991 | return json_encode($arr); 992 | } 993 | private function kugou_lyric($result) 994 | { 995 | if (!$this->_FORMAT) { 996 | return $result; 997 | } 998 | $arr=array( 999 | 'lyric' => $result, 1000 | ); 1001 | return json_encode($arr); 1002 | } 1003 | private function baidu_lyric($result) 1004 | { 1005 | if (!$this->_FORMAT) { 1006 | return $result; 1007 | } 1008 | $result=json_decode($result, 1); 1009 | $data=array( 1010 | 'lyric' => (@$result['lrcContent']) ? @$result['lrcContent'] : '', 1011 | ); 1012 | return json_encode($data); 1013 | } 1014 | /** 1015 | * Format - 规范化函数 1016 | * 用于统一返回的参数,可用 ->format() 一次性开关开启 1017 | */ 1018 | private function format_netease($data) 1019 | { 1020 | $result=array( 1021 | 'id' => $data['id'], 1022 | 'name' => $data['name'], 1023 | 'artist' => array(), 1024 | 'pic_id' => (@$data['al']['pic_str']) ? @$data['al']['pic_str'] : $data['al']['pic'], 1025 | 'url_id' => $data['id'], 1026 | 'lyric_id' => $data['id'], 1027 | 'source' => 'netease', 1028 | ); 1029 | if (isset($data['al']['picUrl'])) { 1030 | preg_match('/\/(\d+)\./', $data['al']['picUrl'], $match); 1031 | $result['pic_id']=$match[1]; 1032 | } 1033 | foreach ($data['ar'] as $vo) { 1034 | $result['artist'][]=$vo['name']; 1035 | } 1036 | return $result; 1037 | } 1038 | private function format_tencent($data) 1039 | { 1040 | if (isset($data['musicData'])) { 1041 | $data=$data['musicData']; 1042 | } 1043 | $result=array( 1044 | 'id' => $data['songmid'], 1045 | 'name' => $data['songname'], 1046 | 'artist' => array(), 1047 | 'pic_id' => $data['albummid'], 1048 | 'url_id' => $data['songmid'], 1049 | 'lyric_id' => $data['songmid'], 1050 | 'source' => 'tencent', 1051 | ); 1052 | foreach ($data['singer'] as $vo) { 1053 | $result['artist'][]=$vo['name']; 1054 | } 1055 | return $result; 1056 | } 1057 | private function format_xiami($data) 1058 | { 1059 | $result=array( 1060 | 'id' => $data['song_id'], 1061 | 'name' => $data['song_name'], 1062 | 'artist' => explode(';', (@$data['singers']) ? @$data['singers'] : $data['artist_name']), 1063 | 'pic_id' => $data['song_id'], 1064 | 'url_id' => $data['song_id'], 1065 | 'lyric_id' => $data['song_id'], 1066 | 'source' => 'xiami', 1067 | ); 1068 | return $result; 1069 | } 1070 | private function format_kugou($data) 1071 | { 1072 | $result=array( 1073 | 'id' => $data['hash'], 1074 | 'name' => (@$data['filename']) ? @$data['filename'] :$data['fileName'], 1075 | 'artist' => array(), 1076 | 'url_id' => $data['hash'], 1077 | 'pic_id' => $data['hash'], 1078 | 'lyric_id' => $data['hash'], 1079 | 'source' => 'kugou', 1080 | ); 1081 | list($result['artist'], $result['name'])=explode(' - ', $result['name'], 2); 1082 | $result['artist']=explode('、', $result['artist']); 1083 | return $result; 1084 | } 1085 | private function format_baidu($data) 1086 | { 1087 | $result=array( 1088 | 'id' => $data['song_id'], 1089 | 'name' => $data['title'], 1090 | 'artist' => explode(',', $data['author']), 1091 | 'pic_id' => $data['song_id'], 1092 | 'url_id' => $data['song_id'], 1093 | 'lyric_id' => $data['song_id'], 1094 | 'source' => 'baidu', 1095 | ); 1096 | return $result; 1097 | } 1098 | } 1099 | -------------------------------------------------------------------------------- /dist/wp-player/include/metaboxes.php: -------------------------------------------------------------------------------- 1 | array( 28 | 'name' => 'wp_player_music_type', 29 | 'type' => 'select', 30 | 'options' => array( 31 | 'netease' => '网易音乐', 32 | 'xiami' => '虾米音乐', 33 | 'tencent' => 'QQ 音乐', 34 | 'baidu' => '百度音乐' 35 | ), 36 | 'output' => false 37 | ), 38 | 'mp3_xiami_type' => array( 39 | 'name' => 'mp3_xiami_type', 40 | 'type' => 'select', 41 | 'options' => array( 42 | 'song' => '歌曲页面', 43 | 'album' => '专辑页面', 44 | 'artist' => '歌手页面', 45 | 'collect' => '歌单页面' 46 | ), 47 | 'output' => false 48 | ), 49 | 'wp_player_lyric_open' => array( 50 | 'name' => 'wp_player_lyric_open', 51 | 'type' => 'select', 52 | 'options' => array( 53 | 'close' => '关闭歌词', 54 | 'open' => '开启歌词' 55 | ), 56 | 'output' => false 57 | ), 58 | 'mp3_xiami' => array( 59 | 'name' => 'mp3_xiami', 60 | 'type' => 'text', 61 | 'description' => '即可填音乐写ID,也可填写音乐网址 http://......', 62 | 'button' => '获取音乐ID', 63 | 'output' => false 64 | ) 65 | ); 66 | } else { 67 | $arr1 = array(); 68 | } 69 | 70 | $arr2 = array( 71 | 'mp3_title' => array( 72 | 'name' => 'mp3_title', 73 | 'type' => 'textarea', 74 | 'title' => '歌曲名', 75 | 'description' => '请填写歌曲名,一行一个歌曲名,用于列表展示显示。', 76 | 'output' => true 77 | ), 78 | 'mp3_author' => array( 79 | 'name' => 'mp3_author', 80 | 'type' => 'textarea', 81 | 'title' => '歌手名', 82 | 'description' => '请填写歌手名,一行一个歌手名,请与上面的歌曲名一一对应', 83 | 'output' => true 84 | ), 85 | 'mp3_address' => array( 86 | 'name' => 'mp3_address', 87 | 'type' => 'upload', 88 | 'title' => '歌曲地址', 89 | "description" => '请填写歌曲地址,可以上传歌曲,也可以用链接地址(请记得带上http://),一行一个歌曲地址,请与上面的歌曲名一一对应。', 90 | 'output' => true 91 | ), 92 | 'mp3_thumb' => array( 93 | 'name' => 'mp3_thumb', 94 | 'type' => 'upload', 95 | 'title' => '歌曲封面', 96 | "description" => '上传封面,可以为空,WP-Player 将使用默认图,上传图片时记得与歌曲名一一对应,如果此歌曲默认封面,则此行留空。', 97 | 'output' => true 98 | ) 99 | ); 100 | $meta_boxes = $val ? $arr1 : $arr2; 101 | 102 | if ( $apply ){ 103 | $meta_boxes = array(); 104 | $meta_boxes = array_merge( $arr1, $arr2 ); 105 | } 106 | 107 | return apply_filters( 'wp_player_meta_boxes', $meta_boxes ); 108 | } 109 | 110 | 111 | /** 112 | * get meta boxes 113 | */ 114 | function get_wp_player_metaBox( $val = true ){ 115 | global $post; 116 | $meta_boxes = wp_player_meta_boxes($val); 117 | foreach ( $meta_boxes as $meta ){ 118 | $value = get_post_meta( $post->ID, $meta['name'], true ); 119 | switch ($meta['type']) { 120 | case 'text': wp_player_get_meta_text_input( $meta, $value ); break; 121 | case 'select': wp_player_get_meta_select( $meta, $value ); break; 122 | case 'textarea': wp_player_get_meta_textarea( $meta, $value ); break; 123 | case 'upload': wp_player_get_meta_upload( $meta, $value ); break; 124 | case 'button': wp_player_get_meta_button( $meta, $value ); break; 125 | } 126 | } 127 | } 128 | 129 | /** 130 | * Displays meta boxes on the Write Post panel. Loops 131 | * through each meta box in the $meta_boxes variable. 132 | * Gets array from solostream_post_meta_boxes(). 133 | */ 134 | 135 | function wpPlayer_post_meta_boxes() { 136 | global $post; ?> 137 |
    138 | 142 |
    143 |
    144 |
    您的站点当前不支持此功能
    '; 149 | } 150 | ?>
    151 |
    152 |
    153 |
    154 | 155 |

    '.$title.'

    ' : "\n"; 168 | $html .= ''; 169 | $html .= ''; 170 | if ( $button ){ 171 | $html .= "\n".''; 172 | $html .= "\n".'使用说明'; 173 | } 174 | $html .= $output ? '

    '."\n" : "\n"; 175 | 176 | echo $html; 177 | } 178 | 179 | /** 180 | * Outputs a select box with arguments from the 181 | * parameters. Used for both the post/page meta boxes. 182 | */ 183 | function wp_player_get_meta_select( $args = array(), $value = false ) { 184 | 185 | extract( $args ); 186 | 187 | $html .= $output ? '

    '.$title.'

    ' : "\n"; 188 | $html .= ''; 194 | $html .= $output ? '

    '."\n" : "\n"; 195 | 196 | echo $html; 197 | } 198 | 199 | /** 200 | * Outputs a textarea box with arguments from the 201 | * parameters. Used for both the post/page meta boxes. 202 | */ 203 | function wp_player_get_meta_textarea( $args = array(), $value = false ) { 204 | 205 | extract( $args ); 206 | 207 | $html .= '

    '.$title.'

    '; 208 | $html .= ''."\n"; 209 | $html .= '

    '.$description.'

    '; 210 | $html .= ''; 211 | $html .= '
    '; 212 | 213 | echo $html; 214 | } 215 | 216 | /** 217 | * Outputs a Upload box with arguments from the 218 | * parameters. Used for both the post/page meta boxes. 219 | */ 220 | function wp_player_get_meta_upload( $args = array(), $value = false ) { 221 | 222 | extract( $args ); 223 | 224 | $html .= '

    '.$title.'

    '; 225 | $html .= ''."\n"; 226 | $html .= ''; 227 | $html .= '

    '.$description.'

    '; 228 | $html .= ''; 229 | $html .= '
    '."\n"; 230 | 231 | echo $html; 232 | } 233 | 234 | /** 235 | * Loops through each meta box's set of variables. 236 | * Saves them to the database as custom fields. 237 | */ 238 | 239 | function wp_player_save_meta_data( $post_id ) { 240 | global $post; 241 | 242 | $meta_boxes = wp_player_meta_boxes( true, true ); 243 | 244 | foreach ( $meta_boxes as $meta_box ){ 245 | 246 | if ( 'page' == $_POST['post_type'] && !current_user_can( 'edit_page', $post_id ) ){ 247 | return $post_id; 248 | } 249 | 250 | if ( 'post' == $_POST['post_type'] && !current_user_can( 'edit_post', $post_id ) ){ 251 | return $post_id; 252 | } 253 | 254 | if ( !wp_verify_nonce( $_POST[$meta_box['name'] . '_noncename'], plugin_basename( __FILE__ ) ) ){ 255 | return $post_id; 256 | } 257 | 258 | $data = stripslashes( $_POST[$meta_box['name']] ); 259 | 260 | if ( get_post_meta( $post_id, $meta_box['name'] ) == '' ){ 261 | add_post_meta( $post_id, $meta_box['name'], $data, true ); 262 | } elseif ( $data != get_post_meta( $post_id, $meta_box['name'], true ) ){ 263 | update_post_meta( $post_id, $meta_box['name'], $data ); 264 | }elseif ( $data == '' ){ 265 | delete_post_meta( $post_id, $meta_box['name'], get_post_meta( $post_id, $meta_box['name'], true ) ); 266 | } 267 | 268 | } 269 | 270 | } 271 | ?> -------------------------------------------------------------------------------- /dist/wp-player/include/player.php: -------------------------------------------------------------------------------- 1 | options = get_option( 'wp_player_options' ); 32 | $this->base_dir = WP_PLUGIN_URL.'/'. dirname( plugin_basename( dirname( __FILE__ ) ) ).'/'; 33 | $this->admin_dir = site_url( '/wp-admin/options-general.php?page=player.php' ); 34 | 35 | $this->netease = new Meting('netease'); 36 | $this->xiami = new Meting('xiami'); 37 | $this->tencent = new Meting('tencent'); 38 | $this->baidu = new Meting('baidu'); 39 | 40 | $this->netease->format(true); 41 | $this->xiami->format(true); 42 | $this->tencent->format(true); 43 | $this->baidu->format(true); 44 | } 45 | 46 | /** 47 | * @desc get actions 48 | * @param string $source 49 | * @return Meting 50 | */ 51 | private function get_api($source = 'netease') { 52 | switch ( $source ) { 53 | case 'netease': $API = $this->netease; break; 54 | case 'xiami': $API = $this->xiami; break; 55 | case 'tencent': $API = $this->tencent; break; 56 | case 'baidu': $API = $this->baidu; break; 57 | default: $this->netease; 58 | } 59 | return $API; 60 | } 61 | 62 | /** @desc Get Netease Song 63 | * 64 | * @Author: METO 65 | * @GitHub: https://github.com/metowolf 66 | * 67 | * @name: Meting 68 | * @URL: https://github.com/metowolf/Meting 69 | **/ 70 | public function wp_player_actions() { 71 | $id = $_POST['id']; 72 | $type = $_POST['type']; 73 | $nonce = $_SERVER['HTTP_NONCE']; 74 | $source = $_POST['source']; 75 | 76 | if ( !wp_verify_nonce($nonce, "wp-player") || !function_exists('curl_init')) { 77 | $JSON = array('status' => false, 'message' => '非法请求', data => array()); 78 | } else { 79 | $API = $this->get_api($source); 80 | switch ( $type ) { 81 | case 'song': $data = $API->song($id); break; 82 | case 'album': $data = $API->album($id); break; 83 | case 'artist': $data = $API->artist($id); break; 84 | case 'collect': $data = $API->playlist($id); break; 85 | default: $data = $API->song($id); 86 | } 87 | $JSON = array( 88 | 'status' => ($data && count($data) > 0) ? true : false, 89 | 'message' => ($data && count($data) > 0) ? '获取成功' : '获取失败', 90 | 'data' => array( 91 | 'list' => ($data && count($data) > 0) ? json_decode($data) : array() 92 | ) 93 | ); 94 | } 95 | 96 | header('Content-type: application/json'); 97 | echo json_encode($JSON); 98 | die(); 99 | } 100 | 101 | /** 102 | * @name Get Song Info 103 | */ 104 | public function wp_player_get_info() { 105 | $id = $_POST['id']; 106 | $pic_id = $_POST['pic_id']; 107 | $url_id = $_POST['url_id']; 108 | $lyric_id = $_POST['lyric_id']; 109 | $nonce = $_SERVER['HTTP_NONCE']; 110 | $source = $_POST['source']; 111 | 112 | if ( !wp_verify_nonce($nonce, "wp-player") || !function_exists('curl_init')) { 113 | $JSON = array('status' => false, 'message' => '非法请求', data => array()); 114 | } else { 115 | $API = $this->get_api($source); 116 | $JSON = array( 117 | 'status' => true, 118 | 'message' => '获取成功', 119 | 'data' => array( 120 | 'id' => $id, 121 | 'pic' => json_decode($API->pic($pic_id, 180)), 122 | 'url' => json_decode($API->url($url_id, 120)), 123 | 'lyric' => json_decode($API->lyric($lyric_id)) 124 | ) 125 | ); 126 | } 127 | 128 | header('Content-type: application/json'); 129 | echo json_encode($JSON); 130 | die(); 131 | } 132 | 133 | /** 134 | * @desc Register Menu 135 | */ 136 | public function options_menu(){ 137 | add_options_page( 'WP-Player 设置', 'WP-Player 设置', 'manage_options', basename( __FILE__ ), array( $this, 'printAdminPage' ) ); 138 | add_action( 'admin_init', array( $this, 'wp_player_settings' )); 139 | } 140 | 141 | /** 142 | * @desc Register WP-Player Setting 143 | */ 144 | public function wp_player_settings() { 145 | register_setting( 'wp_player_settings_group', 'wp_player_options' ); 146 | } 147 | 148 | /** 149 | * @desc Register setting submit 150 | */ 151 | public function wp_player_add_link( $action_links, $plugin_file, $plugin_data, $context ){ 152 | if (strip_tags($plugin_data['Title']) == 'WP-Player') { 153 | $wp_player_links = '设定'; 154 | array_unshift( $action_links, $wp_player_links ); 155 | } 156 | return $action_links; 157 | } 158 | 159 | /** 160 | * @desc Include scripts 161 | */ 162 | public function wp_player_scripts(){ 163 | global $WP_PLAYER_VERSION; 164 | $options = $this->options; 165 | wp_enqueue_style( 'wp-player', $this->base_dir . 'assets/css/wp-player.css', array(), $WP_PLAYER_VERSION, 'screen' ); 166 | if( is_array( $options ) && $options['jQuery'] == 'true' ){ 167 | wp_enqueue_script( 'jquery' ); 168 | } 169 | wp_enqueue_script( 'wp-player-jplayer', $this->base_dir . 'assets/js/libs/soundmanager/soundmanager2.js', array(), $WP_PLAYER_VERSION, true ); 170 | wp_enqueue_script( 'wp-player', $this->base_dir . 'assets/js/wp-player.js', array(), $WP_PLAYER_VERSION, true ); 171 | 172 | wp_localize_script( 'wp-player', 'wp_player_params', 173 | array( 174 | 'swf' => $this->base_dir.'assets/js/libs/soundmanager/', 175 | 'img' => $this->base_dir.'assets/images/default.png', 176 | 'url' => admin_url().'admin-ajax.php', 177 | 'nonce' => wp_create_nonce('wp-player'), 178 | 'single' => ( is_single() || is_page() ) ? 'true' : 'false' 179 | )); 180 | } 181 | 182 | /** 183 | * @desc add Admin WP-Player CSS 184 | */ 185 | public function wp_player_admin_css(){ 186 | global $WP_PLAYER_VERSION; 187 | wp_enqueue_style( 'wp-player-plugin', plugins_url( 'assets/css/wp-player-plugin.css', dirname( __FILE__ ) ), array(), $WP_PLAYER_VERSION ); 188 | } 189 | 190 | /** 191 | * @desc add Admin Upload script 192 | */ 193 | public function wp_player_admin_head(){ 194 | global $WP_PLAYER_VERSION; 195 | wp_enqueue_script( 'jquery' ); 196 | wp_enqueue_script('media-upload'); 197 | wp_enqueue_script('thickbox'); 198 | wp_enqueue_script( 'wp-plugin-uploader', plugins_url( 'assets/js/plugin-uploader.js', dirname( __FILE__ ) ), array('jquery','media-upload','thickbox'), $WP_PLAYER_VERSION ); 199 | } 200 | 201 | /** 202 | * @desc string replace 203 | */ 204 | private function each($str, $isThumb = false) { 205 | $arr = explode("\r", $str); 206 | $text = ''; 207 | if (is_array($arr)) { 208 | foreach ( $arr as $val ) { 209 | $val = trim($val); 210 | if ( !empty($val) ) { 211 | $text .= $val.'|'; 212 | } elseif ($isThumb) { 213 | $text .= $this->base_dir.'images/default.png'.'|'; 214 | } 215 | } 216 | } 217 | return $text; 218 | } 219 | 220 | /** 221 | * @desc get MetaBox 222 | */ 223 | private function get_source() { 224 | global $post; 225 | 226 | $result = array(); 227 | $source = get_post_meta( $post->ID, 'wp_player_music_type', true ); 228 | 229 | $result['source'] = empty($source) ? 'xiami' : $source; 230 | $result['xiami'] = get_post_meta( $post->ID, 'mp3_xiami', true ); 231 | $result['title'] = $this->each(trim(get_post_meta( $post->ID, 'mp3_title', true ))); 232 | $result['author'] = $this->each(trim(get_post_meta( $post->ID, 'mp3_author', true ))); 233 | $result['file'] = $this->each(trim(get_post_meta( $post->ID, 'mp3_address', true ))); 234 | $result['thumb'] = $this->each(get_post_meta( $post->ID, 'mp3_thumb', true ), true); 235 | $result['type'] = get_post_meta( $post->ID, 'mp3_xiami_type', true ); 236 | 237 | $lyric = get_post_meta( $post->ID, 'wp_player_lyric_open', true ); 238 | if ( !empty( $lyric ) && $lyric == 'open' ) { 239 | $result['open'] = $lyric; 240 | $result['output'] = '
    '; 241 | } else { 242 | $result['open'] = 'close'; 243 | $result['output'] = ''; 244 | } 245 | 246 | return $result; 247 | } 248 | 249 | /** 250 | * @desc add shortcode 251 | */ 252 | public function wp_player_shortcode( $atts ){ 253 | global $post; 254 | 255 | extract( shortcode_atts( array( 256 | 'autoplay' => 0, 257 | 'random' => 0 258 | ), $atts ) ); 259 | 260 | $data = $this->get_source(); 261 | $img = $this->base_dir.'assets/images/default.png'; 262 | 263 | return '
    '.$data['output'].'
        '; 264 | } 265 | 266 | /** 267 | * @desc WP-Player Admin Option Page 268 | */ 269 | public function printAdminPage(){ 270 | ?> 271 |
        272 |

        WP-Player 设置


        273 |
        274 | 275 | options; ?> 276 | 277 | 278 | 279 | 280 | 287 | 288 | 289 | 290 | 305 | 306 | 307 | 308 | 316 | 317 | 318 |
        281 | 文章中插入短代码:
        282 |
          283 |
        1. [player]
        2. 284 |
        3. [player autoplay="0" randplay="1"]
        4. 285 |
        286 |
        291 | 提供了MetaBox来填写参数
        292 |
          293 |
        1. WP-Player 支持网易云音乐, 虾米音乐, QQ音乐, 百度音乐平台
        2. 294 |
        3. 如在网易云音乐打开喜欢的歌曲页面,复制歌曲页面的网址如:http://music.163.com/#/song?id=191213
        4. 295 |
        5. 并将复制的网址填写到后面的表单内。音乐类型将根据网址自动做出选择。
        6. 296 |
        7. 点击获取音乐ID按钮,此时音乐ID出现在表单中。
        8. 297 |
        9. 将短代码 [player autoplay="1" random="1"] 填入您的文章内容中。
        10. 298 |
        11. 短代码中 autoplay 表示是否自动播放;参数"0"表示否;"1"表示是;
        12. 299 |
        13. 短代码中 random 表示是否随机播放;参数"0"表示否;"1"表示是;
        14. 300 |
        15. 支持播放歌单:单音乐页面、专辑页面、艺人页面、精选集页面。
        16. 301 |
        17. PS:本插件需要您的服务器或主机支持 PHP 5.4+ and Curl, OpenSSL 模块已安装。
        18. 302 |
        19. Tips:本插件仅供个人学习研究使用,请勿作为各种商业用户,音乐版权归各音乐平台所有。
        20. 303 |
        304 |
        309 |
        310 | 314 |
        315 |
        319 |
        320 |
        321 | 322 |
        323 |
        324 |
        325 | -------------------------------------------------------------------------------- /dist/wp-player/readme.txt: -------------------------------------------------------------------------------- 1 | === WP-Player === 2 | Contributors: M.J 3 | Donate link: http://webjyh.qiniudn.com/alipay.png 4 | Tags: 网易云音乐, 虾米音乐, QQ 音乐, 百度音乐, MP3, WP-Player, Mp3-Player, Player 5 | Requires at least: 4.0 6 | Tested up to: 4.8 7 | Stable tag: trunk 8 | License: GPLv2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | 11 | WP-Player 一个迷你歌曲播放器,支持多歌曲播放,支持使用网易云音乐, 虾米音乐, QQ音乐, 百度音乐歌曲地址, 也支持自定义上传音乐。 12 | 13 | == Description == 14 | 15 | WordPress 插件 WP-Player 是一个迷你歌曲播放器,支持多歌曲播放,支持使用网易云音乐, 虾米音乐, QQ音乐, 百度音乐歌曲地址, 也支持自定义上传音乐。 16 | 17 | 插件介绍: 18 | 1. WP-Player 支持网易云音乐, 虾米音乐, QQ音乐, 百度音乐平台 19 | 2. 如在网易云音乐打开喜欢的歌曲页面,复制歌曲页面的网址如:http://music.163.com/#/song?id=191213 20 | 3. 并将复制的网址填写到后面的表单内。音乐类型将根据网址自动做出选择。 21 | 4. 点击获取音乐ID按钮,此时音乐ID出现在表单中。 22 | 5. 将短代码 [player autoplay="1" random="1"] 填入您的文章内容中。 23 | 6. 短代码中 autoplay 表示是否自动播放;参数"0"表示否;"1"表示是; 24 | 7. 短代码中 random 表示是否随机播放;参数"0"表示否;"1"表示是; 25 | 8. 支持播放歌单:单音乐页面、专辑页面、艺人页面、精选集页面。 26 | 9. PS:本插件需要您的服务器或主机支持 PHP 5.4+ and Curl, OpenSSL 模块已安装。 27 | 10. Tips:本插件仅供个人学习研究使用,请勿作为各种商业用户,音乐版权归各音乐平台所有 28 | 29 | PS:一篇文章只能插入一个播放器,因为用了MetaBox获取参数,只能一篇文章使用一个。 30 | 31 | 详细介绍: http://webjyh.com/wp-player/ 32 | 33 | == Installation == 34 | 1. 上传 `wp-player`目录 到 `/wp-content/plugins/` 目录 35 | 2. 在后台插件菜单激活该插件 36 | 3. 短代码调用插件: 37 | [player] 38 | [player autoplay="1" random="1"] 39 | 40 | == Screenshots == 41 | 42 | 1. 播放器界面 43 | 2. 插件参数填写 44 | 3. 插件后台设置 45 | 46 | == Changelog == 47 | = v2.6.2 = 48 | 1. 修复 网易云音乐某些链接从http重写https的问题 @timk-lalala 49 | 50 | = v2.6.1 = 51 | 1. 修复 PHP 语法报错问题 52 | 53 | = v2.6.0 = 54 | 1. 新增 QQ音乐 百度音乐平台。 55 | 2. 新增 当前歌曲不能播放,跳转至下一曲。 56 | 3. 新增 随机播放歌曲功能。 57 | 4. 新增 $('[data-wp-player="wp-player"]').WPPlayer('reload'); 方法,让单页面用户 可重新初始化播放器。 58 | 5. 新增 $('[data-wp-player="wp-player"]').WPPlayer('destroy'); 方法,用于销毁播放器; 59 | 6. 新增 歌曲列表自动滚动到中间位置,在也不用为找不到当前歌曲烦恼。 60 | 7. 修复虾米,网易获取音乐失败问题。 61 | 8. 修复样式问题,改善收缩列表动画问题 62 | 9. 美化歌曲列表滚动条样式 63 | 10. 更新 SoundManager 版本至最新版本 64 | 11. 在此感谢 @metowolf 开发的 Meting 框架,为获取音乐提供了更简单的方式 65 | 12. 项目地址:https://github.com/metowolf/Meting 66 | 13. 此版本项目结够改动比较大,请删除插件重新安装最好 67 | 68 | = v2.5.1 = 69 | 1. 紧急修复因2.5.0版本导致网易云音乐不能播放问题 70 | 71 | = v2.5.0 = 72 | 1. 新增自定义上传歌曲支持多歌曲。 73 | 2. 歌曲按一行一个填写,歌曲内容列表按歌曲名显示。 74 | 3. 因考虑自定义上传将会有多条记录,所以才用一行一首歌曲来填写。 75 | 4. 修正歌曲只有两首时,上一首,下一首按钮无用情况。 76 | 5. 现阶段功能上已基本完成,年前将只会进行Bug修复,暂不会开发新功能。 77 | 6. 如还想用2.4.2 老版本 请戳:https://github.com/webjyh/WP-Player/releases 78 | 7. 各位马上就要过年了,各位新年快乐! 79 | 80 | = v2.4.2 = 81 | 1. 修正因某些主题使用字体图标导致样式错位 82 | 2. 修正某些主题下歌单不显示的问题 83 | 3. 修正若干样式排版问题 84 | 4. 下个版本将会入手自定义上传多歌曲功能 85 | 86 | = v2.4.1 = 87 | 1. 解决因关闭歌词功能导致的JS错误。 88 | 2. 修正移动端最小宽度问题。 89 | 90 | = v2.4.0 = 91 | 1. 新增移动端播放适配(暂不支持移动端自动播放歌曲功能)。 92 | 2. 因移动端的兼容性问题,自动播放功能将无法使用。 93 | 3. 因歌词功能消耗较大,在移动端下将被禁用。 94 | 4. 在 iPhone 6、iPhone 5s、iPhone 5、iOS 8.x+系统 测试通过。 95 | 5. 在 Android 4.1+ 系统测试过能。 96 | 6. 因移动端机型混杂,各大浏览器厂商也更多,难免会有意料之外的Bug。 97 | 7. 修正移动端样式问题。 98 | 8. 如想用 v2.3.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 99 | 100 | = v2.3.1 = 101 | 1. 紧急修复暂无歌词Bug 102 | 2. 修正图片缓存问题 103 | 104 | = v2.3.0 = 105 | 1. 新增歌词预览功能( 支持虾米和网易 ) 106 | 2. 因歌词预览功能比较耗费资源,可在单独添加播放器时,打开或关闭此功能。 107 | 3. 因获取歌词功能接口的一些特殊性,如在后台选择中未出现歌词功能,则表示当前站点暂不支持。 108 | 4. 因其调取接口获取歌词在处理歌词时间上难免会有些误差(请不要太在意这些细节) 109 | 5. 修正一些样式错误。 110 | 6. 如想用 v2.2.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 111 | 112 | = v2.2.0 = 113 | 1. 新增网易云音乐网址的调用(支持单音乐页面、专辑页面、艺人页面、精选集[即歌单]页面) 114 | 2. 因网易的接口一些特殊性,如在后台选择网站类型中没有出现网易音乐,则您当前的站点暂不支持网易云音乐。 115 | 3. 其次要感谢牧风的音乐播放插件,作为参考实现了网易接口的思路。 116 | 4. 在次还要感谢此文作者 https://github.com/yanunon/NeteaseCloudMusic/wiki/网易云音乐API分析 117 | 5. 修正播放器请求容错处理方案。 118 | 6. 去除短代码中 00:00 字样。 119 | 7. 修正播放器样式问题。 120 | 8. 如想用 v2.1.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 121 | 122 | = v2.1.0 = 123 | 1. 因发现最近播放器在解析虾米地址时,出现不稳定的情况,采用最新发现的虾米接口。 124 | 2. 新接口将是直接调取虾米网接口,速度更快且稳定。 125 | 3. 为其保险起见,怕日后虾米封其接口,如获取失败,将移交给新浪云解析。 126 | 4. 去除播放器HTML中的 Loading 字样,为其前台显示更美观。 127 | 5. 修正播放器样式问题。 128 | 6. 修正某些情况下导致图片无法显示的情况。 129 | 7. 如想用 v2.0.1 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 130 | 131 | = v2.0.1 = 132 | 1. 修正因接口调制后台无法抓取虾米ID的问题 133 | 2. 后台无法抓去将采用 新浪云来解析 134 | 3. 修正播放器样式问题。 135 | 136 | = v2.0.0 = 137 | 1. 播放器新版扁平皮肤 138 | 2. 支持虾米多歌曲播放 139 | 3. 支持单音乐页面、专辑页面、艺人页面、精选集页面 140 | 4. 重构虾米地址填写解析;现只需复制网址,便可自动解析虾米ID。 141 | 5. 将解析虾米地址移交至插件本身 142 | 6. 重构播放器JS,采用SoundManger2来管理 143 | 7. 支持IE6+,FireFox,Chrome; 144 | 8. 废除短代码 loop 参数 145 | 9. 关闭后台无用选项设置 146 | 147 | = v1.3.4 = 148 | 1. 修正 弱干 Bug 149 | 2. 由百度云平台解析 换至 新浪云平台 150 | 3. 百度云平台解析至 2014-10月底废除,请各位小伙伴赶紧更新 151 | 152 | = v1.3.2 = 153 | 1. 修正 后台 jQuery 选项选择无用的Bug。 154 | 155 | = v1.3.1 = 156 | 1. 因提交到官方所以删除一些无用文件 157 | 2. 由原来自带的jQuery库 修改调用WordPress自带jQuery库 158 | 159 | = v1.3.0 = 160 | 1. 增加百度云API,使解析虾米音乐地址更稳定 161 | 2. 细节调整 162 | 3. 修复Bug 163 | 4. 代码重构 164 | 5. 初次使用请到插件设置页面,设置虾米解析API。 165 | 166 | = v1.2.0 = 167 | 1. 增加皮肤选择 168 | 2. 新增扁平化皮肤 具体效果查看本页面播放器 169 | 3. 增加插件设定按钮 170 | 4. 扁平化皮肤 只支持 Chrome 和 FireFox 游览器 171 | 172 | = v1.1.0 = 173 | 1. 因虾米API变动,解决获取歌曲地址问题! 174 | 2. 添加根据虾米ID自动获取歌曲信息 175 | 3. MeatBox 更加简洁化 176 | 177 | = v1.0.0 = 178 | 1. 插件初始版本 -------------------------------------------------------------------------------- /dist/wp-player/wp-player.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name wp-player gulp 3 | * @desc wp-player 打包压缩 4 | * @author M.J 5 | * @date 2017-06-06 6 | * @URL http://webjyh.com 7 | * @Github https://github.com/webjyh/WP-Player 8 | * 9 | */ 10 | var path = require('path'), 11 | fs = require('fs'), 12 | gulp = require('gulp'), 13 | uglify = require('gulp-uglify'), 14 | minifyCss = require('gulp-minify-css'), 15 | postcss = require('gulp-postcss'), 16 | autoprefixer = require('autoprefixer'), 17 | replace = require('gulp-replace'), 18 | pkg = require('./package.json'); 19 | 20 | var source = {base: 'src'}; 21 | var dist = __dirname + '/dist/wp-player'; 22 | var getDate = function() { 23 | var d = new Date(); 24 | return d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate(); 25 | }; 26 | 27 | /* build style */ 28 | gulp.task('build:style', function (){ 29 | gulp.src(['src/assets/css/**/*.css'], source) 30 | .pipe(postcss([autoprefixer(['iOS >= 7', 'Android >= 4.1'])])) 31 | .pipe(replace('<%=date%>', getDate())) 32 | .pipe(replace('<%=version%>', pkg.version)) 33 | .pipe(minifyCss({ 34 | keepBreaks: false, 35 | keepSpecialComments: '*' 36 | })) 37 | .pipe(gulp.dest(dist)); 38 | }); 39 | 40 | /* build script */ 41 | gulp.task('build:script', function () { 42 | gulp.src(['src/assets/js/**/*.js'], source) 43 | .pipe(uglify({ 44 | output: { 45 | comments: /^!/, 46 | } 47 | })) 48 | .pipe(replace('<%=date%>', getDate())) 49 | .pipe(replace('<%=version%>', pkg.version)) 50 | .pipe(gulp.dest(dist)); 51 | }); 52 | 53 | /* build assets */ 54 | gulp.task('build:assets', function (){ 55 | gulp.src('src/assets/**/*.?(eot|svg|ttf|woff|png|jpg|gif|swf)', source) 56 | .pipe(gulp.dest(dist)); 57 | }); 58 | 59 | /* build file */ 60 | gulp.task('build:file', function (){ 61 | gulp.src(['src/**/*.php', 'src/**/*.txt'], source) 62 | .pipe(replace('<%=date%>', getDate())) 63 | .pipe(replace('<%=version%>', pkg.version)) 64 | .pipe(gulp.dest(dist)); 65 | }); 66 | 67 | /* release */ 68 | gulp.task('release', ['build:assets', 'build:style', 'build:script', 'build:file']); 69 | 70 | /* task */ 71 | gulp.task('default', ['release']); 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wp-player", 3 | "version": "2.6.2", 4 | "description": "WP-Player 一个迷你歌曲播放器,支持多歌曲播放,支持使用网易云音乐, 虾米音乐, QQ音乐, 百度音乐歌曲地址, 也支持自定义上传音乐。", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "gulp" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/webjyh/WP-Player.git" 12 | }, 13 | "keywords": [ 14 | "网易云音乐", 15 | "虾米音乐", 16 | "QQ", 17 | "音乐", 18 | "百度音乐", 19 | "MP3", 20 | "WP-Player", 21 | "Mp3-Player", 22 | "Player" 23 | ], 24 | "author": "M.J", 25 | "license": "GPL-2.0", 26 | "bugs": { 27 | "url": "https://github.com/webjyh/WP-Player/issues" 28 | }, 29 | "homepage": "https://github.com/webjyh/WP-Player#readme", 30 | "dependencies": { 31 | "autoprefixer": "^7.1.1", 32 | "gulp": "^3.9.1", 33 | "gulp-minify-css": "^1.2.4", 34 | "gulp-postcss": "^7.0.0", 35 | "gulp-uglify": "^3.0.0" 36 | }, 37 | "devDependencies": { 38 | "gulp-replace": "^0.5.4" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/assets/css/wp-player-plugin.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name WP-Player Admin CSS 3 | * @desc WP-Player MetaBox 样式 4 | * @author M.J 5 | * @date 2014-12-19 6 | * @update <%=date%> 7 | * @URL http://webjyh.com 8 | * @Github https://github.com/webjyh/WP-Player 9 | * @version <%=version%> 10 | */ 11 | .wp-player-wrap { padding: 10px; } 12 | .wp-player-wrap .wp-player-tabs { margin: 0px; border-bottom: 1px solid #EEE; height: 36px; } 13 | .wp-player-wrap .wp-player-tabs li { display: inline-block; *zoom: 1; margin: 0px; } 14 | .wp-player-wrap .wp-player-tabs li a { display: inline-block; *zoom: 1; padding: 0px 15px; height: 36px; line-height:36px; color: #333; text-decoration: none; margin-right: 10px; border: 1px solid #FFF; border-bottom: 0; } 15 | .wp-player-wrap .wp-player-tabs li.current a { border-color: #EEE; background: #FFF; font-weight: bold; } 16 | .wp-player-wrap .wp-player-row { border: 1px solid #EEE; padding:10px 15px; border-top: none; } 17 | .wp-player-wrap .wp-player-row .red { color: red; } 18 | .wp-player-wrap .wp-player-inner { display: none; } 19 | .wp-player-wrap .wp-player-inner.current { display: block; } 20 | .wp-player-wrap .wp-player-text { height: 28px; width: 50%; } 21 | .wp-player-wrap .wp-player-select { vertical-align: top; } 22 | .wp-player-wrap .wp-player-textarea { margin-bottom: 10px; } 23 | .wp-player-wrap .wp-player-textarea textarea { width: 60%; min-height: 120px; margin-bottom: 5px; margin-right: 5px; } 24 | .wp-player-wrap .wp-player-textarea p.desc { margin: 0px; color: #666; } 25 | 26 | @media screen and (min-width: 1200px) { .wp-player-wrap .wp-player-text { width: 35%; } } 27 | @media screen and (min-width: 1300px) { .wp-player-wrap .wp-player-text { width: 45%; } } 28 | @media screen and (min-width: 1400px) { .wp-player-wrap .wp-player-text { width: 50%; } } 29 | @media screen and (min-width: 1500px) { .wp-player-wrap .wp-player-text { width: 55%; } } -------------------------------------------------------------------------------- /src/assets/css/wp-player.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name WP-Player CSS 3 | * @desc WP-Player 样式表 4 | * @author M.J 5 | * @date 2014-12-21 6 | * @update <%=date%> 7 | * @URL http://webjyh.com 8 | * @Github https://github.com/webjyh/WP-Player 9 | * @version <%=version%> 10 | * 11 | */ 12 | .wp-player { overflow: hidden; background: #FFF; width: 350px; min-width: 300px; margin: 10px auto; border: 1px solid #DDD; box-shadow: 0px 0px 10px rgba(0,0,0, 0.15); box-sizing: content-box; } 13 | .wp-player * { -webkit-user-select: none; -webkit-overflow-scrolling: touch; -webkit-tap-highlight-color: rgba(0,0,0,0); outline: 0; border-radius: 0; box-shadow: none; font-family: "Microsoft Yahei", arial; box-sizing: content-box; font-size: 12px; margin: 0; padding: 0; background: none; border: 0; text-indent: 0; line-height: 1.4; } 14 | 15 | .wp-player .wp-player-list ul li, 16 | .wp-player .wp-player-list ul li a, 17 | .wp-player .wp-player-list-order, 18 | .wp-player .wp-player-title, 19 | .wp-player .wp-player-author { overflow: hidden; white-space: nowrap; *white-space: normal; text-overflow: ellipsis; } 20 | 21 | .wp-player .wp-player-play-current, 22 | .wp-player .wp-player-list-btn, 23 | .wp-player .wp-player-lyrics-btn, 24 | .wp-player .wp-player-controls a { background: url(../images/wp_player_bg.png) no-repeat -9999px -9999px !important; _background: url(../images/wp_player_bg_8.png) no-repeat -9999px -9999px !important; } 25 | 26 | @media screen and (-webkit-min-device-pixel-ratio: 2), screen and (max-moz-device-pixel-ratio: 2) { 27 | .wp-player .wp-player-play-current, 28 | .wp-player .wp-player-list-btn, 29 | .wp-player .wp-player-lyrics-btn, 30 | .wp-player .wp-player-controls a { background-image: url(../images/wp_player_bg2x.png) !important; background-size: 58px auto !important; } 31 | } 32 | 33 | /* wp-player-play */ 34 | .wp-player .wp-player-box { height: 90px; user-select: none; } 35 | .wp-player .wp-player-thumb { position: relative; float: left; width: 90px; height: 90px; overflow: hidden; } 36 | .wp-player .wp-player-thumb img { padding: 0 !important; margin: 0!important; border-radius: 0!important; box-shadow: none!important; border: 0!important; display: block; width: 90px; height: 90px; vertical-align: top; } 37 | .wp-player .wp-player-playing { display: none; position: absolute; z-index: 2; top: 0; left: 0; width: 90px; height: 90px; background: #000; background: rgba(0, 0, 0, 0.4); filter: alpha(opacity=40); } 38 | .wp-player .wp-player-playing span { display: block; position: absolute; top: 50%; left: 50%; margin: -5px 0px 0px -5px; z-index: 3; width: 11px; height: 11px; background: url(../images/playing.gif) no-repeat !important; } 39 | .wp-player .wp-player-panel { margin-left: 100px; padding-top: 0px; padding-right: 10px; } 40 | .wp-player .wp-player-title { font-size: 14px; height: 24px; line-height: 24px; color: #555; } 41 | .wp-player .wp-player-author { line-height: 1.4; color: #999; margin-bottom: 5px; } 42 | .wp-player .wp-player-progress { height: 4px; margin-bottom: 7px; background: #e7e9eb; border-radius: 5px; } 43 | .wp-player .wp-player-seek-bar { width: 0; height: 100%; background: #DDD; cursor: pointer; border-radius: 5px; } 44 | .wp-player .wp-player-play-bar { position:relative; width: 0; height: 100%; background: #00cacf; border-radius: 5px; -webkit-transition: all 0.3s; -moz-transition: all 0.3s; transition: all 0.3s; } 45 | .wp-player .wp-player-play-current { display: block; position: absolute; top: -3px; right: -5px; width: 10px; height: 10px; background-position: 0px -57px !important; } 46 | .wp-player .wp-player-controls-holder { position: relative; height: 28px; overflow: hidden; } 47 | .wp-player .wp-player-time { position: absolute; top: 0px; left: 0px; width: 45px; height: 28px; line-height: 28px; color: #9a9a9a; text-align: center; } 48 | .wp-player .wp-player-lyrics-btn { cursor: pointer; position: absolute; top: 9px; right: 25px; width: 14px; height: 14px; background-position: -20px -56px !important; } 49 | .wp-player .wp-player-list-btn { cursor: pointer; position: absolute; top: 10px; right: 0px; width: 18px; height: 10px; background-position: -40px -57px !important; } 50 | .wp-player .wp-player-controls { position: absolute; top: 0px; left: 50%; margin-left: -50px; width: 100px; height: 28px; } 51 | .wp-player .wp-player-controls a { outline: 0 !important; margin: 0 !important; padding: 0 !important; border: 0 !important; text-decoration: none !important; position: absolute; display: block; } 52 | .wp-player a.wp-player-previous, 53 | .wp-player a.wp-player-next { top: 9px; left: 0px; width: 16px; height: 10px; box-shadow: none !important; background-position: 0px -6px !important; _background-position: 0px -4px !important; } 54 | .wp-player a.wp-player-next { left: auto; right: 0px; background-position: -42px -6px !important; _background-position: -42px -4px !important; } 55 | .wp-player a.wp-player-play, 56 | .wp-player a.wp-player-stop { top: 0px; left: 36px; width: 28px; height: 28px; background-position: 0px -21px !important; box-shadow: none !important; } 57 | .wp-player a.wp-player-stop { display: none; background-position: -30px -21px !important; } 58 | 59 | /* wp-player-list */ 60 | .wp-player .wp-player-main { position: relative; } 61 | .wp-player .wp-player-list { border-top: 1px solid #DDD; -webkit-overflow-scrolling: touch; max-height: 330px; overflow: auto; -webkit-transition: height 0.6s; -moz-transition: height 0.6s; transition: height 0.6s; } 62 | .wp-player .wp-player-list::-webkit-scrollbar { height: 8px; width: 8px; } 63 | .wp-player .wp-player-list::-webkit-scrollbar-button { height: 0; width: 0; } 64 | .wp-player .wp-player-list::-webkit-scrollbar-track:vertical, 65 | .wp-player .wp-player-list::-webkit-scrollbar-track:horizontal { background-clip: padding-box; background-color: #fff; } 66 | .wp-player .wp-player-list::-webkit-scrollbar-thumb { -webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1), inset 0 -1px 0 rgba(0, 0, 0, .07); background-clip: padding-box; background-color: rgba(0, 0, 0, .2); min-height: 28px; padding-top: 100 } 67 | .wp-player .wp-player-list::-webkit-scrollbar-thumb:hover { -webkit-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, .25); background-color: rgba(0, 0, 0, .4) } 68 | .wp-player .wp-player-list::-webkit-scrollbar-thumb:active { -webkit-box-shadow: inset 1px 1px 3px rgba(0, 0, 0, .35); background-color: rgba(0, 0, 0, .5) } 69 | .wp-player .wp-player-list::-webkit-scrollbar-track:vertical, 70 | .wp-player .wp-player-list::-webkit-scrollbar-track:horizontal, 71 | .wp-player .wp-player-list::-webkit-scrollbar-thumb:vertical, 72 | .wp-player .wp-player-list::-webkit-scrollbar-thumb:horizontal { border-width: 0; } 73 | .wp-player .wp-player-list::-webkit-scrollbar-track:hover { -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, .1); background-color: rgba(0, 0, 0, .05) } 74 | .wp-player .wp-player-list::-webkit-scrollbar-track:active { -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, .14), inset -1px -1px 0 rgba(0, 0, 0, .07); background-color: rgba(0, 0, 0, .05) } 75 | .wp-player .wp-player-list ul { margin: 0; padding: 0; border: 0; list-style: none; } 76 | .wp-player .wp-player-list ul li { list-style-type: none !important; background:#FFF; margin: 0 !important; padding: 0; border: 0 !important; cursor: pointer; list-style: none; height: 22px; line-height: 22px; padding: 4px 0px; } 77 | .wp-player .wp-player-list ul li:after, 78 | .wp-player .wp-player-list ul li:hover:after { content: '' !important; font-family: "Microsoft Yahei" !important; margin: 0px !important; } 79 | .wp-player .wp-player-list ul li:before, 80 | .wp-player .wp-player-list ul li:hover:before { content: '' !important; font-family: "Microsoft Yahei" !important; margin: 0px !important; } 81 | .wp-player .wp-player-list ul li a { outline: 0!important; box-shadow: none !important; border: 0; background:none !important; height: 22px; overflow: hidden; line-height: 22px; padding: 0px 10px; display: block; *zoom: 1; color: #333; border-left: 4px solid #FFF; text-decoration: none; } 82 | .wp-player .wp-player-list ul li.odd { line-height: 22px; background: #f7f7f7; } 83 | .wp-player .wp-player-list ul li.odd a { line-height: 22px; border-color: #f7f7f7; } 84 | .wp-player .wp-player-list ul li.current a, 85 | .wp-player .wp-player-list ul li a:hover { border-left: 4px solid #00cacf; } 86 | .wp-player .wp-player-list-hide { height: 0 !important; border-top: 0 !important; } 87 | 88 | .wp-player .wp-player-list-title { line-height: 22px; } 89 | .wp-player .wp-player-list-author { line-height: 22px; float: right; padding-left: 10px; } 90 | .wp-player .wp-player-list-order { line-height: 22px; float: left; color: #9a9a9a; *zoom: 1; width: 25px; height: 100%; } 91 | 92 | /* wp-player-lyrics */ 93 | .wp-player .wp-player-lyrics { border-top: 1px solid #DDD; max-height: 330px; overflow: hidden; } 94 | .wp-player .wp-player-lyrics ul { display: none; margin: 0; padding: 0; border: 0; list-style: none; -webkit-transition: all 0.3s linear; -moz-transition: all 0.3s; transition: all 0.3s linear; } 95 | .wp-player .wp-player-lyrics ul li { list-style-type: none !important; background: #FFF; margin: 0 !important; line-height: 1.5 !important; border: 0 !important; padding: 5px 10px !important; color: #666; font-size: 12px; text-align: center; -webkit-transition: color 0.5s linear; transition: color 0.5s linear; height: 17px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } 96 | .wp-player .wp-player-lyrics ul li:after { content: '' !important; font-family: "Microsoft Yahei" !important; margin: 0px !important;} 97 | .wp-player .wp-player-lyrics ul li:before { content: '' !important; font-family: "Microsoft Yahei" !important; margin: 0px !important; } 98 | .wp-player .wp-player-lyrics ul li.current { font-size: 14px; color: #00cacf; } 99 | 100 | /* @media */ 101 | @media screen and (max-width: 720px){ 102 | .wp-player { width: auto; min-width: 210px; } 103 | .wp-player .wp-player-thumb { display: none; } 104 | .wp-player .wp-player-panel { margin: 0; padding-left: 10px; width: auto; } 105 | .wp-player .wp-player-list ul li { padding: 6px 0px; height: 26px; line-height: 26px; } 106 | .wp-player .wp-player-list ul li a { height: 26px; line-height: 26px; font-size: 14px; } 107 | .wp-player .wp-player-list-order, 108 | .wp-player .wp-player-list-author, 109 | .wp-player .wp-player-list-title { line-height: 26px; } 110 | .wp-player-lyrics-btn, 111 | .wp-player-lyrics ul { display: none; } 112 | } -------------------------------------------------------------------------------- /src/assets/images/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/src/assets/images/default.png -------------------------------------------------------------------------------- /src/assets/images/playing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/src/assets/images/playing.gif -------------------------------------------------------------------------------- /src/assets/images/wp_player_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/src/assets/images/wp_player_bg.png -------------------------------------------------------------------------------- /src/assets/images/wp_player_bg2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/src/assets/images/wp_player_bg2x.png -------------------------------------------------------------------------------- /src/assets/images/wp_player_bg_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/src/assets/images/wp_player_bg_8.png -------------------------------------------------------------------------------- /src/assets/js/libs/soundmanager/soundmanager2.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/WP-Player/3a1d42cc7b882ae250fd160160bcb95c99950c5c/src/assets/js/libs/soundmanager/soundmanager2.swf -------------------------------------------------------------------------------- /src/assets/js/plugin-uploader.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name Wp-Player Admin JS 3 | * @desc MetaBox JavaScript 4 | * @depend jQuery 5 | * @author M.J 6 | * @date 2014-12-19 7 | * @update <%=date%> 8 | * @URL http://webjyh.com 9 | * @Github https://github.com/webjyh/WP-Player 10 | * @version <%=version%> 11 | * 12 | */ 13 | jQuery(document).ready(function() { 14 | 15 | //wp-player upload dialog 16 | var original_send_to_editor = window.send_to_editor; 17 | jQuery('.WP-Player-File').on('click', function() { 18 | var $elem = jQuery(this).prev(), 19 | formField = $elem.attr('id'); 20 | 21 | tb_show('', 'media-upload.php?media-upload.php?type=image&TB_iframe=true'); 22 | window.send_to_editor = function(html) { 23 | var fileUrl = jQuery( html ).attr('href'), 24 | originVal = $elem.val(); 25 | 26 | tb_remove(); 27 | jQuery( '#'+formField ).val( originVal + "\r" +fileUrl ); 28 | window.send_to_editor = original_send_to_editor; 29 | } 30 | return false; 31 | }); 32 | 33 | //wp-player Tabs 34 | jQuery('#wp-player-tabs > li').on('click', function() { 35 | var index = jQuery(this).index(); 36 | jQuery(this).addClass('current').siblings().removeClass('current'); 37 | jQuery('#wp-player-row > div').hide().eq(index).fadeIn(); 38 | }); 39 | 40 | //get Music ID 41 | jQuery('#wp_player_get_xiami_id').on('click', function() { 42 | var $type = jQuery('#wp_player_music_type'), 43 | $elem = jQuery('#mp3_xiami'), 44 | $select = jQuery('#mp3_xiami_type'), 45 | $val = $elem.val(), 46 | regs = [ 47 | /^http[s]?:\/\/music.163.com\/#.*\/{1}(.+)\?id=(\d+)/, 48 | /^http[s]?:\/\/\w*[\.]?xiami.com+\/(\w+)\/+(\w+).*/, 49 | /^http[s]?:\/\/y.qq.com\/n\/yqq\/(.+)\/+(\w+)*/, 50 | /^http[s]?:\/\/music.baidu.com\/(.+)\/+(\w+)*/ 51 | ], 52 | typeArr = ['netease', 'xiami', 'tencent', 'baidu'], 53 | result = {}; 54 | 55 | if (typeof $val === undefined || $val == '') { 56 | $elem.focus(); 57 | return false; 58 | } 59 | 60 | var index = $val.indexOf('163.com') > -1 ? 0 : ($val.indexOf('xiami.com') > -1 ? 1 : ($val.indexOf('y.qq.com') > -1 ? 2 : 3)), 61 | row = $val.match(regs[index]); 62 | 63 | if (!row || !jQuery.isArray(row)) { 64 | alert('\u83b7\u53d6\u97f3\u4e50ID\u5931\u8d25\uff01'); 65 | return false; 66 | } 67 | 68 | if (jQuery.isArray(row)) { 69 | result['type'] = row[1]; 70 | result['id'] = row[2]; 71 | } 72 | 73 | if ( jQuery.isArray( row ) && result['type'] && result['id'] ) { 74 | if (result['type'] == 'singer') { 75 | result['type'] = 'artist'; 76 | } 77 | if ( result['type'] == 'playlist' || result['type'] == 'songlist' ) { 78 | result['type'] = 'collect'; 79 | } 80 | $elem.val( result['id'] ); 81 | $type.find('option[value='+typeArr[index]+']').prop('selected', true); 82 | $select.find('option[value='+result['type']+']').prop('selected', true); 83 | } 84 | }); 85 | }); -------------------------------------------------------------------------------- /src/assets/js/wp-player.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * @name wp-player 3 | * @desc 初始化播放器。 4 | * @depend jQuery, SoundManager2 5 | * @author M.J 6 | * @date 2014-12-21 7 | * @update <%=date%> 8 | * @URL http://webjyh.com 9 | * @Github https://github.com/webjyh/WP-Player 10 | * @reutn {jQuery} 11 | * @version <%=version%> 12 | * 13 | */ 14 | ~function($, soundManager) { 15 | 16 | var WPPlayer = function(elem, options) { 17 | 18 | soundManager.setup({ url: options.swf, debugMode: false }); 19 | 20 | this.index = 0; //当前播放歌曲 21 | this.url = options.url; //Ajax请求地址 22 | this.nonce = options.nonce; //WordPress 随机数 23 | this.img = options.img; //默认图片 24 | this.IE6 = !-[1,] && !window.XMLHttpRequest; //是否是IE 6 25 | this.single = options.single; //是否是详情页 26 | this.lyric = null; //当前歌曲歌词 27 | this.offset = {}; //歌词滚动最小,最大值 28 | this.mark = null; //歌词滚动标记 29 | this.lyricH = 300; //歌词容器高度 30 | this.line = 27; //歌词单行行高 31 | this.isLoad = false; //获取歌曲信息是否完成 32 | this.$elem = $(elem); //当前元素DOM 33 | this.first = true; //是否是第一次载入 34 | this.isMobile = 'createTouch' in document && !('onmousemove' in document) || /(iPhone|iPad|iPod)/i.test(navigator.userAgent); 35 | 36 | this.getDOM(this.$elem).getAttr().init(); 37 | }; 38 | 39 | WPPlayer.prototype = { 40 | 41 | // 初始化 42 | init: function() { 43 | var attr = this.attr, 44 | DOM = this.DOM; 45 | 46 | DOM.time.text('00:00'); 47 | DOM.title.text('Loading...'); 48 | DOM.author.text('Loading...'); 49 | if (attr.lyric && this.isMobile) DOM.lyricsbtn.hide(); 50 | this[attr.id ? 'actions' : 'localAction'](); 51 | }, 52 | 53 | // 音乐获取操作 54 | actions: function() { 55 | var _this = this; 56 | 57 | $.ajax({ 58 | url: this.url, 59 | type: 'post', 60 | headers: { 61 | nonce: this.nonce 62 | }, 63 | data: { 64 | action: 'wpplayer', 65 | type: this.attr.type, 66 | id: this.attr.id, 67 | source: this.attr.source 68 | } 69 | }).done(function(json) { 70 | if (json.status && json.data.list && json.data.list.length) { 71 | _this.data = json.data.list; 72 | _this.createList().getSongInfo().addEvent(); 73 | } 74 | }).fail(function() { 75 | window.console && window.console.info('获取歌曲列表失败'); 76 | }); 77 | }, 78 | 79 | // 获取歌曲信息 80 | // 在设置随机播放情况下 flag 参数 控制是否强制指定歌曲播放 81 | // 为 true 时则播放 val 值的歌曲 82 | getSongInfo: function(val, flag) { 83 | var index = typeof val == 'undefined' ? 0 : val, 84 | _this = this, 85 | DOM = this.DOM, 86 | info = {}; 87 | 88 | DOM.time.text('00:00'); 89 | DOM.title.text('Loading...'); 90 | DOM.author.text('Loading...'); 91 | 92 | if (this.attr.random == 1 && !flag) { 93 | index = this.random(); 94 | } 95 | info = this.data[index]; 96 | this.index = index; 97 | this.setList(); 98 | 99 | if (!info || info.url || this.isLoad) { 100 | return; 101 | } 102 | 103 | this.isLoad = true; 104 | $.ajax({ 105 | url: this.url, 106 | type: 'post', 107 | headers: { 108 | nonce: this.nonce 109 | }, 110 | data: { 111 | action: 'wpplayerGetInfo', 112 | id: info.id, 113 | pic_id: info.pic_id, 114 | url_id: info.url_id, 115 | lyric_id: info.lyric_id, 116 | source: this.attr.source 117 | } 118 | }).done(function(json) { 119 | _this.isLoad = false; 120 | if (json.status && json.data) { 121 | _this.data[index]['lyric'] = json.data.lyric.lyric; 122 | _this.data[index]['pic'] = json.data.pic.url; 123 | _this.data[index]['url'] = json.data.url.url; 124 | _this.createSound(index); 125 | } 126 | }).fail(function() { 127 | _this.isLoad = false; 128 | window.console && window.console.info('获取歌曲失败'); 129 | }); 130 | 131 | return this; 132 | }, 133 | 134 | // 本地上传操作 135 | localAction: function() { 136 | if (typeof this.attr.address === 'undefined') return false; 137 | 138 | function transformArray(str) { 139 | var len = str.length-1; 140 | return str.substr(0, len).split('|'); 141 | } 142 | 143 | var data = [], 144 | index = 0, 145 | title = transformArray(this.attr.title), 146 | artist = transformArray(this.attr.author), 147 | location = transformArray(this.attr.address), 148 | pic = transformArray(this.attr.thumb); 149 | 150 | $.each(title, function(i) { 151 | data.push({ 152 | name: title[i], 153 | lyric: "", 154 | artist: [artist[i]], 155 | url: location[i], 156 | pic: pic[i] 157 | }); 158 | }); 159 | 160 | this.data = data; 161 | this.createList(); 162 | 163 | if (this.attr.random == 1) { 164 | index = this.random(); 165 | } 166 | this.index = index; 167 | this.setList(); 168 | 169 | this.createSound(this.index).addEvent(); 170 | }, 171 | 172 | // 创建音乐列表 173 | createList: function() { 174 | var i = 0, 175 | tpl = '', 176 | DOM = this.DOM, 177 | data = this.data, 178 | len = data.length; 179 | 180 | for (; i 1 && !data.url) { 210 | this.nextSound(); 211 | return; 212 | } 213 | 214 | soundManager.onready(function() { 215 | if (typeof _this.sound === 'object') _this.sound.destruct(); 216 | 217 | _this.timeReady = _this.isMobile ? true : false; 218 | 219 | //create sound 220 | _this.sound = soundManager.createSound({ 221 | url: data.url, 222 | onload: function() { 223 | _this.timeReady = true; 224 | }, 225 | onplay: function() { _this.setPlay() }, 226 | onresume: function() { _this.setPlay() }, 227 | onpause: function() { _this.setStop() }, 228 | onfinish: function() { _this.nextSound() }, 229 | whileplaying: function() { 230 | var count, minute, second, pre, 231 | position = (this.position / this.duration)*100, 232 | playbar = position > 100 ? '100%' : position.toFixed(5) + '%'; 233 | 234 | if (_this.timeReady) { 235 | pre = '-'; 236 | count = Math.floor((this.duration - this.position) / 1000); 237 | minute = _this.formatNumber( Math.floor( count / 60 ) ); 238 | second = _this.formatNumber( Math.floor( count % 60 ) ); 239 | } else { 240 | pre = ''; 241 | minute = '00'; 242 | second = '00'; 243 | } 244 | 245 | DOM.playbar.width(playbar); 246 | DOM.time.text(pre + minute +':'+ second); 247 | 248 | if (_this.attr.lyric && _this.lyric && !_this.isMobile) _this.setLyric(this.position); 249 | }, 250 | whileloading: function() { 251 | var seekbar = (this.bytesTotal && this.bytesLoaded != this.bytesTotal) ? (this.bytesLoaded / this.bytesTotal) * 100 : 100; 252 | DOM.seekbar.width(seekbar+'%'); 253 | }, 254 | onerror: function(code, description) { 255 | window.console && console.log(this.id + ' failed?', code, description); 256 | if (_this.data.length > 1) { 257 | _this.nextSound(); 258 | return; 259 | } 260 | } 261 | }); 262 | 263 | _this.soundEvent(); 264 | 265 | if (_this.attr.lyric && !_this.isMobile) { 266 | data.lyric ? _this.createLyric(data.lyric) : _this.noLyric(); 267 | } 268 | 269 | if (_this.first && !autoplay) { 270 | _this.first = false; 271 | return; 272 | } 273 | 274 | _this.sound.play(); 275 | 276 | }); 277 | 278 | return this; 279 | }, 280 | 281 | //创建歌词 282 | createLyric: function(lyric) { 283 | 284 | //清空歌词 285 | this.emptyLyric(); 286 | 287 | var i = 0, 288 | cache = [], 289 | list = lyric.split("\n"), 290 | len = list.length, 291 | DOM = this.DOM, 292 | reg = /\[(\d+:\d+.?\d+)\]/g, 293 | regStr = /[^\[(\d+):(\d+.?\d+)\]\s*].+/g, 294 | tpl = ''; 295 | 296 | //匹配歌词 297 | for (; i < len; i++) { 298 | var arr = $.trim(list[i]).match(reg); 299 | if ($.isArray(arr)) { 300 | var str = $.trim(list[i]).match(regStr); 301 | for (var j = 0; j < arr.length; j++){ 302 | var t = arr[j].replace('[', '').replace(']', '').split(':'), 303 | time = (t[0] * 60) + Math.floor(t[1]); 304 | cache.push({time: time, lyric: $.isArray(str) ? str[0] : ' ' }); 305 | } 306 | } 307 | } 308 | 309 | if (!cache.length) { 310 | this.noLyric(); 311 | return false; 312 | } 313 | 314 | //排序 315 | i = 0; 316 | len = cache.length; 317 | for (; i < len; i++) { 318 | for (var j = i; j < len; j++) { 319 | if ( cache[i].time > cache[j].time ) { 320 | var temp = cache[i]; 321 | cache[i] = cache[j]; 322 | cache[j] = temp; 323 | } 324 | } 325 | } 326 | 327 | //模板 328 | this.lyric = {}; 329 | for (i = 0; i < len; i++) { 330 | tpl += '
      • ' + cache[i].lyric + '
      • '; 331 | this.lyric[cache[i].time] = i; 332 | } 333 | DOM['lyricList'] = $(tpl).appendTo(DOM.lyrics.children('ul')); 334 | 335 | var list = DOM.lyrics.children('ul').height(), 336 | minH = Math.floor(this.lyricH / 2), 337 | maxH = list - minH; 338 | 339 | this.offset = { 340 | min: Math.floor(minH / this.line), 341 | max: Math.floor(maxH / this.line) 342 | }; 343 | }, 344 | 345 | //设置歌词 346 | setLyric: function(val) { 347 | var DOM = this.DOM, 348 | offset = this.offset, 349 | time = Math.floor(val / 1000), 350 | index = this.lyric && this.lyric[time], 351 | scroll = 0; 352 | 353 | // setting class 354 | if (typeof index !== 'undefined' && DOM.lyricList && this.mark != index) { 355 | 356 | if (index >= offset.min) scroll = index - offset.min; 357 | if (index >= offset.max) scroll = offset.max - offset.min; 358 | 359 | DOM.lyricList.removeClass('current').eq(index).addClass('current'); 360 | DOM.lyrics.children('ul').css('margin-top', -scroll * this.line); 361 | 362 | this.mark = index; 363 | } 364 | }, 365 | 366 | //清空歌词 367 | emptyLyric: function() { 368 | var DOM = this.DOM; 369 | this.lyric = null; 370 | DOM.lyrics.children('ul').css('margin-top', 0).html(''); 371 | }, 372 | 373 | //暂无歌词 374 | noLyric: function(val) { 375 | var DOM = this.DOM, 376 | str = typeof val === 'undefined' ? '\u6682\u65e0\u6b4c\u8bcd' : val; 377 | this.lyric = null; 378 | DOM.lyrics.children('ul').html('
      • '+str+'
      • '); 379 | }, 380 | 381 | //播放器事件 382 | addEvent: function() { 383 | var DOM = this.DOM, 384 | _this = this, 385 | eventType = this.isMobile ? 'touchend' : 'click', 386 | startTx, startTy; 387 | 388 | //show list 389 | DOM.listbtn.on(eventType, function() { 390 | var has = $(this).hasClass('wp-player-open'); 391 | DOM.lyrics.children('ul').stop(true, true).hide(); 392 | $(this)[has ? 'removeClass' : 'addClass']('wp-player-open'); 393 | DOM.list.show()[has ? 'removeClass': 'addClass']('wp-player-list-hide'); 394 | }); 395 | 396 | //show lyrics 397 | if (this.attr.lyric){ 398 | DOM.lyricsbtn.on(eventType, function() { 399 | DOM.listbtn.addClass('wp-player-open'); 400 | DOM.list.hide(); 401 | DOM.lyrics.children('ul').stop(true, true).fadeIn(); 402 | }); 403 | } 404 | 405 | //select song event 406 | var selectSong = function(val) { 407 | var $elem = typeof val === 'undefined' ? $(this) : $(val).parents('li'), 408 | index = parseInt($elem.attr('data-index'), 10), 409 | has = $elem.hasClass('current') && _this.sound.playState > 0; 410 | (index < 0 || index > _this.data.length-1) ? _this.index = 0 : _this.index = index; 411 | 412 | if (has && !_this.sound.paused) { 413 | _this.sound.pause(); 414 | } else if (has && _this.sound.paused) { 415 | _this.sound.resume() 416 | } else { 417 | _this.sound && _this.sound.pause(); 418 | _this.reset().setList(); 419 | if (_this.data[_this.index] && _this.data[_this.index].url) { 420 | _this.createSound(_this.index); 421 | } else { 422 | _this.getSongInfo(_this.index, true); 423 | } 424 | } 425 | }; 426 | 427 | //判断当前是否为移动端 428 | //如果是移动端采用 tap 替代 click 事件 429 | if (!this.isMobile) { 430 | DOM.list.on('click', 'li', function() { selectSong.call(this); }); 431 | } else { 432 | DOM.list[0].addEventListener('touchstart', function(e) { 433 | var nodeName = e.target.nodeName; 434 | if (nodeName === 'A' || nodeName === 'SPAN') { 435 | var touches = e.touches[0]; 436 | startTx = touches.clientX; 437 | startTy = touches.clientY; 438 | } 439 | }, false); 440 | 441 | DOM.list[0].addEventListener('touchend', function(e) { 442 | var nodeName = e.target.nodeName; 443 | if (nodeName === 'A' || nodeName === 'SPAN') { 444 | var touches = e.changedTouches[0], 445 | endTx = touches.clientX, 446 | endTy = touches.clientY; 447 | 448 | if( Math.abs(startTx - endTx) < 6 && Math.abs(startTy - endTy) < 6 ){ 449 | selectSong(e.target); 450 | startTx = null; 451 | startTy = null; 452 | } 453 | } 454 | }, false); 455 | } 456 | 457 | return this; 458 | }, 459 | 460 | // SoundManage Event 461 | soundEvent: function() { 462 | var DOM = this.DOM, 463 | _this = this, 464 | eventType = this.isMobile ? 'touchend' : 'click'; 465 | 466 | //sound play 467 | if (!this.isMobile) { 468 | DOM.seekbar.off().on(eventType, function(event) { _this.seekbar(event) }); 469 | } 470 | DOM.play.off().on(eventType, function() { _this.play() }); 471 | DOM.stop.off().on(eventType, function() { _this.stop() }); 472 | 473 | //prev, next 474 | if (this.data.length > 1) { 475 | DOM.previous.off().on(eventType, function() { _this.prevSound() }); 476 | DOM.next.off().on(eventType, function() { _this.nextSound() }); 477 | } 478 | 479 | return this; 480 | }, 481 | 482 | // 播放进度 Event 483 | seekbar: function(event) { 484 | var DOM = this.DOM, 485 | _x = event.offsetX ? event.offsetX : (event.clientX - DOM.progress.offset().left).toFixed(0); 486 | var offsetX = (_x / DOM.progress.width()) * this.sound.duration; 487 | if (offsetX < 0) offsetX = 0; 488 | if (offsetX > this.sound.duration) offsetX = this.sound.duration; 489 | this.sound.setPosition(offsetX); 490 | 491 | DOM.lyricList && DOM.lyricList.removeClass('current'); 492 | }, 493 | 494 | //播放 Event 495 | play: function() { 496 | this.sound[this.sound.playState < 1 ? 'play' : 'resume'](); 497 | }, 498 | 499 | //暂停 Event 500 | stop: function() { 501 | this.sound.pause(); 502 | }, 503 | 504 | // 上一首 Event 505 | prevSound: function() { 506 | var minIndex = 0; 507 | 508 | if (this.attr.random == 1) { 509 | this.index = this.random(); 510 | } else { 511 | if (--this.index < minIndex) { 512 | this.index = this.data.length - 1; 513 | } 514 | } 515 | 516 | this.sound && this.sound.pause(); 517 | this.reset().setList(); 518 | if (this.data[this.index] && this.data[this.index].url) { 519 | this.createSound(this.index); 520 | } else { 521 | this.getSongInfo(this.index, true); 522 | } 523 | }, 524 | 525 | // 下一首 Event 526 | nextSound: function() { 527 | var maxIndex = this.data.length-1; 528 | 529 | if (this.attr.random == 1) { 530 | this.index = this.random(); 531 | } else { 532 | if (++this.index > maxIndex) { 533 | this.index = 0; 534 | } 535 | } 536 | 537 | this.sound && this.sound.pause(); 538 | this.reset().setList(); 539 | if (this.data[this.index] && this.data[this.index].url) { 540 | this.createSound(this.index); 541 | } else { 542 | this.getSongInfo(this.index, true); 543 | } 544 | }, 545 | 546 | // 设置当前播放状态 547 | setPlay: function() { 548 | var DOM = this.DOM; 549 | DOM.playing.stop(true,true)[(this.IE6 || this.isMobile ) ? 'show' : 'fadeIn'](); 550 | DOM.play.hide(); 551 | DOM.stop.show(); 552 | return this; 553 | }, 554 | 555 | // 设置当前暂停状态 556 | setStop: function() { 557 | var DOM = this.DOM; 558 | DOM.playing.stop(true,true)[(this.IE6 || this.isMobile ) ? 'hide' : 'fadeOut'](); 559 | DOM.play.show(); 560 | DOM.stop.hide(); 561 | return this; 562 | }, 563 | 564 | // 获取随机数 565 | random: function() { 566 | if (!this.data || this.data.length === 1) { 567 | return 0; 568 | } 569 | return Math.floor(Math.random() * this.data.length) || 0; 570 | }, 571 | 572 | // 重置播放器界面 573 | reset: function() { 574 | var DOM = this.DOM; 575 | this.setStop(); 576 | DOM.seekbar.width(0); 577 | DOM.playbar.width(0); 578 | return this; 579 | }, 580 | 581 | // 设置列表选中 582 | setList: function() { 583 | var DOM = this.DOM, 584 | index = this.index, 585 | $list = DOM.list.find('li'), 586 | liHeight = $list.eq(0).outerHeight(), 587 | number = Math.floor(DOM.list.height() / liHeight), 588 | mean = Math.floor(number / 2), 589 | min = mean, 590 | max = this.data.length - mean; 591 | 592 | if (this.data.length > number) { 593 | if (index <= min) { 594 | DOM.list.scrollTop(0); 595 | } 596 | 597 | if (index > min && index < max) { 598 | DOM.list.scrollTop((index - mean) * liHeight); 599 | } 600 | 601 | if (index >= max) { 602 | DOM.list.scrollTop(DOM.list.children('ul').outerHeight()); 603 | } 604 | } 605 | 606 | DOM.list.find('li').removeClass('current').eq(this.index).addClass('current'); 607 | return this; 608 | }, 609 | 610 | // 获取播放器DOM 611 | getDOM: function($elem) { 612 | var elem = $elem[0].getElementsByTagName('*'), 613 | DOM = {}; 614 | 615 | DOM['wrap'] = $elem; 616 | for (var i = 0; i < elem.length; i++) { 617 | if (elem[i].className.indexOf('wp-player') > -1 ) { 618 | var name = elem[i].className.replace('wp-player', '').replace(/-/g, ''); 619 | DOM[name] = $(elem[i]); 620 | } 621 | } 622 | 623 | this.DOM = DOM; 624 | return this; 625 | }, 626 | 627 | // 格式化时间 628 | formatNumber: function(val) { 629 | return val.toString().length < 2 ? '0' + val : val; 630 | }, 631 | 632 | // 获取播放器必须的属性 633 | getAttr: function() { 634 | var DOM = this.DOM, 635 | lyric = DOM.wrap.attr('data-lyric'), 636 | open = typeof lyric === 'undefined' ? false : (lyric == 'open' ? true : false); 637 | 638 | this.attr = { 639 | source: DOM.wrap.attr('data-source'), 640 | type: DOM.wrap.attr('data-type'), 641 | id: DOM.wrap.attr('data-id'), 642 | title: DOM.wrap.attr('data-title'), 643 | author: DOM.wrap.attr('data-author'), 644 | address: DOM.wrap.attr('data-address'), 645 | thumb: DOM.wrap.attr('data-thumb'), 646 | autoplay: DOM.wrap.attr('data-autoplay'), 647 | random: DOM.wrap.attr('data-random'), 648 | lyric: open 649 | }; 650 | return this; 651 | }, 652 | 653 | /** 654 | * @name 销毁播放器 655 | */ 656 | destroy: function() { 657 | 658 | this.sound && this.sound.unload(); 659 | this.sound = ""; 660 | 661 | if (this.attr.lyric) { 662 | this.DOM.lyrics.children('ul').html(''); 663 | this.DOM.listbtn.trigger(this.isMobile ? 'touchend' : 'click').removeClass('wp-player-open'); 664 | } 665 | this.reset(); 666 | this.DOM.list.removeClass('wp-player-list-hide').children('ul').html(''); 667 | this.DOM.thumb.children('img').attr('src', this.img); 668 | this.DOM.time.text('00:00'); 669 | this.DOM.title.text('Loading...'); 670 | this.DOM.author.text('Loading...'); 671 | this.DOM.wrap.data('WPPlayer', ""); 672 | this.DOM.wrap.off().find('*').off(); 673 | 674 | this.index = 0; 675 | this.lyric = null; 676 | this.offset = {}; 677 | this.mark = null; 678 | this.lyricH = 300; 679 | this.line = 27; 680 | this.isLoad = false; 681 | this.first = true; 682 | this.attr = {}; 683 | this.data = []; 684 | this.img = null; 685 | this.DOM = {}; 686 | }, 687 | 688 | /** 689 | * 重新载入播放器 690 | */ 691 | reload: function() { 692 | this.destroy(); 693 | this.getDOM(this.$elem).getAttr().init(); 694 | this.DOM.wrap.data('WPPlayer', this); 695 | } 696 | }; 697 | 698 | // 列表模板 699 | WPPlayer.template = '
      • {author}{serial}{title}
      • '; 700 | 701 | // 扩展 jQuery 对象 702 | $.fn.WPPlayer = function(options) { 703 | return this.each(function(){ 704 | var $elem = $(this); 705 | typeof options === 'string' 706 | ? ($elem.data('WPPlayer') && $elem.data('WPPlayer')[options]()) 707 | : $elem.data('WPPlayer', new WPPlayer(this, options)); 708 | }); 709 | }; 710 | 711 | return $; 712 | }(jQuery, soundManager); 713 | 714 | jQuery('[data-wp-player="wp-player"]').WPPlayer( wp_player_params ); -------------------------------------------------------------------------------- /src/include/Meting.php: -------------------------------------------------------------------------------- 1 | 8 | * Released under the MIT license 9 | */ 10 | //namespace Metowolf; 11 | class Meting 12 | { 13 | protected $_SITE; 14 | protected $_TEMP; 15 | protected $_RETRY = 3; 16 | protected $_FORMAT = false; 17 | 18 | public function __construct($v = 'netease') 19 | { 20 | $this->site($v); 21 | } 22 | 23 | public function site($v) 24 | { 25 | $this->_SITE=$v; 26 | return $this; 27 | } 28 | 29 | public function format($v = true) 30 | { 31 | $this->_FORMAT=$v; 32 | return $this; 33 | } 34 | 35 | private function curl($API) 36 | { 37 | if (isset($API['encode'])) { 38 | $API=call_user_func_array(array($this,$API['encode']), array($API)); 39 | } 40 | $BASE=$this->curlset(); 41 | $curl=curl_init(); 42 | if ($API['method']=='POST') { 43 | if (is_array($API['body'])) { 44 | $API['body']=http_build_query($API['body']); 45 | } 46 | curl_setopt($curl, CURLOPT_POST, 1); 47 | curl_setopt($curl, CURLOPT_POSTFIELDS, $API['body']); 48 | } elseif ($API['method']=='GET') { 49 | if (isset($API['body'])) { 50 | $API['url']=$API['url'].'?'.http_build_query($API['body']); 51 | } 52 | } 53 | curl_setopt($curl, CURLOPT_HEADER, 0); 54 | curl_setopt($curl, CURLOPT_TIMEOUT, 20); 55 | curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); 56 | curl_setopt($curl, CURLOPT_IPRESOLVE, 1); 57 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 58 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); 59 | curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); 60 | curl_setopt($curl, CURLOPT_URL, $API['url']); 61 | curl_setopt($curl, CURLOPT_COOKIE, $BASE['cookie']); 62 | curl_setopt($curl, CURLOPT_REFERER, $BASE['referer']); 63 | curl_setopt($curl, CURLOPT_USERAGENT, $BASE['useragent']); 64 | for ($i=0;$i<=$this->_RETRY;$i++) { 65 | $data=curl_exec($curl); 66 | $info=curl_getinfo($curl); 67 | $error=curl_errno($curl); 68 | $status=$error?curl_error($curl):''; 69 | if (!$error) { 70 | break; 71 | } 72 | } 73 | curl_close($curl); 74 | if ($error) { 75 | return json_encode( 76 | array( 77 | 'error' => $error, 78 | 'info' => $info, 79 | 'status' => $status, 80 | ) 81 | ); 82 | } 83 | if ($this->_FORMAT&&isset($API['decode'])) { 84 | $data=call_user_func_array(array($this,$API['decode']), array($data)); 85 | } 86 | if ($this->_FORMAT&&isset($API['format'])) { 87 | $data=json_decode($data, 1); 88 | $data=$this->clean($data, $API['format']); 89 | $data=json_encode($data); 90 | } 91 | return $data; 92 | } 93 | 94 | private function pickup($array, $rule) 95 | { 96 | $t=explode('#', $rule); 97 | foreach ($t as $vo) { 98 | if (is_null($array)) { 99 | return null; 100 | } 101 | $array=$array[$vo]; 102 | } 103 | return $array; 104 | } 105 | 106 | private function clean($raw, $rule) 107 | { 108 | if (!empty($rule)) { 109 | $raw=$this->pickup($raw, $rule); 110 | } 111 | if (is_null($raw)) { 112 | $raw=array(); 113 | } elseif (!isset($raw[0])) { 114 | $raw=array($raw); 115 | } 116 | $result=array_map(array($this,'format_'.$this->_SITE), $raw); 117 | return $result; 118 | } 119 | 120 | public function search($keyword, $page=1, $limit=30) 121 | { 122 | switch ($this->_SITE) { 123 | case 'netease': 124 | $API=array( 125 | 'method' => 'POST', 126 | 'url' => 'http://music.163.com/api/linux/forward', 127 | 'body' => array( 128 | 'method' => 'POST', 129 | 'params' => array( 130 | 's' => $keyword, 131 | 'type' => 1, 132 | 'limit' => $limit, 133 | 'total' => 'true', 134 | 'offset' => $page-1, 135 | ), 136 | 'url' => 'http://music.163.com/api/cloudsearch/pc', 137 | ), 138 | 'encode' => 'netease_AESECB', 139 | 'format' => 'result#songs', 140 | ); 141 | break; 142 | case 'tencent': 143 | $API=array( 144 | 'method' => 'GET', 145 | 'url' => 'https://c.y.qq.com/soso/fcgi-bin/search_cp', 146 | 'body' => array( 147 | 'p' => $page, 148 | 'n' => $limit, 149 | 'w' => $keyword, 150 | 'aggr' => 1, 151 | 'lossless' => 1, 152 | 'cr' => 1, 153 | ), 154 | 'decode' => 'jsonp2json', 155 | 'format' => 'data#song#list', 156 | ); 157 | break; 158 | case 'xiami': 159 | $API=array( 160 | 'method' => 'GET', 161 | 'url' => 'http://api.xiami.com/web', 162 | 'body' => array( 163 | 'v' => '2.0', 164 | 'app_key' => '1', 165 | 'key' => $keyword, 166 | 'page' => $page, 167 | 'limit' => $limit, 168 | 'r' => 'search/songs', 169 | ), 170 | 'format' => 'data#songs', 171 | ); 172 | break; 173 | case 'kugou': 174 | $API=array( 175 | 'method' => 'GET', 176 | 'url' => 'http://ioscdn.kugou.com/api/v3/search/song', 177 | 'body' => array( 178 | 'iscorrect' => 1, 179 | 'pagesize' => $limit, 180 | 'plat' => 2, 181 | 'tag' => 1, 182 | 'sver' => 5, 183 | 'showtype' => 10, 184 | 'page' => $page, 185 | 'keyword' => $keyword, 186 | 'version' => 8550 187 | ), 188 | 'format' => 'data#info', 189 | ); 190 | break; 191 | case 'baidu': 192 | $API=array( 193 | 'method' => 'GET', 194 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 195 | 'body' => array( 196 | 'method' => 'baidu.ting.search.merge', 197 | 'isNew' => 1, 198 | 'query' => $keyword, 199 | 'page_size' => $limit, 200 | 'page_no' => $page, 201 | 'type' => 0, 202 | 'format' => 'json', 203 | 'from' => 'ios', 204 | 'channel' => '(null)', 205 | 'cuid' => 'appstore', 206 | 'from' => 'ios', 207 | 'version' => '5.9.5', 208 | ), 209 | 'format' => 'result#song_info#song_list', 210 | ); 211 | break; 212 | } 213 | return $this->curl($API); 214 | } 215 | 216 | public function song($id) 217 | { 218 | switch ($this->_SITE) { 219 | case 'netease': 220 | $API=array( 221 | 'method' => 'POST', 222 | 'url' => 'http://music.163.com/api/linux/forward', 223 | 'body' => array( 224 | 'method' => 'POST', 225 | 'params' => array( 226 | 'c' => '[{"id":'.$id.'}]', 227 | ), 228 | 'url' => 'http://music.163.com/api/v3/song/detail', 229 | ), 230 | 'encode' => 'netease_AESECB', 231 | 'format' => 'songs', 232 | ); 233 | break; 234 | case 'tencent': 235 | $API=array( 236 | 'method' => 'GET', 237 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg', 238 | 'body' => array( 239 | 'songmid' => $id, 240 | 'format' => 'json', 241 | ), 242 | 'decode' => 'tencent_singlesong', 243 | 'format' => 'data', 244 | ); 245 | break; 246 | case 'xiami': 247 | $API=array( 248 | 'method' => 'GET', 249 | 'url' => 'http://api.xiami.com/web', 250 | 'body' => array( 251 | 'v' => '2.0', 252 | 'app_key' => '1', 253 | 'id' => $id, 254 | 'r' => 'song/detail', 255 | ), 256 | 'format' => 'data#song', 257 | ); 258 | break; 259 | case 'kugou': 260 | $API=array( 261 | 'method' => 'POST', 262 | 'url' => 'http://m.kugou.com/app/i/getSongInfo.php?', 263 | 'body' => array( 264 | "cmd" => "playInfo", 265 | "hash" => $id, 266 | "from" => "mkugou", 267 | ), 268 | 'format' => '', 269 | ); 270 | break; 271 | case 'baidu': 272 | $API=array( 273 | 'method' => 'GET', 274 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 275 | 'body' => array( 276 | 'method' => 'baidu.ting.song.play', 277 | 'songid' => $id, 278 | 'format' => 'json', 279 | 'from' => 'ios', 280 | 'channel' => '(null)', 281 | 'cuid' => 'appstore', 282 | 'from' => 'ios', 283 | 'version' => '5.9.5', 284 | ), 285 | 'format' => 'songinfo', 286 | ); 287 | break; 288 | } 289 | return $this->curl($API); 290 | } 291 | 292 | public function album($id) 293 | { 294 | switch ($this->_SITE) { 295 | case 'netease': 296 | $API=array( 297 | 'method' => 'POST', 298 | 'url' => 'http://music.163.com/api/linux/forward', 299 | 'body' => array( 300 | 'method' => 'GET', 301 | 'params' => array( 302 | 'id' => $id, 303 | ), 304 | 'url' => 'http://music.163.com/api/v1/album/'.$id, 305 | ), 306 | 'encode' => 'netease_AESECB', 307 | 'format' => 'songs', 308 | ); 309 | break; 310 | case 'tencent': 311 | $API=array( 312 | 'method' => 'GET', 313 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_album_info_cp.fcg', 314 | 'body' => array( 315 | 'albummid' => $id, 316 | ), 317 | 'format' => 'data#list', 318 | ); 319 | break; 320 | case 'xiami': 321 | $API=array( 322 | 'method' => 'GET', 323 | 'url' => 'http://api.xiami.com/web', 324 | 'body' => array( 325 | 'v' => '2.0', 326 | 'app_key' => '1', 327 | 'id' => $id, 328 | 'r' => 'album/detail', 329 | ), 330 | 'format' => 'data#songs', 331 | ); 332 | break; 333 | case 'kugou': 334 | $API=array( 335 | 'method' => 'GET', 336 | 'url' => 'http://mobilecdn.kugou.com/api/v3/album/song', 337 | 'body' => array( 338 | 'albumid' => $id, 339 | 'plat' => 2, 340 | 'page' => 1, 341 | 'pagesize' => -1, 342 | 'version' => 8550, 343 | ), 344 | 'format' => 'data#info', 345 | ); 346 | break; 347 | case 'baidu': 348 | $API=array( 349 | 'method' => 'GET', 350 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 351 | 'body' => array( 352 | 'method' => 'baidu.ting.album.getAlbumInfo', 353 | 'album_id' => $id, 354 | 'format' => 'json', 355 | 'from' => 'ios', 356 | 'channel' => '(null)', 357 | 'cuid' => 'appstore', 358 | 'from' => 'ios', 359 | 'version' => '5.9.5', 360 | ), 361 | 'format' => 'songlist', 362 | ); 363 | break; 364 | } 365 | return $this->curl($API); 366 | } 367 | 368 | public function artist($id, $limit=50) 369 | { 370 | switch ($this->_SITE) { 371 | case 'netease': 372 | $API=array( 373 | 'method' => 'POST', 374 | 'url' => 'http://music.163.com/api/linux/forward', 375 | 'body' => array( 376 | 'method' => 'GET', 377 | 'params' => array( 378 | 'top' => $limit, 379 | "id" => $id, 380 | "ext" => "true", 381 | ), 382 | 'url' => 'http://music.163.com/api/v1/artist/'.$id, 383 | ), 384 | 'encode' => 'netease_AESECB', 385 | 'format' => 'hotSongs', 386 | ); 387 | break; 388 | case 'tencent': 389 | $API=array( 390 | 'method' => 'GET', 391 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg', 392 | 'body' => array( 393 | 'singermid' => $id, 394 | 'begin' => 0, 395 | 'num' => $limit, 396 | ), 397 | 'format' => 'data#list', 398 | ); 399 | break; 400 | case 'xiami': 401 | $API=array( 402 | 'method' => 'GET', 403 | 'url' => 'http://api.xiami.com/web', 404 | 'body' => array( 405 | 'v' => '2.0', 406 | 'app_key' => '1', 407 | 'id' => $id, 408 | 'limit' => $limit, 409 | 'page' => 1, 410 | 'r' => 'artist/hot-songs', 411 | ), 412 | 'format' => 'data', 413 | ); 414 | break; 415 | case 'kugou': 416 | $API=array( 417 | 'method' => 'GET', 418 | 'url' => 'http://mobilecdn.kugou.com/api/v3/singer/song', 419 | 'body' => array( 420 | 'singerid' => $id, 421 | 'page' => 1, 422 | 'plat' => 0, 423 | 'pagesize' => $limit, 424 | 'version' => 8400, 425 | ), 426 | 'format' => 'data#info', 427 | ); 428 | break; 429 | case 'baidu': 430 | $API=array( 431 | 'method' => 'GET', 432 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 433 | 'body' => array( 434 | 'method' => 'baidu.ting.artist.getSongList', 435 | 'tinguid' => $id, 436 | 'limits' => $limit, 437 | 'format' => 'json', 438 | 'from' => 'ios', 439 | 'channel' => '(null)', 440 | 'cuid' => 'appstore', 441 | 'from' => 'ios', 442 | 'version' => '5.9.5', 443 | ), 444 | 'format' => 'songlist', 445 | ); 446 | break; 447 | } 448 | return $this->curl($API); 449 | } 450 | 451 | public function playlist($id) 452 | { 453 | switch ($this->_SITE) { 454 | case 'netease': 455 | $API=array( 456 | 'method' => 'POST', 457 | 'url' => 'http://music.163.com/api/linux/forward', 458 | 'body' => array( 459 | 'method' => 'POST', 460 | 'params' => array( 461 | 'id' => $id, 462 | "n" => 1000, 463 | ), 464 | 'url' => 'http://music.163.com/api/v3/playlist/detail', 465 | ), 466 | 'encode' => 'netease_AESECB', 467 | 'format' => 'playlist#tracks', 468 | ); 469 | break; 470 | case 'tencent': 471 | $API=array( 472 | 'method' => 'GET', 473 | 'url' => 'https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg', 474 | 'body' => array( 475 | 'disstid' => $id, 476 | 'utf8' => 1, 477 | 'type' => 1, 478 | ), 479 | 'decode' => 'jsonp2json', 480 | 'format' => 'cdlist#0#songlist', 481 | ); 482 | break; 483 | case 'xiami': 484 | $API=array( 485 | 'method' => 'GET', 486 | 'url' => 'http://api.xiami.com/web', 487 | 'body' => array( 488 | 'v' => '2.0', 489 | 'app_key' => '1', 490 | 'id' => $id, 491 | 'r' => 'collect/detail', 492 | ), 493 | 'format' => 'data#songs', 494 | ); 495 | break; 496 | case 'kugou': 497 | $API=array( 498 | 'method' => 'GET', 499 | 'url' => 'http://mobilecdn.kugou.com/api/v3/special/song', 500 | 'body' => array( 501 | 'specialid' => $id, 502 | 'page' => 1, 503 | 'plat' => 2, 504 | 'pagesize' => -1, 505 | 'version' => 8400, 506 | ), 507 | 'format' => 'data#info', 508 | ); 509 | break; 510 | case 'baidu': 511 | $API=array( 512 | 'method' => 'GET', 513 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 514 | 'body' => array( 515 | 'method' => 'baidu.ting.diy.gedanInfo', 516 | 'listid' => $id, 517 | 'format' => 'json', 518 | 'from' => 'ios', 519 | 'channel' => '(null)', 520 | 'cuid' => 'appstore', 521 | 'from' => 'ios', 522 | 'version' => '5.9.5', 523 | ), 524 | 'format' => 'content', 525 | ); 526 | break; 527 | } 528 | return $this->curl($API); 529 | } 530 | 531 | public function url($id, $br=320) 532 | { 533 | switch ($this->_SITE) { 534 | case 'netease': 535 | $API=array( 536 | 'method' => 'POST', 537 | 'url' => 'http://music.163.com/api/linux/forward', 538 | 'body' => array( 539 | 'method' => 'POST', 540 | 'params' => array( 541 | 'ids' => array($id), 542 | 'br' => $br*1000, 543 | ), 544 | 'url' => 'http://music.163.com/api/song/enhance/player/url', 545 | ), 546 | 'encode' => 'netease_AESECB', 547 | 'decode' => 'netease_url', 548 | ); 549 | break; 550 | case 'tencent': 551 | $API=array( 552 | 'method' => 'GET', 553 | 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg', 554 | 'body' => array( 555 | 'songmid' => $id, 556 | 'format' => 'json', 557 | ), 558 | 'decode' => 'tencent_url', 559 | ); 560 | break; 561 | case 'xiami': 562 | $API=array( 563 | 'method' => 'GET', 564 | 'url' => 'http://www.xiami.com/song/gethqsong/sid/'.$id, 565 | 'body' => array( 566 | 'v' => '2.0', 567 | 'app_key' => '1', 568 | 'id' => $id, 569 | 'r' => 'song/detail', 570 | ), 571 | 'decode' => 'xiami_url', 572 | ); 573 | break; 574 | case 'kugou': 575 | $API=array( 576 | 'method' => 'POST', 577 | 'url' => 'http://media.store.kugou.com/v1/get_res_privilege', 578 | 'body' => json_encode(array( 579 | "relate" => 1, 580 | "userid" => 0, 581 | "vip" => 0, 582 | "appid" => 1005, 583 | "token" => "", 584 | "behavior" => "download", 585 | "clientver" => "8493", 586 | "resource" => array(array( 587 | "id" => 0, 588 | "type" => "audio", 589 | "hash" => $id, 590 | ))) 591 | ), 592 | 'decode' => 'kugou_url', 593 | ); 594 | break; 595 | case 'baidu': 596 | $API=array( 597 | 'method' => 'GET', 598 | 'url' => 'http://music.baidu.com/data/music/fmlink', 599 | 'body' => array( 600 | 'songIds' => $id, 601 | 'rate' => $br, 602 | 'type' => 'mp3', 603 | ), 604 | 'decode' => 'baidu_url', 605 | ); 606 | break; 607 | } 608 | $this->_temp['br']=$br; 609 | return $this->curl($API); 610 | } 611 | 612 | public function lyric($id) 613 | { 614 | switch ($this->_SITE) { 615 | case 'netease': 616 | $API=array( 617 | 'method' => 'POST', 618 | 'url' => 'http://music.163.com/api/linux/forward', 619 | 'body' => array( 620 | 'method' => 'POST', 621 | 'params' => array( 622 | 'id' => $id, 623 | 'os' => 'linux', 624 | 'lv' => -1, 625 | 'kv' => -1, 626 | 'tv' => -1, 627 | ), 628 | 'url' => 'http://music.163.com/api/song/lyric', 629 | ), 630 | 'encode' => 'netease_AESECB', 631 | 'decode' => 'netease_lyric', 632 | ); 633 | break; 634 | case 'tencent': 635 | $API=array( 636 | 'method' => 'GET', 637 | 'url' => 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg', 638 | 'body' => array( 639 | 'songmid' => $id, 640 | 'g_tk' => 5381, 641 | ), 642 | 'decode' => 'tencent_lyric', 643 | ); 644 | break; 645 | case 'xiami': 646 | $API=array( 647 | 'method' => 'GET', 648 | 'url' => 'http://api.xiami.com/web', 649 | 'body' => array( 650 | 'v' => '2.0', 651 | 'app_key' => '1', 652 | 'id' => $id, 653 | 'r' => 'song/detail', 654 | ), 655 | 'decode' => 'xiami_lyric', 656 | ); 657 | break; 658 | case 'kugou': 659 | $API=array( 660 | 'method' => 'GET', 661 | 'url' => 'http://m.kugou.com/app/i/krc.php', 662 | 'body' => array( 663 | 'keyword' => '%20-%20', 664 | 'timelength' => 1000000, 665 | 'cmd' => 100, 666 | 'hash' => $id, 667 | ), 668 | 'decode' => 'kugou_lyric' 669 | ); 670 | break; 671 | case 'baidu': 672 | $API=array( 673 | 'method' => 'GET', 674 | 'url' => 'http://tingapi.ting.baidu.com/v1/restserver/ting', 675 | 'body' => array( 676 | 'method' => 'baidu.ting.song.lry', 677 | 'songid' => $id, 678 | 'format' => 'json', 679 | 'from' => 'ios', 680 | 'channel' => '(null)', 681 | 'cuid' => 'appstore', 682 | 'from' => 'ios', 683 | 'version' => '5.9.5', 684 | ), 685 | 'decode' => 'baidu_lyric' 686 | ); 687 | break; 688 | } 689 | return $this->curl($API); 690 | } 691 | 692 | public function pic($id, $size=300) 693 | { 694 | switch ($this->_SITE) { 695 | case 'netease': 696 | $url='https://p3.music.126.net/'.$this->netease_pickey($id).'/'.$id.'.jpg?param='.$size.'z'.$size.'&quality=100'; 697 | break; 698 | case 'tencent': 699 | $url='https://y.gtimg.cn/music/photo_new/T002R'.$size.'x'.$size.'M000'.$id.'.jpg?max_age=2592000'; 700 | break; 701 | case 'xiami': 702 | $format=$this->_FORMAT; 703 | $data=$this->format(false)->song($id); 704 | $this->format($format); 705 | $data=json_decode($data, 1); 706 | $url=$data['data']['song']['logo']; 707 | $url=str_replace(array('_1.','http:','img.'), array('.','https:','pic.'), $url).'@'.$size.'h_'.$size.'w_100q_1c.jpg'; 708 | break; 709 | case 'kugou': 710 | $format=$this->_FORMAT; 711 | $data=$this->format(false)->song($id); 712 | $this->format($format); 713 | $data=json_decode($data, 1); 714 | $url=$data['imgUrl']; 715 | $url=str_replace('{size}', '400', $url); 716 | break; 717 | case 'baidu': 718 | $format=$this->_FORMAT; 719 | $data=$this->format(false)->song($id); 720 | $this->format($format); 721 | $data=json_decode($data, 1); 722 | $url=$data['songinfo']['pic_big'] ? $data['songinfo']['pic_big'] : $data['songinfo']['pic_small']; 723 | break; 724 | } 725 | return json_encode(array('url'=>$url)); 726 | } 727 | 728 | private function curlset() 729 | { 730 | $BASE=array( 731 | 'netease'=>array( 732 | 'referer' => 'https://music.163.com/', 733 | 'cookie' => 'os=linux; appver=1.0.0.1026; osver=Ubuntu%2016.10; MUSIC_U=78d411095f4b022667bc8ec49e9a44cca088df057d987f5feaf066d37458e41c4a7d9447977352cf27ea9fee03f6ec4441049cea1c6bb9b6; __remember_me=true', 734 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 735 | ), 736 | 'tencent'=>array( 737 | 'referer' => 'http://y.qq.com/portal/player.html', 738 | 'cookie' => 'qqmusic_uin=12345678; qqmusic_key=12345678; qqmusic_fromtag=30; ts_last=y.qq.com/portal/player.html;', 739 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 740 | ), 741 | 'xiami'=>array( 742 | 'referer' => 'http://h.xiami.com/', 743 | 'cookie' => 'user_from=2;XMPLAYER_addSongsToggler=0;XMPLAYER_isOpen=0;_xiamitoken=123456789;', 744 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 745 | ), 746 | 'kugou'=>array( 747 | 'referer' => 'http://www.kugou.com/webkugouplayer/flash/webKugou.swf', 748 | 'cookie' => '_WCMID=123456789', 749 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 750 | ), 751 | 'baidu'=>array( 752 | 'referer' => 'http://ting.baidu.com/', 753 | 'cookie' => 'BAIDUID=123456789', 754 | 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', 755 | ), 756 | ); 757 | return $BASE[$this->_SITE]; 758 | } 759 | 760 | /** 761 | * 乱七八糟的函数,加密解密... 762 | * 正在努力重构这些代码 TAT 763 | */ 764 | private function netease_AESECB($API) 765 | { 766 | $KEY='7246674226682325323F5E6544673A51'; 767 | $body=json_encode($API['body']); 768 | if (function_exists('openssl_encrypt')) { 769 | $body=openssl_encrypt($body, 'aes-128-ecb', pack('H*', $KEY)); 770 | } else { 771 | $PAD=16-(strlen($body)%16); 772 | $body=base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, hex2bin($KEY), $body.str_repeat(chr($PAD), $PAD), MCRYPT_MODE_ECB)); 773 | } 774 | $body=strtoupper(bin2hex(base64_decode($body))); 775 | 776 | $API['body']=array( 777 | 'eparams'=>$body, 778 | ); 779 | return $API; 780 | } 781 | private function jsonp2json($jsonp) 782 | { 783 | if ($jsonp[0] !== '[' && $jsonp[0] !== '{') { 784 | $jsonp = substr($jsonp, strpos($jsonp, '(')); 785 | } 786 | return trim($jsonp, '();'); 787 | } 788 | private function tencent_singlesong($result) 789 | { 790 | $result=json_decode($result, 1); 791 | $data=$result['data'][0]; 792 | $t=array( 793 | 'songmid' => $data['mid'], 794 | 'songname' => $data['name'], 795 | 'albummid' => $data['album']['mid'], 796 | ); 797 | foreach ($t as $key=>$vo) { 798 | $result['data'][0][$key]=$vo; 799 | } 800 | return json_encode($result); 801 | } 802 | private function netease_pickey($id) 803 | { 804 | $magic=str_split('3go8&$8*3*3h0k(2)2'); 805 | $song_id=str_split($id); 806 | for ($i=0;$i str_replace('http://', 'https://', $data['data'][0]['uf']['url']), 823 | 'br' =>$data['data'][0]['uf']['br']/1000, 824 | ); 825 | } 826 | else{ 827 | $url=array( 828 | 'url' => str_replace('http://', 'https://', $data['data'][0]['url']), 829 | 'br' => $data['data'][0]['br']/1000, 830 | ); 831 | } 832 | return json_encode($url); 833 | } 834 | private function tencent_url($result) 835 | { 836 | $data=json_decode($result, 1); 837 | $GUID=mt_rand()%10000000000; 838 | $API=array( 839 | 'method' => 'GET', 840 | 'url' => 'https://c.y.qq.com/base/fcgi-bin/fcg_musicexpress.fcg', 841 | 'body' => array( 842 | 'json' => 3, 843 | 'guid' => $GUID, 844 | ), 845 | 'decode' => 'jsonp2json', 846 | ); 847 | $KEY=json_decode($this->curl($API), 1); 848 | $KEY=$KEY['key']; 849 | 850 | $type=array( 851 | 'size_320mp3' => array(320,'M800','mp3'), 852 | 'size_128mp3' => array(128,'M500','mp3'), 853 | 'size_96aac' => array(96 ,'C400','m4a'), 854 | 'size_48aac' => array(48 ,'C200','m4a'), 855 | ); 856 | foreach ($type as $key=>$vo) { 857 | if ($data['data'][0]['file'][$key]&&$vo[0]<=$this->_temp['br']) { 858 | $url=array( 859 | 'url' => 'http://dl.stream.qqmusic.qq.com/'.$vo[1].$data['data'][0]['file']['media_mid'].'.'.$vo[2].'?vkey='.$KEY.'&guid='.$GUID.'&uid=0&fromtag=30', 860 | 'br' => $vo[0], 861 | ); 862 | break; 863 | } 864 | } 865 | return json_encode($url); 866 | } 867 | private function xiami_url($result) 868 | { 869 | $data=json_decode($result, 1); 870 | if(isset($data['location'])) { 871 | $location = $data['location']; 872 | $num = (int)$location[0]; 873 | $str = substr($location, 1); 874 | $len = floor(strlen($str)/$num); 875 | $sub = strlen($str) % $num; 876 | $qrc = array(); 877 | $tmp = 0; 878 | $urlt = ''; 879 | for(;$tmp<$sub;$tmp++){ 880 | $qrc[$tmp] = substr($str, $tmp*($len+1), $len+1); 881 | } 882 | for(;$tmp<$num;$tmp++){ 883 | $qrc[$tmp] = substr($str, $len*$tmp+$sub, $len); 884 | } 885 | for($tmpa=0;$tmpa<$len+1;$tmpa++){ 886 | for($tmpb=0;$tmpb<$num;$tmpb++){ 887 | if(isset($qrc[$tmpb][$tmpa])) { $urlt.=$qrc[$tmpb][$tmpa]; 888 | } 889 | } 890 | } 891 | for($tmp=0;$tmp<$sub;$tmp++){ 892 | //if(isset($qrc[$tmp][$len])) (string)$urlt.=(string)$qrc[$tmp][$len]; 893 | } 894 | $urlt=str_replace('^', '0', urldecode($urlt)); 895 | $url=array( 896 | 'url' => urldecode($urlt), 897 | 'br' => 320, 898 | ); 899 | } 900 | else{ 901 | $url=array( 902 | 'url' => "error",//str_replace('http:', 'https:', $data['data']['song']['listen_file']), 903 | 'br' => 0, 904 | ); 905 | } 906 | return json_encode($url); 907 | } 908 | private function kugou_url($result) 909 | { 910 | $data=json_decode($result, 1); 911 | 912 | $max=0; 913 | $url=array(); 914 | foreach ($data['data'][0]['relate_goods'] as $vo) { 915 | if ($vo['info']['bitrate']<=$this->_temp['br']&&$vo['info']['bitrate']>$max) { 916 | $API=array( 917 | 'method' => 'GET', 918 | 'url' => 'http://trackercdn.kugou.com/i/v2/', 919 | 'body' => array( 920 | 'hash' => $vo['hash'], 921 | 'key' => md5($vo['hash'].'kgcloudv2'), 922 | 'pid' => 1, 923 | 'behavior' => 'play', 924 | 'cmd' => '23', 925 | 'version' => 8400, 926 | ), 927 | ); 928 | $t=json_decode($this->curl($API), 1); 929 | if (isset($t['url'])) { 930 | $max=$t['bitRate']/1000; 931 | $url=array( 932 | 'url' => $t['url'], 933 | 'br' => $t['bitRate']/1000, 934 | ); 935 | } 936 | } 937 | } 938 | return json_encode($url); 939 | } 940 | private function baidu_url($result) 941 | { 942 | $data=json_decode($result, 1); 943 | $url=array( 944 | 'url' => $data['data']['songList'][0]['songLink'], 945 | 'br' => $data['data']['songList'][0]['rate'], 946 | ); 947 | $url['url']=str_replace('http://yinyueshiting.baidu.com', 'https://gss0.bdstatic.com/y0s1hSulBw92lNKgpU_Z2jR7b2w6buu', $url['url']); 948 | return json_encode($url); 949 | } 950 | /** 951 | * 歌词处理模块 952 | * 用于规范化歌词输出 953 | */ 954 | private function netease_lyric($result) 955 | { 956 | if (!$this->_FORMAT) { 957 | return $result; 958 | } 959 | $result=json_decode($result, 1); 960 | $data=array( 961 | 'lyric' => (@$result['lrc']['lyric'])? @$result['lrc']['lyric'] : '', 962 | 'tlyric' => (@$result['tlyric']['lyric']) ? @$result['tlyric']['lyric'] : '', 963 | ); 964 | return json_encode($data); 965 | } 966 | private function tencent_lyric($result) 967 | { 968 | $result=$this->jsonp2json($result); 969 | if (!$this->_FORMAT) { 970 | return $result; 971 | } 972 | $result=json_decode($result, 1); 973 | $data=array( 974 | 'lyric' => isset($result['lyric'])?base64_decode($result['lyric']):'', 975 | 'tlyric' => isset($result['trans'])?base64_decode($result['trans']):'', 976 | ); 977 | return json_encode($data); 978 | } 979 | private function xiami_lyric($result) 980 | { 981 | if (!$this->_FORMAT) { 982 | return $result; 983 | } 984 | $result=json_decode($result, 1); 985 | $API=array('method'=>'GET','url'=>$result['data']['song']['lyric']); 986 | $data=$this->curl($API); 987 | $data=preg_replace('/<[^>]+>/', '', $data); 988 | $arr=array( 989 | 'lyric' => $data, 990 | ); 991 | return json_encode($arr); 992 | } 993 | private function kugou_lyric($result) 994 | { 995 | if (!$this->_FORMAT) { 996 | return $result; 997 | } 998 | $arr=array( 999 | 'lyric' => $result, 1000 | ); 1001 | return json_encode($arr); 1002 | } 1003 | private function baidu_lyric($result) 1004 | { 1005 | if (!$this->_FORMAT) { 1006 | return $result; 1007 | } 1008 | $result=json_decode($result, 1); 1009 | $data=array( 1010 | 'lyric' => (@$result['lrcContent']) ? @$result['lrcContent'] : '', 1011 | ); 1012 | return json_encode($data); 1013 | } 1014 | /** 1015 | * Format - 规范化函数 1016 | * 用于统一返回的参数,可用 ->format() 一次性开关开启 1017 | */ 1018 | private function format_netease($data) 1019 | { 1020 | $result=array( 1021 | 'id' => $data['id'], 1022 | 'name' => $data['name'], 1023 | 'artist' => array(), 1024 | 'pic_id' => (@$data['al']['pic_str']) ? @$data['al']['pic_str'] : $data['al']['pic'], 1025 | 'url_id' => $data['id'], 1026 | 'lyric_id' => $data['id'], 1027 | 'source' => 'netease', 1028 | ); 1029 | if (isset($data['al']['picUrl'])) { 1030 | preg_match('/\/(\d+)\./', $data['al']['picUrl'], $match); 1031 | $result['pic_id']=$match[1]; 1032 | } 1033 | foreach ($data['ar'] as $vo) { 1034 | $result['artist'][]=$vo['name']; 1035 | } 1036 | return $result; 1037 | } 1038 | private function format_tencent($data) 1039 | { 1040 | if (isset($data['musicData'])) { 1041 | $data=$data['musicData']; 1042 | } 1043 | $result=array( 1044 | 'id' => $data['songmid'], 1045 | 'name' => $data['songname'], 1046 | 'artist' => array(), 1047 | 'pic_id' => $data['albummid'], 1048 | 'url_id' => $data['songmid'], 1049 | 'lyric_id' => $data['songmid'], 1050 | 'source' => 'tencent', 1051 | ); 1052 | foreach ($data['singer'] as $vo) { 1053 | $result['artist'][]=$vo['name']; 1054 | } 1055 | return $result; 1056 | } 1057 | private function format_xiami($data) 1058 | { 1059 | $result=array( 1060 | 'id' => $data['song_id'], 1061 | 'name' => $data['song_name'], 1062 | 'artist' => explode(';', (@$data['singers']) ? @$data['singers'] : $data['artist_name']), 1063 | 'pic_id' => $data['song_id'], 1064 | 'url_id' => $data['song_id'], 1065 | 'lyric_id' => $data['song_id'], 1066 | 'source' => 'xiami', 1067 | ); 1068 | return $result; 1069 | } 1070 | private function format_kugou($data) 1071 | { 1072 | $result=array( 1073 | 'id' => $data['hash'], 1074 | 'name' => (@$data['filename']) ? @$data['filename'] :$data['fileName'], 1075 | 'artist' => array(), 1076 | 'url_id' => $data['hash'], 1077 | 'pic_id' => $data['hash'], 1078 | 'lyric_id' => $data['hash'], 1079 | 'source' => 'kugou', 1080 | ); 1081 | list($result['artist'], $result['name'])=explode(' - ', $result['name'], 2); 1082 | $result['artist']=explode('、', $result['artist']); 1083 | return $result; 1084 | } 1085 | private function format_baidu($data) 1086 | { 1087 | $result=array( 1088 | 'id' => $data['song_id'], 1089 | 'name' => $data['title'], 1090 | 'artist' => explode(',', $data['author']), 1091 | 'pic_id' => $data['song_id'], 1092 | 'url_id' => $data['song_id'], 1093 | 'lyric_id' => $data['song_id'], 1094 | 'source' => 'baidu', 1095 | ); 1096 | return $result; 1097 | } 1098 | } 1099 | -------------------------------------------------------------------------------- /src/include/metaboxes.php: -------------------------------------------------------------------------------- 1 | array( 28 | 'name' => 'wp_player_music_type', 29 | 'type' => 'select', 30 | 'options' => array( 31 | 'netease' => '网易音乐', 32 | 'xiami' => '虾米音乐', 33 | 'tencent' => 'QQ 音乐', 34 | 'baidu' => '百度音乐' 35 | ), 36 | 'output' => false 37 | ), 38 | 'mp3_xiami_type' => array( 39 | 'name' => 'mp3_xiami_type', 40 | 'type' => 'select', 41 | 'options' => array( 42 | 'song' => '歌曲页面', 43 | 'album' => '专辑页面', 44 | 'artist' => '歌手页面', 45 | 'collect' => '歌单页面' 46 | ), 47 | 'output' => false 48 | ), 49 | 'wp_player_lyric_open' => array( 50 | 'name' => 'wp_player_lyric_open', 51 | 'type' => 'select', 52 | 'options' => array( 53 | 'close' => '关闭歌词', 54 | 'open' => '开启歌词' 55 | ), 56 | 'output' => false 57 | ), 58 | 'mp3_xiami' => array( 59 | 'name' => 'mp3_xiami', 60 | 'type' => 'text', 61 | 'description' => '即可填音乐写ID,也可填写音乐网址 http://......', 62 | 'button' => '获取音乐ID', 63 | 'output' => false 64 | ) 65 | ); 66 | } else { 67 | $arr1 = array(); 68 | } 69 | 70 | $arr2 = array( 71 | 'mp3_title' => array( 72 | 'name' => 'mp3_title', 73 | 'type' => 'textarea', 74 | 'title' => '歌曲名', 75 | 'description' => '请填写歌曲名,一行一个歌曲名,用于列表展示显示。', 76 | 'output' => true 77 | ), 78 | 'mp3_author' => array( 79 | 'name' => 'mp3_author', 80 | 'type' => 'textarea', 81 | 'title' => '歌手名', 82 | 'description' => '请填写歌手名,一行一个歌手名,请与上面的歌曲名一一对应', 83 | 'output' => true 84 | ), 85 | 'mp3_address' => array( 86 | 'name' => 'mp3_address', 87 | 'type' => 'upload', 88 | 'title' => '歌曲地址', 89 | "description" => '请填写歌曲地址,可以上传歌曲,也可以用链接地址(请记得带上http://),一行一个歌曲地址,请与上面的歌曲名一一对应。', 90 | 'output' => true 91 | ), 92 | 'mp3_thumb' => array( 93 | 'name' => 'mp3_thumb', 94 | 'type' => 'upload', 95 | 'title' => '歌曲封面', 96 | "description" => '上传封面,可以为空,WP-Player 将使用默认图,上传图片时记得与歌曲名一一对应,如果此歌曲默认封面,则此行留空。', 97 | 'output' => true 98 | ) 99 | ); 100 | $meta_boxes = $val ? $arr1 : $arr2; 101 | 102 | if ( $apply ){ 103 | $meta_boxes = array(); 104 | $meta_boxes = array_merge( $arr1, $arr2 ); 105 | } 106 | 107 | return apply_filters( 'wp_player_meta_boxes', $meta_boxes ); 108 | } 109 | 110 | 111 | /** 112 | * get meta boxes 113 | */ 114 | function get_wp_player_metaBox( $val = true ){ 115 | global $post; 116 | $meta_boxes = wp_player_meta_boxes($val); 117 | foreach ( $meta_boxes as $meta ){ 118 | $value = get_post_meta( $post->ID, $meta['name'], true ); 119 | switch ($meta['type']) { 120 | case 'text': wp_player_get_meta_text_input( $meta, $value ); break; 121 | case 'select': wp_player_get_meta_select( $meta, $value ); break; 122 | case 'textarea': wp_player_get_meta_textarea( $meta, $value ); break; 123 | case 'upload': wp_player_get_meta_upload( $meta, $value ); break; 124 | case 'button': wp_player_get_meta_button( $meta, $value ); break; 125 | } 126 | } 127 | } 128 | 129 | /** 130 | * Displays meta boxes on the Write Post panel. Loops 131 | * through each meta box in the $meta_boxes variable. 132 | * Gets array from solostream_post_meta_boxes(). 133 | */ 134 | 135 | function wpPlayer_post_meta_boxes() { 136 | global $post; ?> 137 |
        138 | 142 |
        143 |
        144 |
        您的站点当前不支持此功能
        '; 149 | } 150 | ?>
        151 |
        152 |
        153 |
        154 | 155 |

        '.$title.'

        ' : "\n"; 168 | $html .= ''; 169 | $html .= ''; 170 | if ( $button ){ 171 | $html .= "\n".''; 172 | $html .= "\n".'使用说明'; 173 | } 174 | $html .= $output ? '

        '."\n" : "\n"; 175 | 176 | echo $html; 177 | } 178 | 179 | /** 180 | * Outputs a select box with arguments from the 181 | * parameters. Used for both the post/page meta boxes. 182 | */ 183 | function wp_player_get_meta_select( $args = array(), $value = false ) { 184 | 185 | extract( $args ); 186 | 187 | $html .= $output ? '

        '.$title.'

        ' : "\n"; 188 | $html .= ''; 194 | $html .= $output ? '

        '."\n" : "\n"; 195 | 196 | echo $html; 197 | } 198 | 199 | /** 200 | * Outputs a textarea box with arguments from the 201 | * parameters. Used for both the post/page meta boxes. 202 | */ 203 | function wp_player_get_meta_textarea( $args = array(), $value = false ) { 204 | 205 | extract( $args ); 206 | 207 | $html .= '

        '.$title.'

        '; 208 | $html .= ''."\n"; 209 | $html .= '

        '.$description.'

        '; 210 | $html .= ''; 211 | $html .= '
        '; 212 | 213 | echo $html; 214 | } 215 | 216 | /** 217 | * Outputs a Upload box with arguments from the 218 | * parameters. Used for both the post/page meta boxes. 219 | */ 220 | function wp_player_get_meta_upload( $args = array(), $value = false ) { 221 | 222 | extract( $args ); 223 | 224 | $html .= '

        '.$title.'

        '; 225 | $html .= ''."\n"; 226 | $html .= ''; 227 | $html .= '

        '.$description.'

        '; 228 | $html .= ''; 229 | $html .= '
        '."\n"; 230 | 231 | echo $html; 232 | } 233 | 234 | /** 235 | * Loops through each meta box's set of variables. 236 | * Saves them to the database as custom fields. 237 | */ 238 | 239 | function wp_player_save_meta_data( $post_id ) { 240 | global $post; 241 | 242 | $meta_boxes = wp_player_meta_boxes( true, true ); 243 | 244 | foreach ( $meta_boxes as $meta_box ){ 245 | 246 | if ( 'page' == $_POST['post_type'] && !current_user_can( 'edit_page', $post_id ) ){ 247 | return $post_id; 248 | } 249 | 250 | if ( 'post' == $_POST['post_type'] && !current_user_can( 'edit_post', $post_id ) ){ 251 | return $post_id; 252 | } 253 | 254 | if ( !wp_verify_nonce( $_POST[$meta_box['name'] . '_noncename'], plugin_basename( __FILE__ ) ) ){ 255 | return $post_id; 256 | } 257 | 258 | $data = stripslashes( $_POST[$meta_box['name']] ); 259 | 260 | if ( get_post_meta( $post_id, $meta_box['name'] ) == '' ){ 261 | add_post_meta( $post_id, $meta_box['name'], $data, true ); 262 | } elseif ( $data != get_post_meta( $post_id, $meta_box['name'], true ) ){ 263 | update_post_meta( $post_id, $meta_box['name'], $data ); 264 | }elseif ( $data == '' ){ 265 | delete_post_meta( $post_id, $meta_box['name'], get_post_meta( $post_id, $meta_box['name'], true ) ); 266 | } 267 | 268 | } 269 | 270 | } 271 | ?> -------------------------------------------------------------------------------- /src/include/player.php: -------------------------------------------------------------------------------- 1 | options = get_option( 'wp_player_options' ); 32 | $this->base_dir = WP_PLUGIN_URL.'/'. dirname( plugin_basename( dirname( __FILE__ ) ) ).'/'; 33 | $this->admin_dir = site_url( '/wp-admin/options-general.php?page=player.php' ); 34 | 35 | $this->netease = new Meting('netease'); 36 | $this->xiami = new Meting('xiami'); 37 | $this->tencent = new Meting('tencent'); 38 | $this->baidu = new Meting('baidu'); 39 | 40 | $this->netease->format(true); 41 | $this->xiami->format(true); 42 | $this->tencent->format(true); 43 | $this->baidu->format(true); 44 | } 45 | 46 | /** 47 | * @desc get actions 48 | * @param string $source 49 | * @return Meting 50 | */ 51 | private function get_api($source = 'netease') { 52 | switch ( $source ) { 53 | case 'netease': $API = $this->netease; break; 54 | case 'xiami': $API = $this->xiami; break; 55 | case 'tencent': $API = $this->tencent; break; 56 | case 'baidu': $API = $this->baidu; break; 57 | default: $this->netease; 58 | } 59 | return $API; 60 | } 61 | 62 | /** @desc Get Netease Song 63 | * 64 | * @Author: METO 65 | * @GitHub: https://github.com/metowolf 66 | * 67 | * @name: Meting 68 | * @URL: https://github.com/metowolf/Meting 69 | **/ 70 | public function wp_player_actions() { 71 | $id = $_POST['id']; 72 | $type = $_POST['type']; 73 | $nonce = $_SERVER['HTTP_NONCE']; 74 | $source = $_POST['source']; 75 | 76 | if ( !wp_verify_nonce($nonce, "wp-player") || !function_exists('curl_init')) { 77 | $JSON = array('status' => false, 'message' => '非法请求', data => array()); 78 | } else { 79 | $API = $this->get_api($source); 80 | switch ( $type ) { 81 | case 'song': $data = $API->song($id); break; 82 | case 'album': $data = $API->album($id); break; 83 | case 'artist': $data = $API->artist($id); break; 84 | case 'collect': $data = $API->playlist($id); break; 85 | default: $data = $API->song($id); 86 | } 87 | $JSON = array( 88 | 'status' => ($data && count($data) > 0) ? true : false, 89 | 'message' => ($data && count($data) > 0) ? '获取成功' : '获取失败', 90 | 'data' => array( 91 | 'list' => ($data && count($data) > 0) ? json_decode($data) : array() 92 | ) 93 | ); 94 | } 95 | 96 | header('Content-type: application/json'); 97 | echo json_encode($JSON); 98 | die(); 99 | } 100 | 101 | /** 102 | * @name Get Song Info 103 | */ 104 | public function wp_player_get_info() { 105 | $id = $_POST['id']; 106 | $pic_id = $_POST['pic_id']; 107 | $url_id = $_POST['url_id']; 108 | $lyric_id = $_POST['lyric_id']; 109 | $nonce = $_SERVER['HTTP_NONCE']; 110 | $source = $_POST['source']; 111 | 112 | if ( !wp_verify_nonce($nonce, "wp-player") || !function_exists('curl_init')) { 113 | $JSON = array('status' => false, 'message' => '非法请求', data => array()); 114 | } else { 115 | $API = $this->get_api($source); 116 | $JSON = array( 117 | 'status' => true, 118 | 'message' => '获取成功', 119 | 'data' => array( 120 | 'id' => $id, 121 | 'pic' => json_decode($API->pic($pic_id, 180)), 122 | 'url' => json_decode($API->url($url_id, 120)), 123 | 'lyric' => json_decode($API->lyric($lyric_id)) 124 | ) 125 | ); 126 | } 127 | 128 | header('Content-type: application/json'); 129 | echo json_encode($JSON); 130 | die(); 131 | } 132 | 133 | /** 134 | * @desc Register Menu 135 | */ 136 | public function options_menu(){ 137 | add_options_page( 'WP-Player 设置', 'WP-Player 设置', 'manage_options', basename( __FILE__ ), array( $this, 'printAdminPage' ) ); 138 | add_action( 'admin_init', array( $this, 'wp_player_settings' )); 139 | } 140 | 141 | /** 142 | * @desc Register WP-Player Setting 143 | */ 144 | public function wp_player_settings() { 145 | register_setting( 'wp_player_settings_group', 'wp_player_options' ); 146 | } 147 | 148 | /** 149 | * @desc Register setting submit 150 | */ 151 | public function wp_player_add_link( $action_links, $plugin_file, $plugin_data, $context ){ 152 | if (strip_tags($plugin_data['Title']) == 'WP-Player') { 153 | $wp_player_links = '设定'; 154 | array_unshift( $action_links, $wp_player_links ); 155 | } 156 | return $action_links; 157 | } 158 | 159 | /** 160 | * @desc Include scripts 161 | */ 162 | public function wp_player_scripts(){ 163 | global $WP_PLAYER_VERSION; 164 | $options = $this->options; 165 | wp_enqueue_style( 'wp-player', $this->base_dir . 'assets/css/wp-player.css', array(), $WP_PLAYER_VERSION, 'screen' ); 166 | if( is_array( $options ) && $options['jQuery'] == 'true' ){ 167 | wp_enqueue_script( 'jquery' ); 168 | } 169 | wp_enqueue_script( 'wp-player-jplayer', $this->base_dir . 'assets/js/libs/soundmanager/soundmanager2.js', array(), $WP_PLAYER_VERSION, true ); 170 | wp_enqueue_script( 'wp-player', $this->base_dir . 'assets/js/wp-player.js', array(), $WP_PLAYER_VERSION, true ); 171 | 172 | wp_localize_script( 'wp-player', 'wp_player_params', 173 | array( 174 | 'swf' => $this->base_dir.'assets/js/libs/soundmanager/', 175 | 'img' => $this->base_dir.'assets/images/default.png', 176 | 'url' => admin_url().'admin-ajax.php', 177 | 'nonce' => wp_create_nonce('wp-player'), 178 | 'single' => ( is_single() || is_page() ) ? 'true' : 'false' 179 | )); 180 | } 181 | 182 | /** 183 | * @desc add Admin WP-Player CSS 184 | */ 185 | public function wp_player_admin_css(){ 186 | global $WP_PLAYER_VERSION; 187 | wp_enqueue_style( 'wp-player-plugin', plugins_url( 'assets/css/wp-player-plugin.css', dirname( __FILE__ ) ), array(), $WP_PLAYER_VERSION ); 188 | } 189 | 190 | /** 191 | * @desc add Admin Upload script 192 | */ 193 | public function wp_player_admin_head(){ 194 | global $WP_PLAYER_VERSION; 195 | wp_enqueue_script( 'jquery' ); 196 | wp_enqueue_script('media-upload'); 197 | wp_enqueue_script('thickbox'); 198 | wp_enqueue_script( 'wp-plugin-uploader', plugins_url( 'assets/js/plugin-uploader.js', dirname( __FILE__ ) ), array('jquery','media-upload','thickbox'), $WP_PLAYER_VERSION ); 199 | } 200 | 201 | /** 202 | * @desc string replace 203 | */ 204 | private function each($str, $isThumb = false) { 205 | $arr = explode("\r", $str); 206 | $text = ''; 207 | if (is_array($arr)) { 208 | foreach ( $arr as $val ) { 209 | $val = trim($val); 210 | if ( !empty($val) ) { 211 | $text .= $val.'|'; 212 | } elseif ($isThumb) { 213 | $text .= $this->base_dir.'images/default.png'.'|'; 214 | } 215 | } 216 | } 217 | return $text; 218 | } 219 | 220 | /** 221 | * @desc get MetaBox 222 | */ 223 | private function get_source() { 224 | global $post; 225 | 226 | $result = array(); 227 | $source = get_post_meta( $post->ID, 'wp_player_music_type', true ); 228 | 229 | $result['source'] = empty($source) ? 'xiami' : $source; 230 | $result['xiami'] = get_post_meta( $post->ID, 'mp3_xiami', true ); 231 | $result['title'] = $this->each(trim(get_post_meta( $post->ID, 'mp3_title', true ))); 232 | $result['author'] = $this->each(trim(get_post_meta( $post->ID, 'mp3_author', true ))); 233 | $result['file'] = $this->each(trim(get_post_meta( $post->ID, 'mp3_address', true ))); 234 | $result['thumb'] = $this->each(get_post_meta( $post->ID, 'mp3_thumb', true ), true); 235 | $result['type'] = get_post_meta( $post->ID, 'mp3_xiami_type', true ); 236 | 237 | $lyric = get_post_meta( $post->ID, 'wp_player_lyric_open', true ); 238 | if ( !empty( $lyric ) && $lyric == 'open' ) { 239 | $result['open'] = $lyric; 240 | $result['output'] = '
        '; 241 | } else { 242 | $result['open'] = 'close'; 243 | $result['output'] = ''; 244 | } 245 | 246 | return $result; 247 | } 248 | 249 | /** 250 | * @desc add shortcode 251 | */ 252 | public function wp_player_shortcode( $atts ){ 253 | global $post; 254 | 255 | extract( shortcode_atts( array( 256 | 'autoplay' => 0, 257 | 'random' => 0 258 | ), $atts ) ); 259 | 260 | $data = $this->get_source(); 261 | $img = $this->base_dir.'assets/images/default.png'; 262 | 263 | return '
        '.$data['output'].'
            '; 264 | } 265 | 266 | /** 267 | * @desc WP-Player Admin Option Page 268 | */ 269 | public function printAdminPage(){ 270 | ?> 271 |
            272 |

            WP-Player 设置


            273 |
            274 | 275 | options; ?> 276 | 277 | 278 | 279 | 280 | 287 | 288 | 289 | 290 | 305 | 306 | 307 | 308 | 316 | 317 | 318 |
            281 | 文章中插入短代码:
            282 |
              283 |
            1. [player]
            2. 284 |
            3. [player autoplay="0" randplay="1"]
            4. 285 |
            286 |
            291 | 提供了MetaBox来填写参数
            292 |
              293 |
            1. WP-Player 支持网易云音乐, 虾米音乐, QQ音乐, 百度音乐平台
            2. 294 |
            3. 如在网易云音乐打开喜欢的歌曲页面,复制歌曲页面的网址如:http://music.163.com/#/song?id=191213
            4. 295 |
            5. 并将复制的网址填写到后面的表单内。音乐类型将根据网址自动做出选择。
            6. 296 |
            7. 点击获取音乐ID按钮,此时音乐ID出现在表单中。
            8. 297 |
            9. 将短代码 [player autoplay="1" random="1"] 填入您的文章内容中。
            10. 298 |
            11. 短代码中 autoplay 表示是否自动播放;参数"0"表示否;"1"表示是;
            12. 299 |
            13. 短代码中 random 表示是否随机播放;参数"0"表示否;"1"表示是;
            14. 300 |
            15. 支持播放歌单:单音乐页面、专辑页面、艺人页面、精选集页面。
            16. 301 |
            17. PS:本插件需要您的服务器或主机支持 PHP 5.4+ and Curl, OpenSSL 模块已安装。
            18. 302 |
            19. Tips:本插件仅供个人学习研究使用,请勿作为各种商业用户,音乐版权归各音乐平台所有。
            20. 303 |
            304 |
            309 |
            310 | 314 |
            315 |
            319 |
            320 |
            321 | 322 |
            323 |
            324 |
            325 | -------------------------------------------------------------------------------- /src/readme.txt: -------------------------------------------------------------------------------- 1 | === WP-Player === 2 | Contributors: M.J 3 | Donate link: http://webjyh.qiniudn.com/alipay.png 4 | Tags: 网易云音乐, 虾米音乐, QQ 音乐, 百度音乐, MP3, WP-Player, Mp3-Player, Player 5 | Requires at least: 4.0 6 | Tested up to: 4.8 7 | Stable tag: trunk 8 | License: GPLv2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | 11 | WP-Player 一个迷你歌曲播放器,支持多歌曲播放,支持使用网易云音乐, 虾米音乐, QQ音乐, 百度音乐歌曲地址, 也支持自定义上传音乐。 12 | 13 | == Description == 14 | 15 | WordPress 插件 WP-Player 是一个迷你歌曲播放器,支持多歌曲播放,支持使用网易云音乐, 虾米音乐, QQ音乐, 百度音乐歌曲地址, 也支持自定义上传音乐。 16 | 17 | 插件介绍: 18 | 1. WP-Player 支持网易云音乐, 虾米音乐, QQ音乐, 百度音乐平台 19 | 2. 如在网易云音乐打开喜欢的歌曲页面,复制歌曲页面的网址如:http://music.163.com/#/song?id=191213 20 | 3. 并将复制的网址填写到后面的表单内。音乐类型将根据网址自动做出选择。 21 | 4. 点击获取音乐ID按钮,此时音乐ID出现在表单中。 22 | 5. 将短代码 [player autoplay="1" random="1"] 填入您的文章内容中。 23 | 6. 短代码中 autoplay 表示是否自动播放;参数"0"表示否;"1"表示是; 24 | 7. 短代码中 random 表示是否随机播放;参数"0"表示否;"1"表示是; 25 | 8. 支持播放歌单:单音乐页面、专辑页面、艺人页面、精选集页面。 26 | 9. PS:本插件需要您的服务器或主机支持 PHP 5.4+ and Curl, OpenSSL 模块已安装。 27 | 10. Tips:本插件仅供个人学习研究使用,请勿作为各种商业用户,音乐版权归各音乐平台所有 28 | 29 | PS:一篇文章只能插入一个播放器,因为用了MetaBox获取参数,只能一篇文章使用一个。 30 | 31 | 详细介绍: http://webjyh.com/wp-player/ 32 | 33 | == Installation == 34 | 1. 上传 `wp-player`目录 到 `/wp-content/plugins/` 目录 35 | 2. 在后台插件菜单激活该插件 36 | 3. 短代码调用插件: 37 | [player] 38 | [player autoplay="1" random="1"] 39 | 40 | == Screenshots == 41 | 42 | 1. 播放器界面 43 | 2. 插件参数填写 44 | 3. 插件后台设置 45 | 46 | == Changelog == 47 | = v2.6.2 = 48 | 1. 修复 网易云音乐某些链接从http重写https的问题 @timk-lalala 49 | 50 | = v2.6.1 = 51 | 1. 修复 PHP 语法报错问题 52 | 53 | = v2.6.0 = 54 | 1. 新增 QQ音乐 百度音乐平台。 55 | 2. 新增 当前歌曲不能播放,跳转至下一曲。 56 | 3. 新增 随机播放歌曲功能。 57 | 4. 新增 $('[data-wp-player="wp-player"]').WPPlayer('reload'); 方法,让单页面用户 可重新初始化播放器。 58 | 5. 新增 $('[data-wp-player="wp-player"]').WPPlayer('destroy'); 方法,用于销毁播放器; 59 | 6. 新增 歌曲列表自动滚动到中间位置,在也不用为找不到当前歌曲烦恼。 60 | 7. 修复虾米,网易获取音乐失败问题。 61 | 8. 修复样式问题,改善收缩列表动画问题 62 | 9. 美化歌曲列表滚动条样式 63 | 10. 更新 SoundManager 版本至最新版本 64 | 11. 在此感谢 @metowolf 开发的 Meting 框架,为获取音乐提供了更简单的方式 65 | 12. 项目地址:https://github.com/metowolf/Meting 66 | 13. 此版本项目结够改动比较大,请删除插件重新安装最好 67 | 68 | = v2.5.1 = 69 | 1. 紧急修复因2.5.0版本导致网易云音乐不能播放问题 70 | 71 | = v2.5.0 = 72 | 1. 新增自定义上传歌曲支持多歌曲。 73 | 2. 歌曲按一行一个填写,歌曲内容列表按歌曲名显示。 74 | 3. 因考虑自定义上传将会有多条记录,所以才用一行一首歌曲来填写。 75 | 4. 修正歌曲只有两首时,上一首,下一首按钮无用情况。 76 | 5. 现阶段功能上已基本完成,年前将只会进行Bug修复,暂不会开发新功能。 77 | 6. 如还想用2.4.2 老版本 请戳:https://github.com/webjyh/WP-Player/releases 78 | 7. 各位马上就要过年了,各位新年快乐! 79 | 80 | = v2.4.2 = 81 | 1. 修正因某些主题使用字体图标导致样式错位 82 | 2. 修正某些主题下歌单不显示的问题 83 | 3. 修正若干样式排版问题 84 | 4. 下个版本将会入手自定义上传多歌曲功能 85 | 86 | = v2.4.1 = 87 | 1. 解决因关闭歌词功能导致的JS错误。 88 | 2. 修正移动端最小宽度问题。 89 | 90 | = v2.4.0 = 91 | 1. 新增移动端播放适配(暂不支持移动端自动播放歌曲功能)。 92 | 2. 因移动端的兼容性问题,自动播放功能将无法使用。 93 | 3. 因歌词功能消耗较大,在移动端下将被禁用。 94 | 4. 在 iPhone 6、iPhone 5s、iPhone 5、iOS 8.x+系统 测试通过。 95 | 5. 在 Android 4.1+ 系统测试过能。 96 | 6. 因移动端机型混杂,各大浏览器厂商也更多,难免会有意料之外的Bug。 97 | 7. 修正移动端样式问题。 98 | 8. 如想用 v2.3.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 99 | 100 | = v2.3.1 = 101 | 1. 紧急修复暂无歌词Bug 102 | 2. 修正图片缓存问题 103 | 104 | = v2.3.0 = 105 | 1. 新增歌词预览功能( 支持虾米和网易 ) 106 | 2. 因歌词预览功能比较耗费资源,可在单独添加播放器时,打开或关闭此功能。 107 | 3. 因获取歌词功能接口的一些特殊性,如在后台选择中未出现歌词功能,则表示当前站点暂不支持。 108 | 4. 因其调取接口获取歌词在处理歌词时间上难免会有些误差(请不要太在意这些细节) 109 | 5. 修正一些样式错误。 110 | 6. 如想用 v2.2.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 111 | 112 | = v2.2.0 = 113 | 1. 新增网易云音乐网址的调用(支持单音乐页面、专辑页面、艺人页面、精选集[即歌单]页面) 114 | 2. 因网易的接口一些特殊性,如在后台选择网站类型中没有出现网易音乐,则您当前的站点暂不支持网易云音乐。 115 | 3. 其次要感谢牧风的音乐播放插件,作为参考实现了网易接口的思路。 116 | 4. 在次还要感谢此文作者 https://github.com/yanunon/NeteaseCloudMusic/wiki/网易云音乐API分析 117 | 5. 修正播放器请求容错处理方案。 118 | 6. 去除短代码中 00:00 字样。 119 | 7. 修正播放器样式问题。 120 | 8. 如想用 v2.1.0 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 121 | 122 | = v2.1.0 = 123 | 1. 因发现最近播放器在解析虾米地址时,出现不稳定的情况,采用最新发现的虾米接口。 124 | 2. 新接口将是直接调取虾米网接口,速度更快且稳定。 125 | 3. 为其保险起见,怕日后虾米封其接口,如获取失败,将移交给新浪云解析。 126 | 4. 去除播放器HTML中的 Loading 字样,为其前台显示更美观。 127 | 5. 修正播放器样式问题。 128 | 6. 修正某些情况下导致图片无法显示的情况。 129 | 7. 如想用 v2.0.1 老版本,可去 https://github.com/webjyh/WP-Player/releases 下载 130 | 131 | = v2.0.1 = 132 | 1. 修正因接口调制后台无法抓取虾米ID的问题 133 | 2. 后台无法抓去将采用 新浪云来解析 134 | 3. 修正播放器样式问题。 135 | 136 | = v2.0.0 = 137 | 1. 播放器新版扁平皮肤 138 | 2. 支持虾米多歌曲播放 139 | 3. 支持单音乐页面、专辑页面、艺人页面、精选集页面 140 | 4. 重构虾米地址填写解析;现只需复制网址,便可自动解析虾米ID。 141 | 5. 将解析虾米地址移交至插件本身 142 | 6. 重构播放器JS,采用SoundManger2来管理 143 | 7. 支持IE6+,FireFox,Chrome; 144 | 8. 废除短代码 loop 参数 145 | 9. 关闭后台无用选项设置 146 | 147 | = v1.3.4 = 148 | 1. 修正 弱干 Bug 149 | 2. 由百度云平台解析 换至 新浪云平台 150 | 3. 百度云平台解析至 2014-10月底废除,请各位小伙伴赶紧更新 151 | 152 | = v1.3.2 = 153 | 1. 修正 后台 jQuery 选项选择无用的Bug。 154 | 155 | = v1.3.1 = 156 | 1. 因提交到官方所以删除一些无用文件 157 | 2. 由原来自带的jQuery库 修改调用WordPress自带jQuery库 158 | 159 | = v1.3.0 = 160 | 1. 增加百度云API,使解析虾米音乐地址更稳定 161 | 2. 细节调整 162 | 3. 修复Bug 163 | 4. 代码重构 164 | 5. 初次使用请到插件设置页面,设置虾米解析API。 165 | 166 | = v1.2.0 = 167 | 1. 增加皮肤选择 168 | 2. 新增扁平化皮肤 具体效果查看本页面播放器 169 | 3. 增加插件设定按钮 170 | 4. 扁平化皮肤 只支持 Chrome 和 FireFox 游览器 171 | 172 | = v1.1.0 = 173 | 1. 因虾米API变动,解决获取歌曲地址问题! 174 | 2. 添加根据虾米ID自动获取歌曲信息 175 | 3. MeatBox 更加简洁化 176 | 177 | = v1.0.0 = 178 | 1. 插件初始版本 -------------------------------------------------------------------------------- /src/wp-player.php: -------------------------------------------------------------------------------- 1 | 7 | * Author: M.J 8 | * Author URI: http://webjyh.com 9 | * License: GPLv2 or later 10 | */ 11 | class_exists('wp_player_plugin') || require_once('include/player.php'); 12 | new wp_player_plugin(); 13 | ?> --------------------------------------------------------------------------------