'#FFFFFF',
'controlbar.icons'=>'rgba(255,255,255,0.8)',
'controlbar.iconsActive'=>'#FFFFFF',
'controlbar.background'=>'rgba(0,0,0,0)',
'timeslider.progress'=>'#F2F2F2',
'timeslider.rail'=>'rgba(255,255,255,0.3)',
'menus.text'=>'rgba(255,255,255,0.8)',
'menus.textActive'=>'#FFFFFF',
'menus.background'=>'#333333',
'tooltips.text'=>'#000000',
'tooltips.background'=>'#FFFFFF'
);
/**
* 激活插件方法,如果激活失败,直接抛出异常
*
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function activate()
{
Typecho_Plugin::factory('Widget_Abstract_Contents')->contentEx = array('JWPlayer_Plugin','jwparse');
Typecho_Plugin::factory('Widget_Abstract_Contents')->excerpt = array('JWPlayer_Plugin','txtparse');
Typecho_Plugin::factory('admin/write-post.php')->bottom = array('JWPlayer_Plugin','jwbutton');
Typecho_Plugin::factory('admin/write-page.php')->bottom = array('JWPlayer_Plugin','jwbutton');
/* 模版调用钩子 例: jwplayer(array('file'=>'http://test.mp4')); ?> 参数为键值对 */
Typecho_Plugin::factory('Widget_Archive')->callJwplayer = array('JWPlayer_Plugin', 'output');
}
/**
* 禁用插件方法,如果禁用失败,直接抛出异常
*
* @static
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function deactivate(){}
/**
* 获取插件配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form 配置面板
* @return void
*/
public static function config(Typecho_Widget_Helper_Form $form)
{
$options = Helper::options();
$security = Helper::security();
$plugurl = $options->pluginUrl;
//格式化默认配色
$cset = array();
$cs = Json::encode(self::$skincs);
if (isset($options->plugins['activated']['JWPlayer'])) {
$settings = $options->plugin('JWPlayer');
$cset = Json::decode($settings->jwcolors,true);
}
//输出面板效果
echo '
'._t('编辑文章或页面写入%s文件地址%s即可显示影音播放器, ','
<jw>','</jw>').'
'._t('多个文件连播可用%s号隔开,','
,').'
'._t('参数间用%s号隔开, 支持%s等
[参数列表]. 示例','
|','
width(宽度)
height(高度)
image(封面)
title(标题)').'
<jw>http://a.mp4,http://b.flv|
image=http://aa.jpg,http://bb.png|
title=aaa,bbb|
autostart=false|
repeat=true</jw>
| '._t('参数').' |
'._t('默认').' |
'._t('说明').' |
| image |
- |
'._t('封面图片url,播放音频时全程显示。').' |
| title |
- |
'._t('标题文字,封面窗口和列表项显示。').' |
| description |
- |
'._t('描述文字,封面窗口显示。').' |
| tracks |
- |
'._t('字幕文件url,支持WebVTT/SRT/DFXP格式。').' |
| width |
640 |
'._t('宽度像素值(整数)或百分数。').' |
| height |
360 |
'._t('高度像素值(整数),40为音频模式高度。').' |
| aspectratio |
- |
'._t('宽高比如%s,与百分数width锁定画面比例。','16:9').' |
| autostart |
false |
'._t('自动播放,为%s时开启。','true').' |
| repeat |
false |
'._t('循环播放,为%s时开启。','true').' |
| mute |
false |
'._t('静音,为%s时开启。','true').' |
| preload |
metadata |
'._t('预加载,%s最少/%s禁用/%s自动。','metadata','none','auto').' |
| abouttext |
- |
'._t('右击菜单文字,可覆盖插件提示原文链接设置。').' |
| aboutlink |
- |
'._t('右击菜单链接,同上。').' |
| stretching |
uniform |
'._t('画面适应方法,可覆盖插件统一设置,对应值%s固定/%s缩放/%s裁切/%s拉伸。','none','uniform','fill','exactfit').' |
| minDvrWindow |
120 |
'._t('(直播流)回放模式判定,默认检测到120个缓存单元开启,设置为0可强制显示录像控制按钮。','monoscopic',',').' |
| stereomode |
- |
'._t('VR全景模式解析,使用值%s即为360度自由旋转,多个视频可重复该值用%s号分隔。','monoscopic',',').' |
| cast |
- |
'._t('投屏模式,没有值,留空即可自动检测%s或%s设备请求并显示相关按钮。','Google Cast','Apple Airplay').' |
';
$skin = new Typecho_Widget_Helper_Form_Element_Select('skin',
array(
'controlbar.text'=>_t('控制栏文本'),
'controlbar.icons'=>_t('图标'),
'controlbar.iconsActive'=>_t('图标(悬停)'),
'controlbar.background'=>_t('控制栏背景'),
'timeslider.progress'=>_t('进度条'),
'timeslider.rail'=>_t('进度条(剩余)'),
'menus.text'=>_t('菜单文本'),
'menus.textActive'=>_t('菜单文本(悬停)'),
'menus.background'=>_t('菜单背景'),
'tooltips.text'=>_t('提示文字'),
'tooltips.background'=>_t('提示文字背景')
),
'controlbar.text','
'._t('定制配色预览').' ⇡
',_t('RGBA末位小数0-1代表透明度可手动修改'));
$skin->input->setAttribute('id','selector');
$form->addInput($skin);
if (Typecho_Request::getInstance()->is('action=resetskin') && isset($options->plugins['activated']['JWPlayer'])) {
$security->protect();
Helper::configPlugin('JWPlayer',array('jwcolors'=>$cs));
Typecho_Response::getInstance()->goBack();
}
//重置动作按钮
$resetskin = new Typecho_Widget_Helper_Form_Element_Submit();
$resetskin->value(_t('重置'));
$resetskin->input->setAttribute('class','btn btn-xs');
$resetskin->input->setAttribute('formaction',$security->getAdminUrl('options-plugin.php?config=JWPlayer&action=resetskin'));
$form->addItem($resetskin);
$stretch = new Typecho_Widget_Helper_Form_Element_Select('stretch',
array('none'=>_t('固定'),''=>_t('缩放'),'fill'=>_t('裁切'),'exactfit'=>_t('拉伸')),'',_t('画面适应方法'),_t('视频尺寸与播放器尺寸不同时的修正方式'));
$form->addInput($stretch);
$encode = new Typecho_Widget_Helper_Form_Element_Radio('encode',
array(1=>_t('是'),0=>_t('否')),0,_t('加密视频地址'),_t('是否隐藏文件url使其在源码中显示为乱码'));
$form->addInput($encode);
$info = new Typecho_Widget_Helper_Form_Element_Radio('info',
array(1=>_t('是'),0=>_t('否')),0,_t('隐藏标题描述'),_t('是否在窗口显示title与description参数信息'));
$form->addInput($info);
$about = new Typecho_Widget_Helper_Form_Element_Radio('about',
array(1=>_t('是'),0=>_t('否')),0,_t('提示原文链接'),_t('右击窗口时是否显示原文链接, 参数可覆盖'));
$form->addInput($about);
$tedge = new Typecho_Widget_Helper_Form_Element_Select('tedge',
array(''=>_t('默认'),'dropshadow'=>_t('下阴影'),'depressed'=>_t('上阴影'),'uniform'=>_t('深描边'),'raised'=>_t('浅描边')),'',_t('外挂字幕效果'));
$form->addInput($tedge);
$tsize = new Typecho_Widget_Helper_Form_Element_Text('tsize',NULL,'15',_t('字体大小(单位px, 不用填写): '));
$tsize->input->setAttribute('class','text-s');
$tsize->label->setAttribute('style','position:absolute;color:#999;font-weight:normal;bottom:10px;left:82px;');
$tsize->input->setAttribute('style','position:absolute;width:38px;bottom:13px;left:258px;');
$tsize->setAttribute('style','position:relative');
$form->addInput($tsize->addRule('isFloat'));
$logo = new Typecho_Widget_Helper_Form_Element_Text('logo',
NULL,'',_t('logo水印图片'),_t('填写完整的图片url, 24位透明png效果最佳'));
$logo->input->setAttribute('class','w-60');
$form->addInput($logo->addRule('url',_t('请输入合法的图片地址')));
$llink = new Typecho_Widget_Helper_Form_Element_Text('llink',
NULL,'',_t('logo链接地址'),_t('填写点击水印图片将跳转到的目标链接url'));
$llink->input->setAttribute('class','w-60');
$form->addInput($llink->addRule('url',_t('请输入合法的链接地址')));
$lpos = new Typecho_Widget_Helper_Form_Element_Select('lpos',
array(''=>_t('右上角'),'top-left'=>_t('左上角'),'bottom-right'=>_t('右下角'),'bottom-left'=>_t('左下角'),'control-bar'=>_t('控制条')),'',_t('logo显示位置'));
$form->addInput($lpos);
$margin = new Typecho_Widget_Helper_Form_Element_Text('margin',NULL,'8',_t('边距(单位px, 不用填写): '));
$margin->input->setAttribute('class','text-s');
$margin->label->setAttribute('style','position:absolute;color:#999;font-weight:normal;bottom:10px;left:82px;');
$margin->input->setAttribute('style','position:absolute;width:38px;bottom:13px;left:230px;');
$margin->setAttribute('style','position:relative');
$form->addInput($margin->addRule('isFloat'));
$hide = new Typecho_Widget_Helper_Form_Element_Checkbox('hide',
array(1=>_t('自动隐藏')),NULL,'');
$hide->label->setAttribute('style','position:absolute;color:#999;font-weight:normal;bottom:10px;left:279px;');
$hide->input->setAttribute('style','position:absolute;bottom:4px;left:60px;');
$hide->setAttribute('style','position:relative');
$form->addInput($hide);
$share = new Typecho_Widget_Helper_Form_Element_Checkbox('share',
array('weibo'=>_t('新浪微博'),'qzone'=>_t('QQ空间'),'tieba'=>_t('百度贴吧'),'douban'=>_t('豆瓣网'),'renren'=>_t('人人网'),'facebook'=>_t('Facebook'),'twitter'=>_t('Twitter')),NULL,_t('分享功能按钮'));
$form->addInput($share);
//配色保存隐藏域
$jwcolors = new Typecho_Widget_Helper_Form_Element_Hidden('jwcolors',NULL,$cs,NULL);
$jwcolors->input->setAttribute('id','jwcolors');
$form->addInput($jwcolors);
}
/**
* 个人用户的配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form
* @return void
*/
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
/**
* 内容标签替换
*
* @param string $content
* @return string
*/
public static function jwparse($content,$widget,$lastResult)
{
$content = empty($lastResult) ? $content : $lastResult;
$version = explode('/',Helper::options()->version);
$sign = '';
$pattern = '/<(jw)>(.*?)<\/\\1>/si';
//markdown fix
if ($version['1']=='17.10.30' && $widget->isMarkdown && !stripos($content,'')) {
$sign = '</jw>';
$pattern = '/<(jw)>(.*?)<\/\\1>/si';
$content = str_replace(';/jw>',$sign,$content);
}
if ($widget instanceof Widget_Archive && !$widget->request->feed && false!==stripos($content,$sign)) {
$content = preg_replace_callback($pattern,array('JWPlayer_Plugin','callback'),$content);
}
return $content;
}
/**
* 摘要文本替换
*
* @param string $text
* @return string
*/
public static function txtparse($text,$widget,$lastResult)
{
$text = empty($lastResult) ? $text : $lastResult;
if ($widget instanceof Widget_Archive && false!==stripos($text,'')) {
$text = preg_replace('/<(jw)>(.*?)<\/\\1>/si',_t(' [影音片段: 请查看原文播放] '),$text);
}
return $text;
}
/**
* 参数回调解析
*
* @param array $match
* @return string
*/
public static function callback($match)
{
$settings = Helper::options()->plugin('JWPlayer');
$data = array();
$lists = array();
//过滤html标签
$codes = trim(Typecho_Common::stripTags($match['2']));
if (strpos($codes,'<')) $codes = substr($codes,0,-3); //markdown fix
$atts = strpos($codes,'|') ? explode('|',$codes) : array($codes);
$file = trim(array_shift($atts));
$files = explode(',',$file);
$fnum = count($files);
$qfiles = array();
$qnum = '';
$source = '';
$quality = array();
$vr = strpos($codes,'stereomode');
$dvr = strpos($codes,'minDvrWindow');
//处理视频参数
for ($i=0;$i<$fnum;++$i) {
//处理画质参数
if ($files[$i]) {
$qfiles = explode(';',$files[$i]);
$qnum = count($qfiles);
//准备画质数组
for ($j=0;$j<$qnum;++$j) {
$source = trim($qfiles[$j]);
if (false!==strpos($source,'^')) {
$metas = explode('^',$source);
$quality[$j]['label'] = $metas['0'];
$quality[$j]['file'] = self::encode($metas['1']);
if (isset($metas['2'])) {
$quality[$j]['type'] = $metas['2'];
}
} else {
$quality[$j]['file'] = self::encode($source);
//预设3种清晰度
$quality['0']['label'] = _t('标清');
if (isset($quality['1'])) {
$quality['1']['label'] = _t('高清');
}
if (isset($quality['2'])) {
$quality['2']['label'] = _t('超清');
}
}
}
}
//多文件画质参数
if ($fnum>1 || $vr || $dvr) {
if ($qnum>1) {
$lists[$i]['sources'] = $quality;
} else {
$lists[$i]['file'] = self::encode(trim($files[$i]));
}
}
}
//单文件画质参数
if ($fnum<=1) {
if ($qnum>1) {
$data['sources'] = $quality;
} else {
$data['file'] = self::encode($file);
}
}
$pair = array();
$key = '';
$val = '';
$listkey = false;
$vals = array();
$keyvals = '';
$tfiles = array();
$tnum = '';
$track = '';
$subs = array();
//处理其他参数
foreach ($atts as $att) {
$pair = explode('=',$att);
$key = trim($pair['0']);
$val = isset($pair['1']) ? trim($pair['1']) : '';
$data[$key] = $val;
$listkey = in_array($key,array('image','title','description','tracks','stereomode','minDvrWindow'));
if ($listkey) {
$vals[$key] = explode(',',$data[$key]);
}
//处理列表参数
for ($i=0;$i<$fnum;++$i) {
if (isset($vals[$key][$i])) {
$keyvals = trim($vals[$key][$i]);
//处理字幕参数
if ($key=='tracks' && $keyvals) {
$tfiles = explode(';',$keyvals);
$tnum = count($tfiles);
//准备语种数组
for ($j=0;$j<$tnum;++$j) {
$track = trim($tfiles[$j]);
if (false!==strpos($track,'^')) {
$infos = explode('^',$track);
$subs[$j]['label'] = $infos['0'];
$subs[$j]['file'] = $infos['1'];
if (isset($infos['2'])) {
$subs[$j]['kind'] = $infos['2'];
}
} else {
$subs[$j]['file'] = $track;
//预设中英字幕
$subs['0']['label'] = _t('中文');
if (isset($subs['1'])) {
$subs['1']['label'] = _t('英文');
}
}
}
if ($tnum<=1) {
array_splice($subs,1);
}
//多文件字幕参数
if ($fnum>1) {
unset($data['tracks']);
$lists[$i]['tracks'] = $subs;
}
//多文件其他参数
} elseif ($fnum>1 || $vr || $dvr) {
unset($data[$key]);
$lists[$i][$key] = $keyvals;
}
//对应自动置空
} elseif ($listkey) {
$lists[$i][$key] = '';
}
}
//单文件字幕参数
if ($key=='tracks') {
if ($fnum<=1) {
$data['tracks'] = $subs;
}
//字幕效果选项
$tsize = $settings->tsize;
if ($tsize && $tsize!=='15') {
$data['captions']['fontSize'] = $tsize;
}
if ($settings->tedge) {
$data['captions']['backgroundOpacity'] = '0';
$data['captions']['edgeStyle'] = $settings->tedge;
}
}
}
if (preg_match("/(\.rss|\.json)/i",$file)) {
unset($data['file']);
$data['playlist'] = self::encode($file);
} elseif ($lists) {
$data['playlist'] = $lists;
}
return self::output('',array($data,true));
}
/**
* 输出播放器实例
*
* @access public
* @param array $params 实例参数
* @return string
*/
public static function output($widget,array $params)
{
$options = Helper::options();
$url = $options->pluginUrl.'/JWPlayer/player/';
$ids = "jwplayer_".++self::$id;
//处理实例参数
$jwsets = array();
$jwsets = isset($params['0']) && is_array($params['0']) ? $params['0'] : $jwsets;
$iscall = false;
$iscall = !empty($params['1']) && is_bool($params['1']) ? $params['1'] : $iscall;
$jwsets = Json::encode($jwsets+self::getsets());
//播放器实例代码
$output = ''; //不重复加载
$output .= ''._t('播放器载入中...').'
';
$output .= '';
//模版输出判断
if ($iscall) {
return $output;
} else {
echo $output;
}
}
/**
* 输出插件设置
*
* @return array
*/
public static function getsets()
{
$options = Helper::options();
$skincs = self::$skincs;
$sets =array();
if (isset($options->plugins['activated']['JWPlayer'])) {
$settings = $options->plugin('JWPlayer');
$share = $settings->share;
$stretch = $settings->stretch;
$csets = Json::decode($settings->jwcolors,true);
$archive = Typecho_Widget::widget('Widget_Archive');
$url = $archive->permalink;
$key = array();
//输出配色参数
foreach ($csets as $keys=>$cs) {
if ($skincs[''.$keys.'']!==$cs) {
$key = explode('.',$keys);
$sets['skin'][''.$key['0'].''][''.$key['1'].''] = $cs;
}
}
if ($stretch) {
$sets['stretching'] = $stretch;
}
if ($settings->info) {
$sets['displaytitle'] = 'false';
$sets['displaydescription'] = 'false';
}
if ($settings->about) {
$sets['abouttext'] = _t('原文链接: ').$archive->title;
$sets['aboutlink'] = $url;
}
if ($share) {
$sets['sharing']['heading'] = _t('分享');
$sets['sharing']['link'] = $url;
array_push($share,'email');
$sets['sharing']['sites'] = $share;
}
//输出logo参数
$logo = $settings->logo;
$llink = $settings->llink;
$lops = $settings->lpos;
$margin = $settings->margin;
if ($logo) {
$sets['logo']['file'] = $logo;
if ($llink) {
$sets['logo']['link'] = $llink;
}
if ($lops) {
$sets['logo']['position'] = $lops;
}
if (false!==$margin && $margin!=='8') {
$sets['logo']['margin'] = $margin;
}
if ($settings->hide) {
$sets['logo']['hide'] = true;
}
}
}
return $sets+self::locals();
}
/**
* 加密视频地址
*
* @param string $string
* @return string
*/
private static function encode($string)
{
if (Helper::options()->plugin('JWPlayer')->encode) {
$string = rawurlencode($string);
$ntexto = '';
$codekey = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';
for ($i=0;$iarray(
'rewind'=>_t('后退10秒'),
'settings'=>_t('选项'),
'cc'=>_t('字幕'),
'hd'=>_t('画质'),
'fullscreen'=>_t('全屏'),
'videoInfo'=>_t('查看媒体信息'),
'copied'=>_t('复制成功'),
'playlist'=>_t('列表'),
'nextUp'=>_t('下一个'),
'liveBroadcast'=>_t('在线直播')
));
}
/**
* 输出编辑器按钮
*
* @access public
* @return void
*/
public static function jwbutton()
{
?>