Version Description
- Integration into BuddyPress Activities
- HTML5 Audio Tag Support (with fallback)
- HTML5 Video Tag Support (with fallback)
Download this release
Release Info
Developer | rtcamp |
Plugin | rtMedia for WordPress, BuddyPress and bbPress |
Version | 2.0 |
Comparing to | |
See all releases |
Version 2.0
- includes/bp-media-actions.php +186 -0
- includes/bp-media-admin.php +187 -0
- includes/bp-media-class-wordpress.php +365 -0
- includes/bp-media-filters.php +76 -0
- includes/bp-media-functions.php +118 -0
- includes/bp-media-loader.php +353 -0
- includes/bp-media-screens.php +337 -0
- includes/bp-media-shortcodes.php +38 -0
- includes/bp-media-template-functions.php +102 -0
- includes/css/bp-media-admin.css +39 -0
- includes/css/bp-media-style.css +65 -0
- includes/img/audio_thumb.png +0 -0
- includes/img/bp_media_social.png +0 -0
- includes/img/image_thumb.png +0 -0
- includes/img/logo_medibp_32.png +0 -0
- includes/img/video_thumb.png +0 -0
- includes/js/bp-media.js +15 -0
- includes/lib/MP4Info.php +257 -0
- includes/lib/MP4Info/Box.php +446 -0
- includes/lib/MP4Info/Box/Container.php +99 -0
- includes/lib/MP4Info/Box/ftyp.php +231 -0
- includes/lib/MP4Info/Box/hdlr.php +140 -0
- includes/lib/MP4Info/Box/ilst.php +122 -0
- includes/lib/MP4Info/Box/ilst_sub.php +148 -0
- includes/lib/MP4Info/Box/mdhd.php +146 -0
- includes/lib/MP4Info/Box/meta.php +69 -0
- includes/lib/MP4Info/Box/mvhd.php +233 -0
- includes/lib/MP4Info/Box/stsd.php +139 -0
- includes/lib/MP4Info/Box/tkhd.php +215 -0
- includes/lib/MP4Info/Box/uuid.php +117 -0
- includes/lib/MP4Info/Exception.php +61 -0
- includes/lib/MP4Info/Helper.php +72 -0
- includes/media-element/background.png +0 -0
- includes/media-element/bigplay.png +0 -0
- includes/media-element/controls-ted.png +0 -0
- includes/media-element/controls-wmp-bg.png +0 -0
- includes/media-element/controls-wmp.png +0 -0
- includes/media-element/controls.png +0 -0
- includes/media-element/flashmediaelement.swf +0 -0
- includes/media-element/loading.gif +0 -0
- includes/media-element/mediaelement-and-player.js +4262 -0
- includes/media-element/mediaelement-and-player.min.js +149 -0
- includes/media-element/mediaelement.js +1517 -0
- includes/media-element/mediaelement.min.js +59 -0
- includes/media-element/mediaelementplayer.css +801 -0
- includes/media-element/mediaelementplayer.js +2743 -0
- includes/media-element/mediaelementplayer.min.css +1 -0
- includes/media-element/mediaelementplayer.min.js +88 -0
- includes/media-element/mejs-skins.css +283 -0
- includes/media-element/silverlightmediaelement.xap +0 -0
- loader.php +56 -0
- readme.txt +40 -0
includes/bp-media-actions.php
ADDED
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Handles the uploads and creates respective posts for the upload
|
4 |
+
*
|
5 |
+
* @since BP Media 2.0
|
6 |
+
*/
|
7 |
+
function bp_media_handle_uploads() {
|
8 |
+
global $bp;
|
9 |
+
if (isset($_POST['action']) && $_POST['action'] == 'wp_handle_upload') {
|
10 |
+
if (isset($_FILES) && is_array($_FILES) && array_key_exists('bp_media_file', $_FILES) && $_FILES['bp_media_file']['name'] != '') {
|
11 |
+
$bp_media_entry = new BP_Media_Host_Wordpress();
|
12 |
+
try {
|
13 |
+
$title = isset($_POST['bp_media_title']) ? ($_POST['bp_media_title'] != "") ? $_POST['bp_media_title'] : pathinfo($_FILES['bp_media_file']['name'], PATHINFO_FILENAME) : pathinfo($_FILES['bp_media_file']['name'], PATHINFO_FILENAME);
|
14 |
+
$entry = $bp_media_entry->add_media($title, $_POST['bp_media_description']);
|
15 |
+
$bp->{BP_MEDIA_SLUG}->messages['updated'][] = __('Upload Successful', 'bp-media');
|
16 |
+
} catch (Exception $e) {
|
17 |
+
$bp->{BP_MEDIA_SLUG}->messages['error'][] = $e->getMessage();
|
18 |
+
}
|
19 |
+
} else {
|
20 |
+
$bp->{BP_MEDIA_SLUG}->messages['error'][] = __('You did not specified a file to upload', 'bp-media');
|
21 |
+
}
|
22 |
+
}
|
23 |
+
}
|
24 |
+
add_action('bp_init', 'bp_media_handle_uploads');
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Displays the messages that other functions/methods creates according to the BuddyPress' formating
|
28 |
+
*
|
29 |
+
* @since BP Media 2.0
|
30 |
+
*/
|
31 |
+
function bp_media_show_messages() {
|
32 |
+
global $bp;
|
33 |
+
if (is_array($bp->{BP_MEDIA_SLUG}->messages)) {
|
34 |
+
$types = array('error', 'updated', 'info');
|
35 |
+
foreach ($types as $type) {
|
36 |
+
if (count($bp->{BP_MEDIA_SLUG}->messages[$type]) > 0) {
|
37 |
+
bp_media_show_formatted_error_message($bp->{BP_MEDIA_SLUG}->messages[$type], $type);
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}
|
42 |
+
add_action('bp_media_before_content', 'bp_media_show_messages');
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Enqueues all the required scripts and stylesheets for the proper working of BuddyPress Media Component
|
46 |
+
*
|
47 |
+
* @since BP Media 2.0
|
48 |
+
*/
|
49 |
+
function bp_media_enqueue_scripts_styles() {
|
50 |
+
wp_enqueue_script('bp-media-mejs', plugins_url('includes/media-element/mediaelement-and-player.min.js', dirname(__FILE__)));
|
51 |
+
wp_enqueue_script('bp-media-default', plugins_url('includes/js/bp-media.js', dirname(__FILE__)));
|
52 |
+
wp_enqueue_style('bp-media-mecss', plugins_url('includes/media-element/mediaelementplayer.min.css', dirname(__FILE__)));
|
53 |
+
wp_enqueue_style('bp-media-default', plugins_url('includes/css/bp-media-style.css', dirname(__FILE__)));
|
54 |
+
}
|
55 |
+
|
56 |
+
add_action('wp_enqueue_scripts', 'bp_media_enqueue_scripts_styles', 11);
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Deletes associated media entry and its files upon deletion of an activity.
|
60 |
+
*
|
61 |
+
* @since BP Media 2.0
|
62 |
+
*/
|
63 |
+
function bp_media_delete_activity_handler($activity_id, $user) {
|
64 |
+
global $bp_media_count;
|
65 |
+
bp_media_init_count(bp_loggedin_user_id());
|
66 |
+
$post_id = bp_activity_get_meta($activity_id, 'bp_media_parent_post');
|
67 |
+
$type = get_post_meta($post_id, 'bp_media_type', true);
|
68 |
+
switch ($type) {
|
69 |
+
case 'image':
|
70 |
+
$bp_media_count['images'] = intval($bp_media_count['images']) - 1;
|
71 |
+
break;
|
72 |
+
case 'video':
|
73 |
+
$bp_media_count['videos'] = intval($bp_media_count['videos']) - 1;
|
74 |
+
break;
|
75 |
+
case 'audio':
|
76 |
+
$bp_media_count['audio'] = intval($bp_media_count['audio']) - 1;
|
77 |
+
break;
|
78 |
+
}
|
79 |
+
$attachment_id = get_post_meta($post_id, 'bp_media_child_attachment', true);
|
80 |
+
wp_delete_attachment($attachment_id, true);
|
81 |
+
wp_delete_post($post_id, true);
|
82 |
+
bp_update_user_meta(bp_loggedin_user_id(), 'bp_media_count', $bp_media_count);
|
83 |
+
}
|
84 |
+
|
85 |
+
/* Adds bp_media_delete_activity_handler() function to be called on bp_activity_before_action_delete_activity hook */
|
86 |
+
add_action('bp_activity_before_action_delete_activity', 'bp_media_delete_activity_handler', 10, 2);
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Called on bp_init by screen functions
|
90 |
+
*
|
91 |
+
* @uses global $bp, $bp_media_query
|
92 |
+
*
|
93 |
+
* @since BP Media 2.0
|
94 |
+
*/
|
95 |
+
function bp_media_set_query() {
|
96 |
+
global $bp, $bp_media_query;
|
97 |
+
switch ($bp->current_action) {
|
98 |
+
case BP_MEDIA_IMAGES_SLUG:
|
99 |
+
$type = 'image';
|
100 |
+
break;
|
101 |
+
case BP_MEDIA_AUDIO_SLUG:
|
102 |
+
$type = 'audio';
|
103 |
+
break;
|
104 |
+
case BP_MEDIA_VIDEOS_SLUG:
|
105 |
+
$type = 'video';
|
106 |
+
break;
|
107 |
+
default :
|
108 |
+
$type = null;
|
109 |
+
}
|
110 |
+
if (isset($bp->action_variables) && is_array($bp->action_variables) && isset($bp->action_variables[0]) && $bp->action_variables[0] == 'page' && isset($bp->action_variables[1]) && is_numeric($bp->action_variables[1])) {
|
111 |
+
$paged = $bp->action_variables[1];
|
112 |
+
} else {
|
113 |
+
$paged = 1;
|
114 |
+
}
|
115 |
+
if ($type) {
|
116 |
+
$args = array(
|
117 |
+
'post_type' => 'bp_media',
|
118 |
+
'author' => $bp->displayed_user->id,
|
119 |
+
'meta_key' => 'bp_media_type',
|
120 |
+
'meta_value' => $type,
|
121 |
+
'meta_compare' => 'LIKE',
|
122 |
+
'paged' => $paged
|
123 |
+
);
|
124 |
+
$bp_media_query = new WP_Query($args);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Adds a download button on single entry pages of media files.
|
130 |
+
*
|
131 |
+
* @since BP Media 2.0
|
132 |
+
*/
|
133 |
+
function bp_media_action_download_button() {
|
134 |
+
if(!in_array('bp_media_current_entry', $GLOBALS))
|
135 |
+
return false;
|
136 |
+
global $bp_media_current_entry;
|
137 |
+
if($bp_media_current_entry!=NULL)
|
138 |
+
echo '<a href="'.$bp_media_current_entry->get_attachment_url().'" class="button item-button bp-secondary-action bp-media-download" title="Download">Download</a>';
|
139 |
+
}
|
140 |
+
add_action('bp_activity_entry_meta', 'bp_media_action_download_button');
|
141 |
+
|
142 |
+
/* Should be used with Content Disposition Type for media files set to attachment */
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Shows the media count of a user in the tabs
|
146 |
+
*
|
147 |
+
* @since BP Media 2.0
|
148 |
+
*/
|
149 |
+
function bp_media_init_count($user = null) {
|
150 |
+
global $bp_media_count;
|
151 |
+
if (!$user)
|
152 |
+
$user = bp_displayed_user_id();
|
153 |
+
if ($user < 1) {
|
154 |
+
$bp_media_count = null;
|
155 |
+
return false;
|
156 |
+
}
|
157 |
+
$count = bp_get_user_meta($user, 'bp_media_count', true);
|
158 |
+
if (!$count) {
|
159 |
+
$bp_media_count = array('images' => 0, 'videos' => 0, 'audio' => 0);
|
160 |
+
bp_update_user_meta($user, 'bp_media_count', $bp_media_count);
|
161 |
+
} else {
|
162 |
+
$bp_media_count = $count;
|
163 |
+
}
|
164 |
+
add_filter('bp_get_displayed_user_nav_' . BP_MEDIA_SLUG, 'bp_media_items_count_filter', 10, 2);
|
165 |
+
|
166 |
+
if (bp_current_component() == BP_MEDIA_SLUG) {
|
167 |
+
add_filter('bp_get_options_nav_' . BP_MEDIA_IMAGES_SLUG, 'bp_media_items_count_filter', 10, 2);
|
168 |
+
add_filter('bp_get_options_nav_' . BP_MEDIA_VIDEOS_SLUG, 'bp_media_items_count_filter', 10, 2);
|
169 |
+
add_filter('bp_get_options_nav_' . BP_MEDIA_AUDIO_SLUG, 'bp_media_items_count_filter', 10, 2);
|
170 |
+
}
|
171 |
+
return true;
|
172 |
+
}
|
173 |
+
add_action('init', 'bp_media_init_count');
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Displays the footer of the BP Media Plugin if enabled through the dashboard options page
|
177 |
+
*
|
178 |
+
* @since BP Media 2.0
|
179 |
+
*/
|
180 |
+
function bp_media_footer() { ?>
|
181 |
+
<div id="bp-media-footer"><p>We ♥ <a href="http://rtcamp.com/buddypress-media/">MediaBP</a></p></div>
|
182 |
+
<?php
|
183 |
+
}
|
184 |
+
if(get_option('bp_media_remove_linkback')!='1')
|
185 |
+
add_action('bp_footer','bp_media_footer');
|
186 |
+
?>
|
includes/bp-media-admin.php
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Add the BuddyPress Media Component's options menu in the BuddyPress' options subnavigation.
|
4 |
+
*
|
5 |
+
* @since BP Media 2.0
|
6 |
+
*/
|
7 |
+
function bp_media_add_admin_menu() {
|
8 |
+
global $bp;
|
9 |
+
if (!is_super_admin())
|
10 |
+
return false;
|
11 |
+
|
12 |
+
$page = add_submenu_page('bp-general-settings', __('BuddyPress Media Component Settings', 'bp-media'), __('MediaBP', 'bp-media'), 'manage_options', 'bp-media-settings', 'bp_media_admin_menu'
|
13 |
+
);
|
14 |
+
add_action('admin_print_styles-' . $page, 'bp_media_admin_enqueue');
|
15 |
+
}
|
16 |
+
add_action(bp_core_admin_hook(), 'bp_media_add_admin_menu');
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Displays and updates the options menu of BuddyPress Media Component
|
20 |
+
*
|
21 |
+
* @since BP Media 2.0
|
22 |
+
*/
|
23 |
+
function bp_media_admin_menu() {
|
24 |
+
$bp_media_errors=array();
|
25 |
+
$bp_media_messages=array();
|
26 |
+
|
27 |
+
if(array_key_exists('submit', $_POST)){
|
28 |
+
check_admin_referer('bp_media_update_options');
|
29 |
+
if(array_key_exists('refresh_media_count', $_POST)){
|
30 |
+
if(!bp_media_update_count())
|
31 |
+
$bp_media_errors[]="Recounting Failed";
|
32 |
+
else
|
33 |
+
$bp_media_messages[]="Recounting of media files done successfully";
|
34 |
+
}
|
35 |
+
if(array_key_exists('remove_linkback', $_POST)&&$_POST['remove_linkback']=='1'){
|
36 |
+
update_option('bp_media_remove_linkback', '1');
|
37 |
+
}
|
38 |
+
else{
|
39 |
+
update_option('bp_media_remove_linkback', '0');
|
40 |
+
}
|
41 |
+
}
|
42 |
+
?>
|
43 |
+
<div class="metabox-fixed metabox-holder alignright">
|
44 |
+
<?php bp_media_default_admin_sidebar(); ?>
|
45 |
+
</div>
|
46 |
+
<div class="wrap bp-media-admin">
|
47 |
+
<div id="icon-bp-media" class="icon32"><br/></div>
|
48 |
+
<h2>BuddyPress Media Component Settings</h2>
|
49 |
+
<?php if(count($bp_media_errors)) { ?>
|
50 |
+
<div class="error"><p><?php foreach($bp_media_errors as $error) echo $error.'<br/>'; ?></p></div>
|
51 |
+
<?php } if(count($bp_media_messages)){?>
|
52 |
+
<div class="updated"><p><?php foreach($bp_media_messages as $message) echo $message.'<br/>'; ?></p></div>
|
53 |
+
<?php }?>
|
54 |
+
<form method="post">
|
55 |
+
<?php wp_nonce_field( 'bp_media_update_options' ); ?>
|
56 |
+
<table class="form-table ">
|
57 |
+
<tbody>
|
58 |
+
<tr valign="top">
|
59 |
+
<th scope="row"><label for="refresh_media_count">Re-Count Media Entries</label></th>
|
60 |
+
<td> <fieldset><legend class="screen-reader-text"><span>Re-Count Media Entries</span></legend><label for="refresh_media_count">
|
61 |
+
<input name="refresh_media_count" type="checkbox" id="refresh_media_count" value="1">
|
62 |
+
Check for Re-Count</label>
|
63 |
+
</fieldset></td>
|
64 |
+
</tr>
|
65 |
+
<tr valign="top">
|
66 |
+
<th scope="row"><label for="remove_linkback">Remove Linkback</label></th>
|
67 |
+
<td>
|
68 |
+
<fieldset>
|
69 |
+
<legend class="screen-reader-text"><span>Remove Linkback</span></legend>
|
70 |
+
<label for="remove_linkback"><input name="remove_linkback" type="checkbox" id="remove_linkback" value="1" <?php if(get_option('bp_media_remove_linkback')=='1') echo 'checked="checked"' ?>> Removes the link to MediaBP from footer</label>
|
71 |
+
</fieldset>
|
72 |
+
</td>
|
73 |
+
</tr>
|
74 |
+
</tbody>
|
75 |
+
</table>
|
76 |
+
<p class="submit"><input type="submit" name="submit" id="submit" class="button-primary" value="Save Changes"></p></form>
|
77 |
+
</div>
|
78 |
+
<?php
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Display feeds from a specified Feed URL
|
83 |
+
*
|
84 |
+
* @param string $feed_url The Feed URL.
|
85 |
+
*
|
86 |
+
* @since BP Media 2.0
|
87 |
+
*/
|
88 |
+
function bp_media_get_feeds($feed_url = 'http://rtcamp.com/blog/category/buddypress-media/feed/') {
|
89 |
+
// Get RSS Feed(s)
|
90 |
+
require_once( ABSPATH . WPINC . '/feed.php' );
|
91 |
+
$maxitems = 0;
|
92 |
+
// Get a SimplePie feed object from the specified feed source.
|
93 |
+
$rss = fetch_feed($feed_url);
|
94 |
+
if (!is_wp_error($rss)) { // Checks that the object is created correctly
|
95 |
+
// Figure out how many total items there are, but limit it to 5.
|
96 |
+
$maxitems = $rss->get_item_quantity(5);
|
97 |
+
|
98 |
+
// Build an array of all the items, starting with element 0 (first element).
|
99 |
+
$rss_items = $rss->get_items(0, $maxitems);
|
100 |
+
}
|
101 |
+
?>
|
102 |
+
<ul><?php
|
103 |
+
if ($maxitems == 0) {
|
104 |
+
echo '<li>' . __('No items', 'bp-media') . '.</li>';
|
105 |
+
} else {
|
106 |
+
// Loop through each feed item and display each item as a hyperlink.
|
107 |
+
foreach ($rss_items as $item) {
|
108 |
+
?>
|
109 |
+
<li>
|
110 |
+
<a href='<?php echo $item->get_permalink(); ?>' title='<?php echo __('Posted ', 'bp-media') . $item->get_date('j F Y | g:i a'); ?>'><?php echo $item->get_title(); ?></a>
|
111 |
+
</li><?php
|
112 |
+
}
|
113 |
+
}
|
114 |
+
?>
|
115 |
+
</ul><?php
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Default BuddyPress Media Component admin sidebar with metabox styling
|
120 |
+
*
|
121 |
+
* @since BP Media 2.0
|
122 |
+
*/
|
123 |
+
function bp_media_default_admin_sidebar() {
|
124 |
+
?>
|
125 |
+
<div class="postbox" id="social">
|
126 |
+
<div title="<?php _e('Click to toggle', 'bp-media'); ?>" class="handlediv"><br /></div>
|
127 |
+
<h3 class="hndle"><span><?php _e('Getting Social is Good', 'bp-media'); ?></span></h3>
|
128 |
+
<div class="inside" style="text-align:center;">
|
129 |
+
<a href="<?php printf('%s', 'http://www.facebook.com/rtCamp.solutions/'); ?>" target="_blank" title="<?php _e('Become a fan on Facebook', 'bp-media'); ?>" class="bp-media-facebook bp-media-social"><?php _e('Facebook', 'bp-media'); ?></a>
|
130 |
+
<a href="<?php printf('%s', 'https://twitter.com/rtcamp/'); ?>" target="_blank" title="<?php _e('Follow us on Twitter', 'bp-media'); ?>" class="bp-media-twitter bp-media-social"><?php _e('Twitter', 'bp-media'); ?></a>
|
131 |
+
<a href="<?php printf('%s', 'http://feeds.feedburner.com/rtcamp/'); ?>" target="_blank" title="<?php _e('Subscribe to our feeds', 'bp-media'); ?>" class="bp-media-rss bp-media-social"><?php _e('RSS Feed', 'bp-media'); ?></a>
|
132 |
+
</div>
|
133 |
+
</div>
|
134 |
+
|
135 |
+
<div class="postbox" id="donations">
|
136 |
+
<div title="<?php _e('Click to toggle', 'bp-media'); ?>" class="handlediv"><br /></div>
|
137 |
+
<h3 class="hndle"><span><?php _e('Promote, Donate, Share', 'bp-media'); ?>...</span></h3>
|
138 |
+
<div class="inside">
|
139 |
+
<p><?php printf(__('Buy coffee/beer for team behind <a href="%s" title="BuddyPress Media Component">BuddyPress Media Component</a>.', 'bp-media'), 'http://rtcamp.com/buddypress-media/'); ?></p>
|
140 |
+
<div class="bp-media-paypal" style="text-align:center">
|
141 |
+
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
|
142 |
+
<input type="hidden" name="cmd" value="_donations" />
|
143 |
+
<input type="hidden" name="business" value="paypal@rtcamp.com" />
|
144 |
+
<input type="hidden" name="lc" value="US" />
|
145 |
+
<input type="hidden" name="item_name" value="BuddyPress Media Component" />
|
146 |
+
<input type="hidden" name="no_note" value="0" />
|
147 |
+
<input type="hidden" name="currency_code" value="USD" />
|
148 |
+
<input type="hidden" name="bn" value="PP-DonationsBF:btn_donateCC_LG.gif:NonHostedGuest" />
|
149 |
+
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" name="submit" alt="PayPal - The safer, easier way to pay online!" />
|
150 |
+
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
|
151 |
+
</form>
|
152 |
+
</div>
|
153 |
+
<div class="rt-social-share" style="text-align:center; width: 135px; margin: 2px auto">
|
154 |
+
<div class="rt-facebook" style="float:left; margin-right:5px;">
|
155 |
+
<a style=" text-align:center;" name="fb_share" type="box_count" share_url="http://rtcamp.com/buddypress-media/"></a>
|
156 |
+
</div>
|
157 |
+
<div class="rt-twitter" style="">
|
158 |
+
<a href="<?php printf('%s', 'http://twitter.com/share'); ?>" class="twitter-share-button" data-text="I ♥ #mediabp" data-url="http://rtcamp.com/buddypress-media/" data-count="vertical" data-via="mediabp"><?php _e('Tweet', 'bp-media'); ?></a>
|
159 |
+
<script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
|
160 |
+
</div>
|
161 |
+
<div class="clear"></div>
|
162 |
+
</div>
|
163 |
+
</div>
|
164 |
+
</div>
|
165 |
+
|
166 |
+
<div class="postbox" id="support">
|
167 |
+
<div title="<?php _e('Click to toggle', 'bp-media'); ?>" class="handlediv"><br /></div>
|
168 |
+
<h3 class="hndle"><span><?php _e('Free Support', 'bp-media'); ?></span></h3>
|
169 |
+
<div class="inside"><p><?php printf(__(' If you are facing any problems while using BuddyPress Media Component, or have good ideas for improvements, please discuss the same in our <a href="%s" target="_blank" title="Click here for BuddyPress Media Component Free Support">Support forums</a>', 'bp-media'), 'http://rtcamp.com/support/forum/buddypress-media/'); ?>.</p></div>
|
170 |
+
</div>
|
171 |
+
|
172 |
+
<div class="postbox" id="latest_news">
|
173 |
+
<div title="<?php _e('Click to toggle', 'bp-media'); ?>" class="handlediv"><br /></div>
|
174 |
+
<h3 class="hndle"><span><?php _e('Latest News', 'bp-media'); ?></span></h3>
|
175 |
+
<div class="inside"><?php bp_media_get_feeds(); ?></div>
|
176 |
+
</div><?php
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Enqueues the scripts and stylesheets needed for the BuddyPress Media Component's options page
|
181 |
+
*/
|
182 |
+
function bp_media_admin_enqueue() {
|
183 |
+
wp_enqueue_style('bp-media-admin-style', plugins_url('includes/css/bp-media-admin.css', dirname(__FILE__)));
|
184 |
+
wp_enqueue_script('rt-fb-share', ('http://static.ak.fbcdn.net/connect.php/js/FB.Share'), '', '', true);
|
185 |
+
}
|
186 |
+
add_action('admin_enqueue_scripts', 'bp_media_admin_enqueue');
|
187 |
+
?>
|
includes/bp-media-class-wordpress.php
ADDED
@@ -0,0 +1,365 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class BP_Media_Host_Wordpress {
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Private variables not to be accessible outside this class' member functions
|
6 |
+
*/
|
7 |
+
private $id, //id of the entry
|
8 |
+
$name, //Name of the entry
|
9 |
+
$description, //Description of the entry
|
10 |
+
$url, //URL of the entry
|
11 |
+
$type, //Type of the entry (Video, Image or Audio)
|
12 |
+
$owner, //Owner of the entry
|
13 |
+
$attachment_id; //The attachment ID of the media file
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Constructs a new BP_Media_Host_Wordpress element
|
17 |
+
*
|
18 |
+
* @param mixed $media_id optional Media ID of the element to be initialized if not defined, returns an empty element.
|
19 |
+
*
|
20 |
+
* @since BP Media 2.0
|
21 |
+
*/
|
22 |
+
function __construct($media_id = '') {
|
23 |
+
if (!$media_id == '') {
|
24 |
+
$this->init($media_id);
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Initializes the object with the variables from the post
|
30 |
+
*
|
31 |
+
* @param mixed $media_id Media ID of the element to be initialized. Can be the ID or the object of the Media
|
32 |
+
*
|
33 |
+
* @since BP Media 2.0
|
34 |
+
*/
|
35 |
+
function init($media_id = '') {
|
36 |
+
if (is_object($media_id)) {
|
37 |
+
$media = $media_id;
|
38 |
+
} else {
|
39 |
+
$media = &get_post($media_id);
|
40 |
+
}
|
41 |
+
if (empty($media->ID))
|
42 |
+
throw new Exception(__('Sorry, the requested entry does not exist.', 'bp-media'));
|
43 |
+
$this->id = $media->ID;
|
44 |
+
$this->description = $media->post_content;
|
45 |
+
$this->name = $media->post_title;
|
46 |
+
$this->owner = $media->post_author;
|
47 |
+
$this->type = get_post_meta($media->ID, 'bp_media_type', true);
|
48 |
+
switch ($this->type) {
|
49 |
+
case 'video' :
|
50 |
+
$this->url = trailingslashit(bp_core_get_user_domain($this->owner) . BP_MEDIA_VIDEOS_SLUG . '/' . BP_MEDIA_VIDEOS_ENTRY_SLUG . '/' . $this->id);
|
51 |
+
break;
|
52 |
+
case 'audio' :
|
53 |
+
$this->url = trailingslashit(bp_core_get_user_domain($this->owner) . BP_MEDIA_AUDIO_SLUG . '/' . BP_MEDIA_AUDIO_ENTRY_SLUG . '/' . $this->id);
|
54 |
+
break;
|
55 |
+
case 'image' :
|
56 |
+
$this->url = trailingslashit(bp_core_get_user_domain($this->owner) . BP_MEDIA_IMAGES_SLUG . '/' . BP_MEDIA_IMAGES_ENTRY_SLUG . '/' . $this->id);
|
57 |
+
break;
|
58 |
+
default :
|
59 |
+
return false;
|
60 |
+
}
|
61 |
+
$this->attachment_id = get_post_meta($this->id, 'bp_media_child_attachment', true);
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Handles the uploaded media file and creates attachment post for the file.
|
66 |
+
*
|
67 |
+
* @since BP Media 2.0
|
68 |
+
*/
|
69 |
+
function add_media($name, $description) {
|
70 |
+
global $bp, $wpdb, $bp_media_count;
|
71 |
+
include_once(ABSPATH . 'wp-admin/includes/file.php');
|
72 |
+
include_once(ABSPATH . 'wp-admin/includes/image.php');
|
73 |
+
//media_handle_upload('async-upload', $_REQUEST['post_id']);
|
74 |
+
$postarr = array(
|
75 |
+
'post_status' => 'draft',
|
76 |
+
'post_type' => 'bp_media',
|
77 |
+
'post_content' => $description,
|
78 |
+
'post_title' => $name
|
79 |
+
);
|
80 |
+
$post_id = wp_insert_post($postarr);
|
81 |
+
$file = wp_handle_upload($_FILES['bp_media_file']);
|
82 |
+
if (isset($file['error']) || $file === null) {
|
83 |
+
wp_delete_post($post_id, true);
|
84 |
+
throw new Exception(__('Error Uploading File', 'bp-media'));
|
85 |
+
}
|
86 |
+
$attachment = array();
|
87 |
+
$url = $file['url'];
|
88 |
+
$type = $file['type'];
|
89 |
+
$file = $file['file'];
|
90 |
+
$title = $name;
|
91 |
+
$content = $description;
|
92 |
+
$attachment = array(
|
93 |
+
'post_mime_type' => $type,
|
94 |
+
'guid' => $url,
|
95 |
+
'post_title' => $title,
|
96 |
+
'post_content' => $content,
|
97 |
+
'post_parent' => $post_id,
|
98 |
+
);
|
99 |
+
bp_media_init_count(bp_loggedin_user_id());
|
100 |
+
switch ($type) {
|
101 |
+
case 'video/mp4' :
|
102 |
+
$type = 'video';
|
103 |
+
include_once(trailingslashit(BP_MEDIA_PLUGIN_DIR) . 'includes/lib/MP4Info.php');
|
104 |
+
try {
|
105 |
+
$vid_info = MP4Info::getInfo($file);
|
106 |
+
} catch (MP4Info_Exception $e) {
|
107 |
+
wp_delete_post($post_id, true);
|
108 |
+
unlink($file);
|
109 |
+
$activity_content = false;
|
110 |
+
throw new Exception(__('MP4 file you have uploaded is currupt.', 'bp-media'));
|
111 |
+
} catch (Exception $e) {
|
112 |
+
wp_delete_post($post_id, true);
|
113 |
+
unlink($file);
|
114 |
+
$activity_content = false;
|
115 |
+
throw new Exception(__('MP4 file you have uploaded is currupt.', 'bp-media'));
|
116 |
+
}
|
117 |
+
if (is_object($vid_info)) {
|
118 |
+
if (isset($vid_info->hasVideo) && $vid_info->hasVideo && isset($vid_info->video)) {
|
119 |
+
if (!(isset($vid_info->video->codecStr) && $vid_info->video->codecStr == 'H.264')) {
|
120 |
+
wp_delete_post($post_id, true);
|
121 |
+
unlink($file);
|
122 |
+
$activity_content = false;
|
123 |
+
throw new Exception(__('The MP4 file you have uploaded is using an unsupported video codec. Supported video codec is H.264.', 'bp-media'));
|
124 |
+
}
|
125 |
+
} else {
|
126 |
+
wp_delete_post($post_id, true);
|
127 |
+
unlink($file);
|
128 |
+
$activity_content = false;
|
129 |
+
throw new Exception(__('The MP4 file you have uploaded contains no video.', 'bp-media'));
|
130 |
+
}
|
131 |
+
} else {
|
132 |
+
wp_delete_post($post_id, true);
|
133 |
+
unlink($file);
|
134 |
+
$activity_content = false;
|
135 |
+
throw new Exception(__('The MP4 file you have uploaded is not a video file.', 'bp-media'));
|
136 |
+
}
|
137 |
+
$bp_media_count['videos'] = intval($bp_media_count['videos']) + 1;
|
138 |
+
break;
|
139 |
+
case 'audio/mpeg' :
|
140 |
+
$type = 'audio';
|
141 |
+
$bp_media_count['audio'] = intval($bp_media_count['audio']) + 1;
|
142 |
+
break;
|
143 |
+
case 'image/gif' :
|
144 |
+
case 'image/jpeg' :
|
145 |
+
case 'image/png' :
|
146 |
+
$type = 'image';
|
147 |
+
$bp_media_count['images'] = intval($bp_media_count['images']) + 1;
|
148 |
+
break;
|
149 |
+
default : unlink($file);
|
150 |
+
wp_delete_post($post_id, true);
|
151 |
+
unlink($file);
|
152 |
+
$activity_content = false;
|
153 |
+
throw new Exception(__('Media File you have tried to upload is not supported. Supported media files are .jpg, .png, .gif, .mp3 and .mp4.', 'bp-media'));
|
154 |
+
}
|
155 |
+
$attachment_id = wp_insert_attachment($attachment, $file, $post_id);
|
156 |
+
if (!is_wp_error($attachment_id)) {
|
157 |
+
wp_update_attachment_metadata($attachment_id, wp_generate_attachment_metadata($attachment_id, $file));
|
158 |
+
} else {
|
159 |
+
wp_delete_post($post_id, true);
|
160 |
+
unlink($file);
|
161 |
+
throw new Exception(__('Error creating activity for the media file, please try again', 'bp-media'));
|
162 |
+
}
|
163 |
+
$postarr['ID'] = $post_id;
|
164 |
+
$postarr['post_mime_type'] = $type;
|
165 |
+
$postarr['post_status'] = 'publish';
|
166 |
+
wp_insert_post($postarr);
|
167 |
+
$activity_content = '[bp_media_content id="' . $post_id . '"]';
|
168 |
+
$activity_id = bp_media_record_activity(array(
|
169 |
+
'action' => '[bp_media_action id="' . $post_id . '"]',
|
170 |
+
'content' => $activity_content,
|
171 |
+
'primary_link' => '[bp_media_url id="' . $post_id . '"]',
|
172 |
+
'type' => 'media_upload'
|
173 |
+
));
|
174 |
+
bp_activity_update_meta($activity_id, 'bp_media_parent_post', $post_id);
|
175 |
+
update_post_meta($post_id, 'bp_media_child_activity', $activity_id);
|
176 |
+
update_post_meta($post_id, 'bp_media_child_attachment', $attachment_id);
|
177 |
+
update_post_meta($post_id, 'bp_media_type', $type);
|
178 |
+
update_post_meta($post_id, 'bp_media_hosting', 'wordpress');
|
179 |
+
$this->id = $post_id;
|
180 |
+
$this->name = $name;
|
181 |
+
$this->description = $description;
|
182 |
+
$this->owner = bp_loggedin_user_id();
|
183 |
+
$this->type = $type;
|
184 |
+
$this->url = $url;
|
185 |
+
bp_update_user_meta(bp_loggedin_user_id(), 'bp_media_count', $bp_media_count);
|
186 |
+
}
|
187 |
+
|
188 |
+
function get_media_activity_content() {
|
189 |
+
if (!bp_is_activity_component()) {
|
190 |
+
return false;
|
191 |
+
}
|
192 |
+
global $bp_media_counter, $bp_media_default_excerpts;
|
193 |
+
$attachment_id = get_post_meta($this->id, 'bp_media_child_attachment', true);
|
194 |
+
$activity_content = '<div class="bp_media_title"><a href="' . $this->url . '" title="' . $this->description . '">' . wp_html_excerpt($this->name, $bp_media_default_excerpts['activity_entry_title']) . '</a></div>';
|
195 |
+
$activity_content .='<div class="bp_media_content">';
|
196 |
+
switch ($this->type) {
|
197 |
+
case 'video' :
|
198 |
+
$activity_content.='<video src="' . wp_get_attachment_url($attachment_id) . '" width="320" height="240" type="video/mp4" id="bp_media_video_' . $this->id . '_' . $bp_media_counter . '" controls="controls" preload="none"></video></span><script>bp_media_create_element("bp_media_video_' . $this->id . '_' . $bp_media_counter . '");</script>';
|
199 |
+
break;
|
200 |
+
case 'audio' :
|
201 |
+
$activity_content.='<audio src="' . wp_get_attachment_url($attachment_id) . '" width="320" type="audio/mp3" id="bp_media_audio_' . $this->id . '_' . $bp_media_counter . '" controls="controls" preload="none" ></audio></span><script>bp_media_create_element("bp_media_audio_' . $this->id . '_' . $bp_media_counter . '");</script>';
|
202 |
+
$type = 'audio';
|
203 |
+
break;
|
204 |
+
case 'image' :
|
205 |
+
$image_array = image_downsize($attachment_id, 'bp_media_activity_image');
|
206 |
+
$activity_content.='<a href="' . $this->url . '" title="' . $this->name . '"><img src="' . $image_array[0] . '" id="bp_media_image_' . $this->id . '_' . $bp_media_counter++ . '" alt="' . $this->name . '" /></a>';
|
207 |
+
$type = 'image';
|
208 |
+
break;
|
209 |
+
default :
|
210 |
+
return false;
|
211 |
+
}
|
212 |
+
$activity_content .= '</div>';
|
213 |
+
$activity_content .= '<div class="bp_media_description">' . wp_html_excerpt($this->description, $bp_media_default_excerpts['activity_entry_description']) . '</div>';
|
214 |
+
return $activity_content;
|
215 |
+
}
|
216 |
+
|
217 |
+
function get_media_activity_url() {
|
218 |
+
if (!bp_is_activity_component())
|
219 |
+
return false;
|
220 |
+
$activity_url = $this->url;
|
221 |
+
return $activity_url;
|
222 |
+
}
|
223 |
+
|
224 |
+
function get_media_activity_action() {
|
225 |
+
if (!bp_is_activity_component())
|
226 |
+
return false;
|
227 |
+
$activity_action = sprintf(__("%s uploaded a media."), bp_core_get_userlink($this->owner));
|
228 |
+
return $activity_action;
|
229 |
+
}
|
230 |
+
|
231 |
+
function get_media_single_content() {
|
232 |
+
global $bp_media_default_sizes, $bp_media_default_excerpts;
|
233 |
+
|
234 |
+
$content = '<div class="bp_media_title">' . wp_html_excerpt($this->name, $bp_media_default_excerpts['single_entry_title']) . '</div><div class="bp_media_content">';
|
235 |
+
switch ($this->type) {
|
236 |
+
case 'video' :
|
237 |
+
$content.='<video src="' . wp_get_attachment_url($this->attachment_id) . '" width="' . $bp_media_default_sizes['single_video']['width'] . '" height="' . ($bp_media_default_sizes['single_video']['height'] == 0 ? 'auto' : $bp_media_default_sizes['single_video']['height']) . '" type="video/mp4" id="bp_media_video_' . $this->id . '" controls="controls" preload="none"></video><script>bp_media_create_element("bp_media_video_' . $this->id . '");</script>';
|
238 |
+
break;
|
239 |
+
case 'audio' :
|
240 |
+
$content.='<audio src="' . wp_get_attachment_url($this->attachment_id) . '" width="' . $bp_media_default_sizes['single_audio']['width'] . '" type="audio/mp3" id="bp_media_audio_' . $this->id . '" controls="controls" preload="none" ></audio><script>bp_media_create_element("bp_media_audio_' . $this->id . '");</script>';
|
241 |
+
$type = 'audio';
|
242 |
+
break;
|
243 |
+
case 'image' :
|
244 |
+
$image_array = image_downsize($this->attachment_id, 'bp_media_single_image');
|
245 |
+
$content.='<img src="' . $image_array[0] . '" id="bp_media_image_' . $this->id . '" />';
|
246 |
+
$type = 'image';
|
247 |
+
break;
|
248 |
+
default :
|
249 |
+
return false;
|
250 |
+
}
|
251 |
+
$content .= '</div>';
|
252 |
+
$content .= '<div class="bp_media_description">' . wp_html_excerpt($this->description, $bp_media_default_excerpts['single_entry_description']) . '</div>';
|
253 |
+
return $content;
|
254 |
+
}
|
255 |
+
|
256 |
+
function get_media_gallery_content() {
|
257 |
+
$attachment = get_post_meta($this->id, 'bp_media_child_attachment', true);
|
258 |
+
switch ($this->type) {
|
259 |
+
case 'video' :
|
260 |
+
?>
|
261 |
+
<li>
|
262 |
+
<a href="<?php echo $this->url ?>" title="<?php echo $this->description ?>">
|
263 |
+
<img src="<?php echo plugins_url('img/video_thumb.png', __FILE__) ?>" />
|
264 |
+
</a>
|
265 |
+
<h3 title="<?php echo $this->name ?>"><a href="<?php echo $this->url ?>" title="<?php echo $this->description ?>"><?php echo $this->name ?></a></h3>
|
266 |
+
</li>
|
267 |
+
<?php
|
268 |
+
break;
|
269 |
+
case 'audio' :
|
270 |
+
?>
|
271 |
+
<li>
|
272 |
+
<a href="<?php echo $this->url ?>" title="<?php echo $this->description ?>">
|
273 |
+
<img src="<?php echo plugins_url('img/audio_thumb.png', __FILE__) ?>" />
|
274 |
+
</a>
|
275 |
+
<h3 title="<?php echo $this->name ?>"><a href="<?php echo $this->url ?>" title="<?php echo $this->description ?>"><?php echo $this->name ?></a></h3>
|
276 |
+
</li>
|
277 |
+
<?php
|
278 |
+
break;
|
279 |
+
case 'image' :
|
280 |
+
$medium_array = image_downsize($attachment, 'thumbnail');
|
281 |
+
$medium_path = $medium_array[0];
|
282 |
+
?>
|
283 |
+
<li>
|
284 |
+
<a href="<?php echo $this->url ?>" title="<?php echo $this->description ?>">
|
285 |
+
<img src="<?php echo $medium_path ?>" />
|
286 |
+
</a>
|
287 |
+
<h3 title="<?php echo $this->name ?>"><a href="<?php echo $this->url ?>" title="<?php echo $this->description ?>"><?php echo $this->name ?></a></h3>
|
288 |
+
</li>
|
289 |
+
<?php
|
290 |
+
break;
|
291 |
+
default :
|
292 |
+
return false;
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
+
function show_comment_form() {
|
297 |
+
$activity_id = get_post_meta($this->id, 'bp_media_child_activity', true);
|
298 |
+
if (bp_has_activities(array(
|
299 |
+
'display_comments' => 'stream',
|
300 |
+
'include' => $activity_id,
|
301 |
+
'max' => 1
|
302 |
+
))) :
|
303 |
+
while (bp_activities()) : bp_the_activity();
|
304 |
+
do_action('bp_before_activity_entry');
|
305 |
+
?>
|
306 |
+
<div class="activity">
|
307 |
+
<ul id="activity-stream" class="activity-list item-list">
|
308 |
+
<li class="activity activity_update" id="activity-<?php echo $activity_id; ?>">
|
309 |
+
<div class="activity-content">
|
310 |
+
<?php do_action('bp_activity_entry_content'); ?>
|
311 |
+
<?php if (is_user_logged_in()) : ?>
|
312 |
+
<div class="activity-meta no-ajax">
|
313 |
+
<?php if (bp_activity_can_comment()) : ?>
|
314 |
+
<a href="<?php bp_get_activity_comment_link(); ?>" class="button acomment-reply bp-primary-action" id="acomment-comment-<?php bp_activity_id(); ?>"><?php printf(__('Comment <span>%s</span>', 'buddypress'), bp_activity_get_comment_count()); ?></a>
|
315 |
+
<?php endif; ?>
|
316 |
+
<?php if (bp_activity_can_favorite()) : ?>
|
317 |
+
<?php if (!bp_get_activity_is_favorite()) : ?>
|
318 |
+
<a href="<?php bp_activity_favorite_link(); ?>" class="button fav bp-secondary-action" title="<?php esc_attr_e('Mark as Favorite', 'buddypress'); ?>"><?php _e('Favorite', 'buddypress') ?></a>
|
319 |
+
<?php else : ?>
|
320 |
+
<a href="<?php bp_activity_unfavorite_link(); ?>" class="button unfav bp-secondary-action" title="<?php esc_attr_e('Remove Favorite', 'buddypress'); ?>"><?php _e('Remove Favorite', 'buddypress') ?></a>
|
321 |
+
<?php endif; ?>
|
322 |
+
<?php endif; ?>
|
323 |
+
<?php if (bp_activity_user_can_delete()) bp_activity_delete_link(); ?>
|
324 |
+
<?php do_action('bp_activity_entry_meta'); ?>
|
325 |
+
</div>
|
326 |
+
<?php endif; ?>
|
327 |
+
</div>
|
328 |
+
<?php do_action('bp_before_activity_entry_comments'); ?>
|
329 |
+
<?php if (( is_user_logged_in() && bp_activity_can_comment() ) || bp_activity_get_comment_count()) : ?>
|
330 |
+
<div class="activity-comments">
|
331 |
+
<?php bp_activity_comments(); ?>
|
332 |
+
<?php if (is_user_logged_in()) : ?>
|
333 |
+
<form action="<?php bp_activity_comment_form_action(); ?>" method="post" id="ac-form-<?php bp_activity_id(); ?>" class="ac-form"<?php bp_activity_comment_form_nojs_display(); ?>>
|
334 |
+
<div class="ac-reply-avatar"><?php bp_loggedin_user_avatar('width=' . BP_AVATAR_THUMB_WIDTH . '&height=' . BP_AVATAR_THUMB_HEIGHT); ?></div>
|
335 |
+
<div class="ac-reply-content">
|
336 |
+
<div class="ac-textarea">
|
337 |
+
<textarea id="ac-input-<?php bp_activity_id(); ?>" class="ac-input" name="ac_input_<?php bp_activity_id(); ?>"></textarea>
|
338 |
+
</div>
|
339 |
+
<input type="submit" name="ac_form_submit" value="<?php _e('Post', 'buddypress'); ?>" /> <?php _e('or press esc to cancel.', 'buddypress'); ?>
|
340 |
+
<input type="hidden" name="comment_form_id" value="<?php bp_activity_id(); ?>" />
|
341 |
+
</div>
|
342 |
+
<?php do_action('bp_activity_entry_comments'); ?>
|
343 |
+
<?php wp_nonce_field('new_activity_comment', '_wpnonce_new_activity_comment'); ?>
|
344 |
+
</form>
|
345 |
+
<?php endif; ?>
|
346 |
+
</div>
|
347 |
+
<?php endif; ?>
|
348 |
+
<?php do_action('bp_after_activity_entry_comments'); ?>
|
349 |
+
</li>
|
350 |
+
</ul>
|
351 |
+
</div>
|
352 |
+
<?php
|
353 |
+
endwhile;
|
354 |
+
endif;
|
355 |
+
}
|
356 |
+
|
357 |
+
function get_url() {
|
358 |
+
return $this->url;
|
359 |
+
}
|
360 |
+
|
361 |
+
function get_attachment_url(){
|
362 |
+
return wp_get_attachment_url($this->attachment_id);
|
363 |
+
}
|
364 |
+
}
|
365 |
+
?>
|
includes/bp-media-filters.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
function bp_media_activity_permalink_filter($link, $activity_obj) {
|
3 |
+
if ('media_upload' == $activity_obj->type) {
|
4 |
+
add_shortcode('bp_media_url', 'bp_media_shortcode_url');
|
5 |
+
$link = do_shortcode($activity_obj->primary_link);
|
6 |
+
remove_shortcode('bp_media_url');
|
7 |
+
}
|
8 |
+
if ('activity_comment' == $activity_obj->type) {
|
9 |
+
$parent = bp_activity_get_meta($activity_obj->item_id, 'bp_media_parent_post');
|
10 |
+
if ($parent) {
|
11 |
+
$parent = new BP_Media_Host_Wordpress($parent);
|
12 |
+
$link = $parent->get_url();
|
13 |
+
}
|
14 |
+
}
|
15 |
+
return $link;
|
16 |
+
}
|
17 |
+
add_filter('bp_activity_get_permalink', 'bp_media_activity_permalink_filter', 10, 2);
|
18 |
+
|
19 |
+
function bp_media_activity_action_filter($activity_action, $activity_obj) {
|
20 |
+
if ('media_upload' == $activity_obj->type) {
|
21 |
+
add_shortcode('bp_media_action', 'bp_media_shortcode_action');
|
22 |
+
$activity_action = do_shortcode($activity_action);
|
23 |
+
remove_shortcode('bp_media_action');
|
24 |
+
}
|
25 |
+
return $activity_action;
|
26 |
+
}
|
27 |
+
add_filter('bp_get_activity_action', 'bp_media_activity_action_filter', 10, 2);
|
28 |
+
|
29 |
+
function bp_media_activity_content_filter($activity_content, $activity_obj) {
|
30 |
+
if ('media_upload' == $activity_obj->type) {
|
31 |
+
add_shortcode('bp_media_content', 'bp_media_shortcode_content');
|
32 |
+
$activity_content = do_shortcode($activity_content);
|
33 |
+
remove_shortcode('bp_media_content');
|
34 |
+
}
|
35 |
+
return $activity_content;
|
36 |
+
}
|
37 |
+
add_filter('bp_get_activity_content_body', 'bp_media_activity_content_filter', 10, 2);
|
38 |
+
|
39 |
+
function bp_media_activity_parent_content_filter($content) {
|
40 |
+
add_shortcode('bp_media_action', 'bp_media_shortcode_action');
|
41 |
+
add_shortcode('bp_media_content', 'bp_media_shortcode_content');
|
42 |
+
$content=do_shortcode($content);
|
43 |
+
remove_shortcode('bp_media_action');
|
44 |
+
remove_shortcode('bp_media_content');
|
45 |
+
return $content;
|
46 |
+
}
|
47 |
+
|
48 |
+
add_filter('bp_get_activity_parent_content', 'bp_media_activity_parent_content_filter');
|
49 |
+
|
50 |
+
function bp_media_delete_button_handler($link) {
|
51 |
+
if(bp_current_component()=='media')
|
52 |
+
$link=str_replace('class="button', 'class="button delete-activity-single"', $link);
|
53 |
+
return $link;
|
54 |
+
}
|
55 |
+
add_filter('bp_get_activity_delete_link','bp_media_delete_button_handler');
|
56 |
+
|
57 |
+
function bp_media_items_count_filter ($title,$nav_item) {
|
58 |
+
global $bp_media_count;
|
59 |
+
switch($nav_item['slug']){
|
60 |
+
case BP_MEDIA_SLUG :
|
61 |
+
$count= intval($bp_media_count['images'])+intval($bp_media_count['videos'])+intval($bp_media_count['audio']);
|
62 |
+
break;
|
63 |
+
case BP_MEDIA_IMAGES_SLUG:
|
64 |
+
$count= intval($bp_media_count['images']);
|
65 |
+
break;
|
66 |
+
case BP_MEDIA_VIDEOS_SLUG:
|
67 |
+
$count= intval($bp_media_count['videos']);
|
68 |
+
break;
|
69 |
+
case BP_MEDIA_AUDIO_SLUG:
|
70 |
+
$count= intval($bp_media_count['audio']);
|
71 |
+
break;
|
72 |
+
}
|
73 |
+
$count_html=' <span>'. $count.'</span>';
|
74 |
+
return str_replace('</a>', $count_html.'</a>', $title);
|
75 |
+
}
|
76 |
+
?>
|
includes/bp-media-functions.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
function bp_media_record_activity($args = '') {
|
3 |
+
global $bp;
|
4 |
+
if (!function_exists('bp_activity_add'))
|
5 |
+
return false;
|
6 |
+
$defaults = array(
|
7 |
+
'id' => false, // Pass an existing activity ID to update an existing entry.
|
8 |
+
'action' => '', // The activity action - e.g. "Jon Doe posted an update"
|
9 |
+
'content' => '', // Optional: The content of the activity item e.g. "BuddyPress is awesome guys!"
|
10 |
+
'component' => BP_MEDIA_SLUG, // The name/ID of the component e.g. groups, profile, mycomponent
|
11 |
+
'type' => false, // The activity type e.g. activity_update, profile_updated
|
12 |
+
'primary_link' => '', // Optional: The primary URL for this item in RSS feeds (defaults to activity permalink)
|
13 |
+
'user_id' => $bp->loggedin_user->id, // Optional: The user to record the activity for, can be false if this activity is not for a user.
|
14 |
+
'item_id' => false, // Optional: The ID of the specific item being recorded, e.g. a blog_id
|
15 |
+
'secondary_item_id' => false, // Optional: A second ID used to further filter e.g. a comment_id
|
16 |
+
'recorded_time' => bp_core_current_time(), // The GMT time that this activity was recorded
|
17 |
+
'hide_sitewide' => false // Should this be hidden on the sitewide activity stream?
|
18 |
+
);
|
19 |
+
add_filter('bp_activity_allowed_tags', 'bp_media_override_allowed_tags');
|
20 |
+
$r = wp_parse_args($args, $defaults);
|
21 |
+
extract($r);
|
22 |
+
$activity_id = bp_activity_add(array('id' => $id, 'user_id' => $user_id, 'action' => $action, 'content' => $content, 'primary_link' => $primary_link, 'component' => $component, 'type' => $type, 'item_id' => $item_id, 'secondary_item_id' => $secondary_item_id, 'recorded_time' => $recorded_time, 'hide_sitewide' => $hide_sitewide));
|
23 |
+
return $activity_id;
|
24 |
+
}
|
25 |
+
|
26 |
+
function bp_media_override_allowed_tags($activity_allowedtags) {
|
27 |
+
$activity_allowedtags['video'] = array();
|
28 |
+
$activity_allowedtags['video']['id'] = array();
|
29 |
+
$activity_allowedtags['video']['class'] = array();
|
30 |
+
$activity_allowedtags['video']['src'] = array();
|
31 |
+
$activity_allowedtags['video']['height'] = array();
|
32 |
+
$activity_allowedtags['video']['width'] = array();
|
33 |
+
$activity_allowedtags['video']['controls'] = array();
|
34 |
+
$activity_allowedtags['video']['preload'] = array();
|
35 |
+
$activity_allowedtags['video']['alt'] = array();
|
36 |
+
$activity_allowedtags['video']['title'] = array();
|
37 |
+
$activity_allowedtags['audio'] = array();
|
38 |
+
$activity_allowedtags['audio']['id'] = array();
|
39 |
+
$activity_allowedtags['audio']['class'] = array();
|
40 |
+
$activity_allowedtags['audio']['src'] = array();
|
41 |
+
$activity_allowedtags['audio']['controls'] = array();
|
42 |
+
$activity_allowedtags['audio']['preload'] = array();
|
43 |
+
$activity_allowedtags['audio']['alt'] = array();
|
44 |
+
$activity_allowedtags['audio']['title'] = array();
|
45 |
+
$activity_allowedtags['script'] = array();
|
46 |
+
$activity_allowedtags['script']['type'] = array();
|
47 |
+
$activity_allowedtags['div'] = array();
|
48 |
+
$activity_allowedtags['div']['id'] = array();
|
49 |
+
$activity_allowedtags['div']['class'] = array();
|
50 |
+
$activity_allowedtags['a'] = array();
|
51 |
+
$activity_allowedtags['a']['title'] = array();
|
52 |
+
$activity_allowedtags['a']['href'] = array();
|
53 |
+
return $activity_allowedtags;
|
54 |
+
}
|
55 |
+
|
56 |
+
function bp_media_show_formatted_error_message($messages, $type) {
|
57 |
+
echo '<div id="message" class="' . $type . '">';
|
58 |
+
if (is_array($messages)) {
|
59 |
+
foreach ($messages as $key => $message) {
|
60 |
+
if (is_string($message)) {
|
61 |
+
echo '<p>' . $message . '</p>';
|
62 |
+
}
|
63 |
+
}
|
64 |
+
} else {
|
65 |
+
if (is_string($messages)) {
|
66 |
+
echo '<p>' . $messages . '</p>';
|
67 |
+
}
|
68 |
+
}
|
69 |
+
echo '</div>';
|
70 |
+
}
|
71 |
+
|
72 |
+
function bp_media_conditional_override_allowed_tags($content, $activity) {
|
73 |
+
if ($activity->type == 'media_upload') {
|
74 |
+
add_filter('bp_activity_allowed_tags', 'bp_media_override_allowed_tags', 1);
|
75 |
+
}
|
76 |
+
return bp_activity_filter_kses($content);
|
77 |
+
}
|
78 |
+
|
79 |
+
function bp_media_swap_filters() {
|
80 |
+
add_filter('bp_get_activity_content_body', 'bp_media_conditional_override_allowed_tags', 1, 2);
|
81 |
+
remove_filter('bp_get_activity_content_body', 'bp_activity_filter_kses', 1);
|
82 |
+
}
|
83 |
+
add_action('bp_init', 'bp_media_swap_filters');
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Updates the media count of all users.
|
87 |
+
*/
|
88 |
+
function bp_media_update_count() {
|
89 |
+
global $wpdb;
|
90 |
+
$query = "SELECT COUNT(*) AS total,b.meta_value AS type,a.post_author
|
91 |
+
FROM $wpdb->posts AS a,$wpdb->postmeta AS b
|
92 |
+
WHERE (a.id = b.post_id) AND a.post_type='bp_media' AND b.meta_key='bp_media_type'
|
93 |
+
GROUP BY b.meta_value,a.post_author";
|
94 |
+
$result = $wpdb->get_results($query);
|
95 |
+
$users_count = array();
|
96 |
+
foreach ($result as $obj) {
|
97 |
+
$users_count[$obj->post_author][$obj->type] = $obj->total;
|
98 |
+
}
|
99 |
+
$users = get_users();
|
100 |
+
foreach ($users as $user) {
|
101 |
+
if (array_key_exists($user->ID, $users_count)) {
|
102 |
+
$count = array(
|
103 |
+
'images' => isset($users_count[$user->ID]['image']) ? intval($users_count[$user->ID]['image']) : 0,
|
104 |
+
'videos' => isset($users_count[$user->ID]['video']) ? intval($users_count[$user->ID]['video']) : 0,
|
105 |
+
'audio' => isset($users_count[$user->ID]['audio']) ? intval($users_count[$user->ID]['audio']) : 0,
|
106 |
+
);
|
107 |
+
} else {
|
108 |
+
$count = array(
|
109 |
+
'images' => 0,
|
110 |
+
'videos' => 0,
|
111 |
+
'audio' => 0
|
112 |
+
);
|
113 |
+
}
|
114 |
+
bp_update_user_meta($user->ID, 'bp_media_count', $count);
|
115 |
+
}
|
116 |
+
return true;
|
117 |
+
}
|
118 |
+
?>
|
includes/bp-media-loader.php
ADDED
@@ -0,0 +1,353 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The Main loader file of BuddyPress Media Component Plugin
|
4 |
+
*/
|
5 |
+
/* Exit if accessed directlly. */
|
6 |
+
if (!defined('ABSPATH'))
|
7 |
+
exit;
|
8 |
+
|
9 |
+
/* Slug Constants */
|
10 |
+
define('BP_MEDIA_SLUG', 'media');
|
11 |
+
define('BP_MEDIA_UPLOAD_SLUG', 'upload');
|
12 |
+
|
13 |
+
define('BP_MEDIA_IMAGES_SLUG', 'images');
|
14 |
+
define('BP_MEDIA_IMAGES_ENTRY_SLUG', 'view');
|
15 |
+
define('BP_MEDIA_IMAGES_EDIT_SLUG', 'edit');
|
16 |
+
|
17 |
+
define('BP_MEDIA_VIDEOS_SLUG', 'videos');
|
18 |
+
define('BP_MEDIA_VIDEOS_ENTRY_SLUG', 'watch');
|
19 |
+
define('BP_MEDIA_VIDEOS_EDIT_SLUG', 'edit');
|
20 |
+
|
21 |
+
define('BP_MEDIA_AUDIO_SLUG', 'audio');
|
22 |
+
define('BP_MEDIA_AUDIO_ENTRY_SLUG', 'listen');
|
23 |
+
define('BP_MEDIA_AUDIO_EDIT_SLUG', 'edit');
|
24 |
+
|
25 |
+
/* Label Constants(need to be translatable) */
|
26 |
+
define('BP_MEDIA_LABEL', __('Media', 'bp-media'));
|
27 |
+
define('BP_MEDIA_LABEL_SINGULAR', __('Media', 'bp-media'));
|
28 |
+
define('BP_MEDIA_IMAGES_LABEL', __('Images', 'bp-media'));
|
29 |
+
define('BP_MEDIA_IMAGES_LABEL_SINGULAR', __('Image', 'bp-media'));
|
30 |
+
define('BP_MEDIA_VIDEOS_LABEL', __('Videos', 'bp-media'));
|
31 |
+
define('BP_MEDIA_VIDEOS_LABEL_SINGULAR', __('Video', 'bp-media'));
|
32 |
+
define('BP_MEDIA_AUDIO_LABEL', __('Audio', 'bp-media'));
|
33 |
+
define('BP_MEDIA_AUDIO_LABEL_SINGULAR', __('Audio', 'bp-media'));
|
34 |
+
define('BP_MEDIA_UPLOAD_LABEL', __('Upload', 'bp-media'));
|
35 |
+
|
36 |
+
/* Global variable to store the query */
|
37 |
+
global $bp_media_query;
|
38 |
+
|
39 |
+
/* Global variable for making distinct ids for different media objects in activity stream */
|
40 |
+
global $bp_media_counter;
|
41 |
+
$bp_media_counter = 0;
|
42 |
+
|
43 |
+
/* Global variable storing the count of the media files displayed user has */
|
44 |
+
global $bp_media_count;
|
45 |
+
$bp_media_count=null;
|
46 |
+
|
47 |
+
/* Global variable for various display sizes */
|
48 |
+
global $bp_media_default_sizes;
|
49 |
+
$bp_media_default_sizes = array(
|
50 |
+
'activity_image' => array(
|
51 |
+
'width' => 320,
|
52 |
+
'height' => 240
|
53 |
+
),
|
54 |
+
'activity_video' => array(
|
55 |
+
'width' => 320,
|
56 |
+
'height' => 240
|
57 |
+
),
|
58 |
+
'activity_audio' => array(
|
59 |
+
'width' => 320,
|
60 |
+
),
|
61 |
+
'single_image' => array(
|
62 |
+
'width' => 800,
|
63 |
+
'height' => 0
|
64 |
+
),
|
65 |
+
'single_video' => array(
|
66 |
+
'width' => 640,
|
67 |
+
'height' => 480
|
68 |
+
),
|
69 |
+
'single_audio' => array(
|
70 |
+
'width' => 640,
|
71 |
+
),
|
72 |
+
);
|
73 |
+
|
74 |
+
/* Global variable to store various excerpt sizes */
|
75 |
+
global $bp_media_default_excerpts;
|
76 |
+
$bp_media_default_excerpts=array(
|
77 |
+
'single_entry_title' => 100,
|
78 |
+
'single_entry_description' => 500,
|
79 |
+
'activity_entry_title' => 50,
|
80 |
+
'activity_entry_description'=> 500
|
81 |
+
);
|
82 |
+
|
83 |
+
/* To set the language according to the locale selected and availability of the language file. */
|
84 |
+
if (file_exists(BP_MEDIA_PLUGIN_DIR . '/languages/' . get_locale() . '.mo'))
|
85 |
+
load_textdomain('bp-media', BP_MEDIA_PLUGIN_DIR . '/languages/' . get_locale() . '.mo');
|
86 |
+
|
87 |
+
/**
|
88 |
+
* BP Media Component Class, extends BP_Component
|
89 |
+
*
|
90 |
+
* @see BP_Component
|
91 |
+
*
|
92 |
+
* @since BP Media 2.0
|
93 |
+
*/
|
94 |
+
class BP_Media_Component extends BP_Component {
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Hold the messages generated during initialization process and will be shown on the screen functions
|
98 |
+
*
|
99 |
+
* @since BP Media 2.0
|
100 |
+
*/
|
101 |
+
var $messages = array(
|
102 |
+
'error' => array(),
|
103 |
+
'info' => array(),
|
104 |
+
'updated' => array()
|
105 |
+
);
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Constructor for the BuddyPress Media Component
|
109 |
+
*
|
110 |
+
* @since BP Media 2.0
|
111 |
+
*/
|
112 |
+
function __construct() {
|
113 |
+
global $bp;
|
114 |
+
parent::start(BP_MEDIA_SLUG, BP_MEDIA_LABEL, BP_MEDIA_PLUGIN_DIR);
|
115 |
+
$this->includes();
|
116 |
+
$bp->active_components[$this->id] = '1';
|
117 |
+
add_action('init', array(&$this, 'register_post_types'));
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Includes the files required for the BuddyPress Media Component and calls the parent class' includes function
|
122 |
+
*
|
123 |
+
* @since BP Media 2.0
|
124 |
+
*/
|
125 |
+
function includes() {
|
126 |
+
$includes = array(
|
127 |
+
'includes/bp-media-screens.php',
|
128 |
+
'includes/bp-media-functions.php',
|
129 |
+
'includes/bp-media-filters.php',
|
130 |
+
'includes/bp-media-template-functions.php',
|
131 |
+
'includes/bp-media-actions.php',
|
132 |
+
'includes/bp-media-interface.php',
|
133 |
+
'includes/bp-media-class-wordpress.php',
|
134 |
+
'includes/bp-media-shortcodes.php'
|
135 |
+
);
|
136 |
+
if (is_admin() || is_network_admin()) {
|
137 |
+
$includes[] = 'includes/bp-media-admin.php';
|
138 |
+
}
|
139 |
+
parent::includes($includes);
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Initializes the global variables of the BuddyPress Media component and its parent class.
|
144 |
+
*/
|
145 |
+
function setup_globals() {
|
146 |
+
global $bp;
|
147 |
+
$globals = array(
|
148 |
+
'slug' => BP_MEDIA_SLUG,
|
149 |
+
'root_slug' => isset($bp->pages->{$this->id}->slug) ? $bp->pages->{$this->id}->slug : BP_MEDIA_SLUG,
|
150 |
+
/*'has_directory' => true, /* Set to false if not required */
|
151 |
+
'search_string' => __('Search Media...', 'bp-media'),
|
152 |
+
);
|
153 |
+
parent::setup_globals($globals);
|
154 |
+
}
|
155 |
+
|
156 |
+
function setup_nav() {
|
157 |
+
/* Add 'Media' to the main navigation */
|
158 |
+
if (bp_is_my_profile()) {
|
159 |
+
$main_nav = array(
|
160 |
+
'name' => BP_MEDIA_LABEL,
|
161 |
+
'slug' => BP_MEDIA_SLUG,
|
162 |
+
'position' => 80,
|
163 |
+
'screen_function' => 'bp_media_upload_screen',
|
164 |
+
'default_subnav_slug' => BP_MEDIA_UPLOAD_SLUG
|
165 |
+
);
|
166 |
+
} else {
|
167 |
+
$main_nav = array(
|
168 |
+
'name' => BP_MEDIA_LABEL,
|
169 |
+
'slug' => BP_MEDIA_SLUG,
|
170 |
+
'position' => 80,
|
171 |
+
'screen_function' => 'bp_media_images_screen',
|
172 |
+
'default_subnav_slug' => BP_MEDIA_IMAGES_SLUG
|
173 |
+
);
|
174 |
+
}
|
175 |
+
$sub_nav[] = array(
|
176 |
+
'name' => BP_MEDIA_UPLOAD_LABEL,
|
177 |
+
'slug' => BP_MEDIA_UPLOAD_SLUG,
|
178 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_SLUG),
|
179 |
+
'parent_slug' => BP_MEDIA_SLUG,
|
180 |
+
'screen_function' => 'bp_media_upload_screen',
|
181 |
+
'position' => 10,
|
182 |
+
'user_has_access' => bp_is_my_profile()
|
183 |
+
);
|
184 |
+
parent::setup_nav($main_nav, $sub_nav);
|
185 |
+
|
186 |
+
bp_core_new_nav_item(array(
|
187 |
+
'name' => BP_MEDIA_IMAGES_LABEL,
|
188 |
+
'slug' => BP_MEDIA_IMAGES_SLUG,
|
189 |
+
'screen_function' => 'bp_media_images_screen'
|
190 |
+
));
|
191 |
+
|
192 |
+
bp_core_new_nav_item(array(
|
193 |
+
'name' => BP_MEDIA_VIDEOS_LABEL,
|
194 |
+
'slug' => BP_MEDIA_VIDEOS_SLUG,
|
195 |
+
'screen_function' => 'bp_media_videos_screen'
|
196 |
+
));
|
197 |
+
|
198 |
+
bp_core_new_nav_item(array(
|
199 |
+
'name' => BP_MEDIA_AUDIO_LABEL,
|
200 |
+
'slug' => BP_MEDIA_AUDIO_SLUG,
|
201 |
+
'screen_function' => 'bp_media_audio_screen'
|
202 |
+
));
|
203 |
+
|
204 |
+
bp_core_new_subnav_item(array(
|
205 |
+
'name' => 'Listen', /* Display name for the nav item(It won't be shown anywhere) */
|
206 |
+
'slug' => BP_MEDIA_AUDIO_ENTRY_SLUG, /* URL slug for the nav item */
|
207 |
+
'parent_slug' => BP_MEDIA_AUDIO_SLUG, /* URL slug of the parent nav item */
|
208 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_AUDIO_SLUG), /* URL of the parent item */
|
209 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
210 |
+
'screen_function' => 'bp_media_audio_screen', /* The name of the function to run when clicked */
|
211 |
+
));
|
212 |
+
|
213 |
+
bp_core_new_subnav_item(array(
|
214 |
+
'name' => 'Watch', /* Display name for the nav item(It won't be shown anywhere) */
|
215 |
+
'slug' => BP_MEDIA_VIDEOS_ENTRY_SLUG, /* URL slug for the nav item */
|
216 |
+
'parent_slug' => BP_MEDIA_VIDEOS_SLUG, /* URL slug of the parent nav item */
|
217 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_VIDEOS_SLUG), /* URL of the parent item */
|
218 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
219 |
+
'screen_function' => 'bp_media_videos_screen', /* The name of the function to run when clicked */
|
220 |
+
));
|
221 |
+
|
222 |
+
bp_core_new_subnav_item(array(
|
223 |
+
'name' => 'View', /* Display name for the nav item(It won't be shown anywhere) */
|
224 |
+
'slug' => BP_MEDIA_IMAGES_ENTRY_SLUG, /* URL slug for the nav item */
|
225 |
+
'parent_slug' => BP_MEDIA_IMAGES_SLUG, /* URL slug of the parent nav item */
|
226 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_IMAGES_SLUG), /* URL of the parent item */
|
227 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
228 |
+
'screen_function' => 'bp_media_images_screen', /* The name of the function to run when clicked */
|
229 |
+
));
|
230 |
+
|
231 |
+
bp_core_new_subnav_item(array(
|
232 |
+
'name' => 'Edit', /* Display name for the nav item(It won't be shown anywhere) */
|
233 |
+
'slug' => BP_MEDIA_IMAGES_EDIT_SLUG, /* URL slug for the nav item */
|
234 |
+
'parent_slug' => BP_MEDIA_IMAGES_SLUG, /* URL slug of the parent nav item */
|
235 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_IMAGES_SLUG), /* URL of the parent item */
|
236 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
237 |
+
'screen_function' => 'bp_media_images_edit_screen', /* The name of the function to run when clicked */
|
238 |
+
));
|
239 |
+
|
240 |
+
bp_core_new_subnav_item(array(
|
241 |
+
'name' => 'Edit', /* Display name for the nav item(It won't be shown anywhere) */
|
242 |
+
'slug' => BP_MEDIA_AUDIO_EDIT_SLUG, /* URL slug for the nav item */
|
243 |
+
'parent_slug' => BP_MEDIA_AUDIO_SLUG, /* URL slug of the parent nav item */
|
244 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_AUDIO_SLUG), /* URL of the parent item */
|
245 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
246 |
+
'screen_function' => 'bp_media_audio_edit_screen', /* The name of the function to run when clicked */
|
247 |
+
));
|
248 |
+
|
249 |
+
bp_core_new_subnav_item(array(
|
250 |
+
'name' => 'Edit', /* Display name for the nav item(It won't be shown anywhere) */
|
251 |
+
'slug' => BP_MEDIA_VIDEOS_EDIT_SLUG, /* URL slug for the nav item */
|
252 |
+
'parent_slug' => BP_MEDIA_VIDEOS_SLUG, /* URL slug of the parent nav item */
|
253 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_VIDEOS_SLUG), /* URL of the parent item */
|
254 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
255 |
+
'screen_function' => 'bp_media_videos_edit_screen', /* The name of the function to run when clicked */
|
256 |
+
));
|
257 |
+
|
258 |
+
bp_core_new_subnav_item(array(
|
259 |
+
'name' => 'Page', /* Display name for the nav item(It won't be shown anywhere) */
|
260 |
+
'slug' => 'page', /* URL slug for the nav item */
|
261 |
+
'parent_slug' => BP_MEDIA_IMAGES_SLUG, /* URL slug of the parent nav item */
|
262 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_IMAGES_SLUG), /* URL of the parent item */
|
263 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
264 |
+
'screen_function' => 'bp_media_images_screen', /* The name of the function to run when clicked */
|
265 |
+
));
|
266 |
+
|
267 |
+
bp_core_new_subnav_item(array(
|
268 |
+
'name' => 'Page', /* Display name for the nav item(It won't be shown anywhere) */
|
269 |
+
'slug' => 'page', /* URL slug for the nav item */
|
270 |
+
'parent_slug' => BP_MEDIA_AUDIO_SLUG, /* URL slug of the parent nav item */
|
271 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_AUDIO_SLUG), /* URL of the parent item */
|
272 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
273 |
+
'screen_function' => 'bp_media_audio_screen', /* The name of the function to run when clicked */
|
274 |
+
));
|
275 |
+
|
276 |
+
bp_core_new_subnav_item(array(
|
277 |
+
'name' => 'Page', /* Display name for the nav item(It won't be shown anywhere) */
|
278 |
+
'slug' => 'page', /* URL slug for the nav item */
|
279 |
+
'parent_slug' => BP_MEDIA_VIDEOS_SLUG, /* URL slug of the parent nav item */
|
280 |
+
'parent_url' => trailingslashit(bp_loggedin_user_domain() . BP_MEDIA_VIDEOS_SLUG), /* URL of the parent item */
|
281 |
+
'position' => 90, /* Index of where this nav item should be positioned */
|
282 |
+
'screen_function' => 'bp_media_videos_screen', /* The name of the function to run when clicked */
|
283 |
+
));
|
284 |
+
}
|
285 |
+
|
286 |
+
function register_post_types() {
|
287 |
+
/* Set up labels for the post type */
|
288 |
+
$labels = array(
|
289 |
+
'name' => __('Media', 'bp-media'),
|
290 |
+
'singular' => __('Media', 'bp-media'),
|
291 |
+
'add_new' => __('Add New Media', 'bp-media')
|
292 |
+
);
|
293 |
+
|
294 |
+
/* Set up the argument array for register_post_type() */
|
295 |
+
$args = array(
|
296 |
+
'label' => __('Media', 'bp-media'),
|
297 |
+
'labels' => $labels,
|
298 |
+
'description' => 'BuddyPress Media Component\'s Media Files',
|
299 |
+
'public' => true,
|
300 |
+
'show_ui' => false,
|
301 |
+
'supports' => array('title', 'editor', 'excerpt', 'author', 'thumbnail', 'custom-fields')
|
302 |
+
);
|
303 |
+
register_post_type('bp_media', $args);
|
304 |
+
parent::register_post_types();
|
305 |
+
}
|
306 |
+
}
|
307 |
+
|
308 |
+
function bp_media_load_core_component() {
|
309 |
+
global $bp;
|
310 |
+
|
311 |
+
$bp->{BP_MEDIA_SLUG} = new BP_Media_Component();
|
312 |
+
}
|
313 |
+
add_action('bp_loaded', 'bp_media_load_core_component');
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Function to set the custom navigation system in effect.
|
317 |
+
*/
|
318 |
+
function bp_media_custom_nav() {
|
319 |
+
global $bp;
|
320 |
+
foreach ($bp->bp_nav as $key => $nav_item) {
|
321 |
+
if ($nav_item['slug'] == BP_MEDIA_IMAGES_SLUG || $nav_item['slug'] == BP_MEDIA_VIDEOS_SLUG || $nav_item['slug'] == BP_MEDIA_AUDIO_SLUG) {
|
322 |
+
$bp->bp_options_nav[BP_MEDIA_SLUG][] = array(
|
323 |
+
'name' => $nav_item['name'],
|
324 |
+
'link' => (isset($bp->displayed_user->domain) ? $bp->displayed_user->domain : (isset($bp->loggedin_user->domain) ? $bp->loggedin_user->domain : '')) . $nav_item['slug'] . '/',
|
325 |
+
'slug' => $nav_item['slug'],
|
326 |
+
'css_id' => $nav_item['css_id'],
|
327 |
+
'position' => $nav_item['position'],
|
328 |
+
'screen_function' => $nav_item['screen_function'],
|
329 |
+
'user_has_access' => true,
|
330 |
+
'parent_url' => trailingslashit(bp_displayed_user_domain())
|
331 |
+
);
|
332 |
+
unset($bp->bp_nav[$key]);
|
333 |
+
}
|
334 |
+
}
|
335 |
+
if ($bp->current_component == BP_MEDIA_IMAGES_SLUG || $bp->current_component == BP_MEDIA_VIDEOS_SLUG || $bp->current_component == BP_MEDIA_AUDIO_SLUG) {
|
336 |
+
$count = count($bp->action_variables);
|
337 |
+
for ($i = $count; $i > 0; $i--) {
|
338 |
+
$bp->action_variables[$i] = $bp->action_variables[$i - 1];
|
339 |
+
}
|
340 |
+
$bp->action_variables[0] = $bp->current_action;
|
341 |
+
$bp->current_action = $bp->current_component;
|
342 |
+
$bp->current_component = BP_MEDIA_SLUG;
|
343 |
+
}
|
344 |
+
}
|
345 |
+
add_action('bp_setup_nav', 'bp_media_custom_nav', 999);
|
346 |
+
|
347 |
+
function bp_media_thumbnail() {
|
348 |
+
global $bp_media_default_sizes;
|
349 |
+
add_image_size('bp_media_activity_image', $bp_media_default_sizes['activity_image']['width'], $bp_media_default_sizes['activity_image']['height'], true);
|
350 |
+
add_image_size('bp_media_single_image', $bp_media_default_sizes['single_image']['width'], $bp_media_default_sizes['single_image']['height'], true);
|
351 |
+
}
|
352 |
+
add_action('after_setup_theme', 'bp_media_thumbnail');
|
353 |
+
?>
|
includes/bp-media-screens.php
ADDED
@@ -0,0 +1,337 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Screens for all the slugs defined in the BuddyPress Media Component
|
5 |
+
*/
|
6 |
+
|
7 |
+
/* Exit if accessed directlly. */
|
8 |
+
if (!defined('ABSPATH'))
|
9 |
+
exit;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Screen function for Upload page
|
13 |
+
*/
|
14 |
+
function bp_media_upload_screen() {
|
15 |
+
add_action('bp_template_title', 'bp_media_upload_screen_title');
|
16 |
+
add_action('bp_template_content', 'bp_media_upload_screen_content');
|
17 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
18 |
+
}
|
19 |
+
|
20 |
+
function bp_media_upload_screen_title() {
|
21 |
+
_e('Upload Page');
|
22 |
+
}
|
23 |
+
|
24 |
+
function bp_media_upload_screen_content() {
|
25 |
+
do_action('bp_media_before_content');
|
26 |
+
bp_media_show_upload_form();
|
27 |
+
do_action('bp_media_after_content');
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Screen function for Images listing page (Default)
|
32 |
+
*/
|
33 |
+
function bp_media_images_screen() {
|
34 |
+
global $bp;
|
35 |
+
if (isset($bp->action_variables[0])) {
|
36 |
+
switch ($bp->action_variables[0]) {
|
37 |
+
case BP_MEDIA_IMAGES_EDIT_SLUG :
|
38 |
+
bp_media_images_edit_screen();
|
39 |
+
break;
|
40 |
+
case BP_MEDIA_IMAGES_ENTRY_SLUG:
|
41 |
+
global $bp_media_current_entry;
|
42 |
+
if (!$bp->action_variables[0] == BP_MEDIA_IMAGES_ENTRY_SLUG)
|
43 |
+
return false;
|
44 |
+
try {
|
45 |
+
$bp_media_current_entry = new BP_Media_Host_Wordpress($bp->action_variables[1]);
|
46 |
+
} catch (Exception $e) {
|
47 |
+
/* Send the values to the cookie for page reload display */
|
48 |
+
@setcookie('bp-message', $_COOKIE['bp-message'], time() + 60 * 60 * 24, COOKIEPATH);
|
49 |
+
@setcookie('bp-message-type', $_COOKIE['bp-message-type'], time() + 60 * 60 * 24, COOKIEPATH);
|
50 |
+
wp_redirect(trailingslashit(bp_displayed_user_domain() . BP_MEDIA_IMAGES_SLUG));
|
51 |
+
exit;
|
52 |
+
}
|
53 |
+
add_action('bp_template_content', 'bp_media_images_entry_screen_content');
|
54 |
+
break;
|
55 |
+
default:
|
56 |
+
bp_media_set_query();
|
57 |
+
add_action('bp_template_content', 'bp_media_images_screen_content');
|
58 |
+
}
|
59 |
+
} else {
|
60 |
+
bp_media_set_query();
|
61 |
+
add_action('bp_template_content', 'bp_media_images_screen_content');
|
62 |
+
}
|
63 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
64 |
+
}
|
65 |
+
|
66 |
+
function bp_media_images_screen_title() {
|
67 |
+
_e('Images List Page');
|
68 |
+
}
|
69 |
+
|
70 |
+
function bp_media_images_screen_content() {
|
71 |
+
global $bp_media_query;
|
72 |
+
if ($bp_media_query && $bp_media_query->have_posts()):
|
73 |
+
bp_media_show_pagination();
|
74 |
+
do_action('bp_media_before_content');
|
75 |
+
echo '<ul id="groups-list" class="bp-media-gallery item-list">';
|
76 |
+
while ($bp_media_query->have_posts()) : $bp_media_query->the_post();
|
77 |
+
bp_media_the_content();
|
78 |
+
endwhile;
|
79 |
+
echo '</ul>';
|
80 |
+
do_action('bp_media_after_content');
|
81 |
+
bp_media_show_pagination('bottom');
|
82 |
+
else:
|
83 |
+
bp_media_show_formatted_error_message(__('Sorry, no images were found.', 'bp-media'), 'info');
|
84 |
+
endif;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Screen function for Images Edit page
|
89 |
+
*/
|
90 |
+
function bp_media_images_edit_screen() {
|
91 |
+
if (bp_loggedin_user_id() != bp_displayed_user_id()) {
|
92 |
+
bp_core_no_access(array(
|
93 |
+
'message' => __('You do not have access to this page.', 'buddypress'),
|
94 |
+
'root' => bp_displayed_user_domain(),
|
95 |
+
'redirect' => false
|
96 |
+
));
|
97 |
+
exit;
|
98 |
+
}
|
99 |
+
add_action('bp_template_title', 'bp_media_images_edit_screen_title');
|
100 |
+
add_action('bp_template_content', 'bp_media_images_edit_screen_content');
|
101 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
102 |
+
}
|
103 |
+
|
104 |
+
function bp_media_images_edit_screen_title() {
|
105 |
+
_e('Images Edit Page');
|
106 |
+
}
|
107 |
+
|
108 |
+
function bp_media_images_edit_screen_content() {
|
109 |
+
global $bp;
|
110 |
+
_e('Images Edit Page Content');
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Screen function for Images Entry page
|
115 |
+
*/
|
116 |
+
function bp_media_images_entry_screen() {
|
117 |
+
add_action('bp_template_title', 'bp_media_images_entry_screen_title');
|
118 |
+
add_action('bp_template_content', 'bp_media_images_entry_screen_content');
|
119 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
120 |
+
}
|
121 |
+
|
122 |
+
function bp_media_images_entry_screen_title() {
|
123 |
+
_e('Images Entry Page');
|
124 |
+
}
|
125 |
+
|
126 |
+
function bp_media_images_entry_screen_content() {
|
127 |
+
global $bp, $bp_media_current_entry;
|
128 |
+
if (!$bp->action_variables[0] == BP_MEDIA_IMAGES_ENTRY_SLUG)
|
129 |
+
return false;
|
130 |
+
do_action('bp_media_before_content');
|
131 |
+
echo '<div class="bp-media-single bp-media-image">';
|
132 |
+
echo $bp_media_current_entry->get_media_single_content();
|
133 |
+
echo $bp_media_current_entry->show_comment_form();
|
134 |
+
echo '</div>';
|
135 |
+
do_action('bp_media_after_content');
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Screen function for Videos listing page (Default)
|
140 |
+
*/
|
141 |
+
function bp_media_videos_screen() {
|
142 |
+
global $bp;
|
143 |
+
if (isset($bp->action_variables[0])) {
|
144 |
+
switch ($bp->action_variables[0]) {
|
145 |
+
case BP_MEDIA_VIDEOS_EDIT_SLUG :
|
146 |
+
add_action('bp_template_content', 'bp_media_videos_edit_screen_content');
|
147 |
+
break;
|
148 |
+
case BP_MEDIA_VIDEOS_ENTRY_SLUG:
|
149 |
+
global $bp_media_current_entry;
|
150 |
+
if (!$bp->action_variables[0] == BP_MEDIA_IMAGES_ENTRY_SLUG)
|
151 |
+
return false;
|
152 |
+
try {
|
153 |
+
$bp_media_current_entry = new BP_Media_Host_Wordpress($bp->action_variables[1]);
|
154 |
+
} catch (Exception $e) {
|
155 |
+
/* Send the values to the cookie for page reload display */
|
156 |
+
@setcookie('bp-message', $_COOKIE['bp-message'], time() + 60 * 60 * 24, COOKIEPATH);
|
157 |
+
@setcookie('bp-message-type', $_COOKIE['bp-message-type'], time() + 60 * 60 * 24, COOKIEPATH);
|
158 |
+
wp_redirect(trailingslashit(bp_displayed_user_domain() . BP_MEDIA_VIDEOS_SLUG));
|
159 |
+
exit;
|
160 |
+
}
|
161 |
+
add_action('bp_template_content', 'bp_media_videos_entry_screen_content');
|
162 |
+
break;
|
163 |
+
default:
|
164 |
+
bp_media_set_query();
|
165 |
+
add_action('bp_template_content', 'bp_media_videos_screen_content');
|
166 |
+
}
|
167 |
+
} else {
|
168 |
+
bp_media_set_query();
|
169 |
+
add_action('bp_template_content', 'bp_media_videos_screen_content');
|
170 |
+
}
|
171 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
172 |
+
}
|
173 |
+
|
174 |
+
function bp_media_videos_screen_title() {
|
175 |
+
_e('Videos List Page');
|
176 |
+
}
|
177 |
+
|
178 |
+
function bp_media_videos_screen_content() {
|
179 |
+
global $bp_media_query;
|
180 |
+
if ($bp_media_query && $bp_media_query->have_posts()):
|
181 |
+
bp_media_show_pagination();
|
182 |
+
do_action('bp_media_before_content');
|
183 |
+
echo '<ul class="bp-media-gallery">';
|
184 |
+
while ($bp_media_query->have_posts()) : $bp_media_query->the_post();
|
185 |
+
bp_media_the_content();
|
186 |
+
endwhile;
|
187 |
+
echo '</ul>';
|
188 |
+
do_action('bp_media_after_content');
|
189 |
+
bp_media_show_pagination('bottom');
|
190 |
+
else:
|
191 |
+
bp_media_show_formatted_error_message(__('Sorry, no videos were found.', 'bp-media'), 'info');
|
192 |
+
endif;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Screen function for Videos Edit page
|
197 |
+
*/
|
198 |
+
function bp_media_videos_edit_screen() {
|
199 |
+
add_action('bp_template_title', 'bp_media_videos_edit_screen_title');
|
200 |
+
add_action('bp_template_content', 'bp_media_videos_edit_screen_content');
|
201 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
202 |
+
}
|
203 |
+
|
204 |
+
function bp_media_videos_edit_screen_title() {
|
205 |
+
_e('Videos Edit Page');
|
206 |
+
}
|
207 |
+
|
208 |
+
function bp_media_videos_edit_screen_content() {
|
209 |
+
global $bp;
|
210 |
+
_e('Videos Edit Page Content');
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Screen function for Videos Entry page
|
215 |
+
*/
|
216 |
+
function bp_media_videos_entry_screen() {
|
217 |
+
add_action('bp_template_title', 'bp_media_videos_entry_screen_title');
|
218 |
+
add_action('bp_template_content', 'bp_media_videos_entry_screen_content');
|
219 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
220 |
+
}
|
221 |
+
|
222 |
+
function bp_media_videos_entry_screen_title() {
|
223 |
+
_e('Videos Entry Page');
|
224 |
+
}
|
225 |
+
|
226 |
+
function bp_media_videos_entry_screen_content() {
|
227 |
+
global $bp, $bp_media_current_entry;
|
228 |
+
if (!$bp->action_variables[0] == BP_MEDIA_VIDEOS_ENTRY_SLUG)
|
229 |
+
return false;
|
230 |
+
do_action('bp_media_before_content');
|
231 |
+
echo '<div class="bp-media-single bp-media-video">';
|
232 |
+
echo $bp_media_current_entry->get_media_single_content();
|
233 |
+
echo $bp_media_current_entry->show_comment_form();
|
234 |
+
echo '</div>';
|
235 |
+
do_action('bp_media_after_content');
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Screen function for Audio listing page (Default)
|
240 |
+
*/
|
241 |
+
function bp_media_audio_screen() {
|
242 |
+
global $bp;
|
243 |
+
if (isset($bp->action_variables[0])) {
|
244 |
+
switch ($bp->action_variables[0]) {
|
245 |
+
case BP_MEDIA_AUDIO_EDIT_SLUG :
|
246 |
+
add_action('bp_template_content', 'bp_media_audio_edit_screen_content');
|
247 |
+
break;
|
248 |
+
case BP_MEDIA_AUDIO_ENTRY_SLUG:
|
249 |
+
global $bp_media_current_entry;
|
250 |
+
if (!$bp->action_variables[0] == BP_MEDIA_IMAGES_ENTRY_SLUG)
|
251 |
+
return false;
|
252 |
+
try {
|
253 |
+
$bp_media_current_entry = new BP_Media_Host_Wordpress($bp->action_variables[1]);
|
254 |
+
} catch (Exception $e) {
|
255 |
+
/* Send the values to the cookie for page reload display */
|
256 |
+
@setcookie('bp-message', $_COOKIE['bp-message'], time() + 60 * 60 * 24, COOKIEPATH);
|
257 |
+
@setcookie('bp-message-type', $_COOKIE['bp-message-type'], time() + 60 * 60 * 24, COOKIEPATH);
|
258 |
+
wp_redirect(trailingslashit(bp_displayed_user_domain() . BP_MEDIA_AUDIO_SLUG));
|
259 |
+
exit;
|
260 |
+
}
|
261 |
+
add_action('bp_template_content', 'bp_media_audio_entry_screen_content');
|
262 |
+
break;
|
263 |
+
default:
|
264 |
+
bp_media_set_query();
|
265 |
+
add_action('bp_template_content', 'bp_media_audio_screen_content');
|
266 |
+
}
|
267 |
+
} else {
|
268 |
+
bp_media_set_query();
|
269 |
+
add_action('bp_template_content', 'bp_media_audio_screen_content');
|
270 |
+
}
|
271 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
272 |
+
}
|
273 |
+
|
274 |
+
function bp_media_audio_screen_title() {
|
275 |
+
_e('Audio List Page');
|
276 |
+
}
|
277 |
+
|
278 |
+
function bp_media_audio_screen_content() {
|
279 |
+
global $bp_media_query;
|
280 |
+
if ($bp_media_query && $bp_media_query->have_posts()):
|
281 |
+
bp_media_show_pagination();
|
282 |
+
do_action('bp_media_before_content');
|
283 |
+
echo '<ul class="bp-media-gallery">';
|
284 |
+
while ($bp_media_query->have_posts()) : $bp_media_query->the_post();
|
285 |
+
bp_media_the_content();
|
286 |
+
endwhile;
|
287 |
+
echo '</ul>';
|
288 |
+
do_action('bp_media_after_content');
|
289 |
+
bp_media_show_pagination('bottom');
|
290 |
+
else:
|
291 |
+
bp_media_show_formatted_error_message(__('Sorry, no audio files were found.', 'bp-media'), 'info');
|
292 |
+
endif;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Screen function for Audio Edit page
|
297 |
+
*/
|
298 |
+
function bp_media_audio_edit_screen() {
|
299 |
+
add_action('bp_template_title', 'bp_media_audio_edit_screen_title');
|
300 |
+
add_action('bp_template_content', 'bp_media_audio_edit_screen_content');
|
301 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
302 |
+
}
|
303 |
+
|
304 |
+
function bp_media_audio_edit_screen_title() {
|
305 |
+
_e('Audio Edit Page');
|
306 |
+
}
|
307 |
+
|
308 |
+
function bp_media_audio_edit_screen_content() {
|
309 |
+
global $bp;
|
310 |
+
_e('Audio Edit Page Content');
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Screen function for Audio Entry page
|
315 |
+
*/
|
316 |
+
function bp_media_audio_entry_screen() {
|
317 |
+
add_action('bp_template_title', 'bp_media_audio_entry_screen_title');
|
318 |
+
add_action('bp_template_content', 'bp_media_audio_entry_screen_content');
|
319 |
+
bp_core_load_template(apply_filters('bp_core_template_plugin', 'members/single/plugins'));
|
320 |
+
}
|
321 |
+
|
322 |
+
function bp_media_audio_entry_screen_title() {
|
323 |
+
_e('Audio Entry Page');
|
324 |
+
}
|
325 |
+
|
326 |
+
function bp_media_audio_entry_screen_content() {
|
327 |
+
global $bp, $bp_media_current_entry;
|
328 |
+
if (!$bp->action_variables[0] == BP_MEDIA_AUDIO_ENTRY_SLUG)
|
329 |
+
return false;
|
330 |
+
do_action('bp_media_before_content');
|
331 |
+
echo '<div class="bp-media-single bp-media-audio">';
|
332 |
+
echo $bp_media_current_entry->get_media_single_content();
|
333 |
+
echo $bp_media_current_entry->show_comment_form();
|
334 |
+
echo '</div>';
|
335 |
+
do_action('bp_media_after_content');
|
336 |
+
}
|
337 |
+
?>
|
includes/bp-media-shortcodes.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Shortcode for generating the action of the activity
|
5 |
+
*/
|
6 |
+
function bp_media_shortcode_action($atts) {
|
7 |
+
extract(shortcode_atts(array(
|
8 |
+
'id' => '0'
|
9 |
+
), $atts)
|
10 |
+
);
|
11 |
+
$media=new BP_Media_Host_Wordpress($id);
|
12 |
+
return $media->get_media_activity_action();
|
13 |
+
}
|
14 |
+
//add_shortcode('bp_media_action', 'bp_media_shortcode_action');
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Shortcode for generationg the content of the activity
|
18 |
+
*/
|
19 |
+
function bp_media_shortcode_content($atts) {
|
20 |
+
extract(shortcode_atts(array(
|
21 |
+
'id' => '0'
|
22 |
+
), $atts)
|
23 |
+
);
|
24 |
+
$media=new BP_Media_Host_Wordpress($id);
|
25 |
+
return $media->get_media_activity_content();
|
26 |
+
}
|
27 |
+
//add_shortcode('bp_media_content', 'bp_media_shortcode_content');
|
28 |
+
|
29 |
+
function bp_media_shortcode_url($atts) {
|
30 |
+
extract(shortcode_atts(array(
|
31 |
+
'id' => '0'
|
32 |
+
), $atts)
|
33 |
+
);
|
34 |
+
$media=new BP_Media_Host_Wordpress($id);
|
35 |
+
return $media->get_media_activity_url();
|
36 |
+
}
|
37 |
+
//add_shortcode('bp_media_url','bp_media_shortcode_url');
|
38 |
+
?>
|
includes/bp-media-template-functions.php
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
function bp_media_show_upload_form() {
|
3 |
+
global $bp,$bp_media_default_excerpts;
|
4 |
+
?>
|
5 |
+
<form method="post" enctype="multipart/form-data" class="standard-form" id="bp-media-upload-form">
|
6 |
+
<label for="bp-media-upload-input-title"><?php _e('Media Title', 'bp-media'); ?></label><input id="bp-media-upload-input-title" type="text" name="bp_media_title" class="settings-input" maxlength="<?php echo max(array($bp_media_default_excerpts['single_entry_title'],$bp_media_default_excerpts['activity_entry_title'])) ?>" />
|
7 |
+
<label for="bp-media-upload-input-description"><?php _e('Media Description', 'bp-media'); ?></label><input id="bp-media-upload-input-description" type="text" name="bp_media_description" class="settings-input" maxlength="<?php echo max(array($bp_media_default_excerpts['single_entry_description'],$bp_media_default_excerpts['activity_entry_description'])) ?>" />
|
8 |
+
<label for="bp-media-upload-file"><?php _e('Select Media File', 'bp-media') ?> (Max File Size:<?php echo min(array(ini_get('upload_max_filesize'),ini_get('post_max_size'))); ?>)</label><input type="file" name="bp_media_file" id="bp-media-upload-file" />
|
9 |
+
<input type="hidden" name="action" value="wp_handle_upload" />
|
10 |
+
<div class="submit"><input type="submit" class="auto" value="Upload" /></div>
|
11 |
+
</form>
|
12 |
+
<?php
|
13 |
+
}
|
14 |
+
|
15 |
+
function bp_media_show_pagination($type = 'top') {
|
16 |
+
global $bp, $bp_media_paginated_links, $bp_media_query;
|
17 |
+
switch ($bp->current_action) {
|
18 |
+
case BP_MEDIA_IMAGES_SLUG :
|
19 |
+
$current = $bp_media_query->found_posts > 1 ? BP_MEDIA_IMAGES_LABEL : BP_MEDIA_IMAGES_LABEL_SINGULAR;
|
20 |
+
$current_single = BP_MEDIA_IMAGES_LABEL_SINGULAR;
|
21 |
+
break;
|
22 |
+
case BP_MEDIA_VIDEOS_SLUG :
|
23 |
+
$current = $bp_media_query->found_posts > 1 ? BP_MEDIA_VIDEOS_LABEL : BP_MEDIA_VIDEOS_LABEL_SINGULAR;
|
24 |
+
$current_single = BP_MEDIA_VIDEOS_LABEL_SINGULAR;
|
25 |
+
break;
|
26 |
+
case BP_MEDIA_AUDIO_SLUG :
|
27 |
+
$current = BP_MEDIA_AUDIO_LABEL;
|
28 |
+
$current_single = BP_MEDIA_AUDIO_LABEL_SINGULAR;
|
29 |
+
break;
|
30 |
+
default :
|
31 |
+
$current = BP_MEDIA_LABEL;
|
32 |
+
$current_single = BP_MEDIA_LABEL_SINGULAR;
|
33 |
+
}
|
34 |
+
$args = array(
|
35 |
+
'base' => trailingslashit(bp_displayed_user_domain() . $bp->current_action . '/') . '%_%',
|
36 |
+
'format' => 'page/%#%',
|
37 |
+
'total' => $bp_media_query->max_num_pages,
|
38 |
+
'current' => $bp_media_query->query_vars['paged'],
|
39 |
+
'type' => 'array',
|
40 |
+
'prev_text' => '←',
|
41 |
+
'next_text' => '→',
|
42 |
+
);
|
43 |
+
$start_num = intval($bp_media_query->query_vars['posts_per_page'] * ($bp_media_query->query_vars['paged'] - 1)) + 1;
|
44 |
+
$from_num = $start_num;
|
45 |
+
$to_num = $start_num + $bp_media_query->post_count - 1;
|
46 |
+
$total = $bp_media_query->found_posts;
|
47 |
+
$bp_media_paginated_links = paginate_links($args);
|
48 |
+
?>
|
49 |
+
<div id="pag-<?php echo $type; ?>" class="pagination no-ajax">
|
50 |
+
<div class="pag-count">
|
51 |
+
Viewing <?php echo $current_single ?> <?php echo $from_num ?> to <?php echo $to_num ?> (of <?php echo $total; ?> <?php echo $current ?>)
|
52 |
+
</div>
|
53 |
+
<div class="pagination-links">
|
54 |
+
<?php if(is_array($bp_media_paginated_links)) : foreach ($bp_media_paginated_links as $link) : ?>
|
55 |
+
<?php echo $link; ?>
|
56 |
+
<?php endforeach; endif; ?>
|
57 |
+
</div>
|
58 |
+
</div>
|
59 |
+
<?php
|
60 |
+
}
|
61 |
+
|
62 |
+
function bp_media_get_permalink($id = 0) {
|
63 |
+
if (is_object($id))
|
64 |
+
$media = $id;
|
65 |
+
else
|
66 |
+
$media = &get_post($id);
|
67 |
+
if (empty($media->ID))
|
68 |
+
return false;
|
69 |
+
if (!$media->post_type == 'bp_media')
|
70 |
+
return false;
|
71 |
+
switch (get_post_meta($media->ID, 'bp_media_type', true)) {
|
72 |
+
case 'video' :
|
73 |
+
return trailingslashit(bp_displayed_user_domain() . BP_MEDIA_VIDEOS_SLUG . '/watch/' . $media->ID);
|
74 |
+
break;
|
75 |
+
case 'audio' :
|
76 |
+
return trailingslashit(bp_displayed_user_domain() . BP_MEDIA_AUDIO_SLUG . '/listen/' . $media->ID);
|
77 |
+
break;
|
78 |
+
case 'image' :
|
79 |
+
return trailingslashit(bp_displayed_user_domain() . BP_MEDIA_IMAGES_SLUG . '/view/' . $media->ID);
|
80 |
+
break;
|
81 |
+
default :
|
82 |
+
return false;
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
function bp_media_the_permalink() {
|
87 |
+
echo apply_filters('bp_media_the_permalink', bp_media_get_permalink());
|
88 |
+
}
|
89 |
+
|
90 |
+
function bp_media_the_content($id = 0) {
|
91 |
+
if (is_object($id))
|
92 |
+
$media = $id;
|
93 |
+
else
|
94 |
+
$media = &get_post($id);
|
95 |
+
if (empty($media->ID))
|
96 |
+
return false;
|
97 |
+
if (!$media->post_type == 'bp_media')
|
98 |
+
return false;
|
99 |
+
$media = new BP_Media_Host_Wordpress($media->ID);
|
100 |
+
echo $media->get_media_gallery_content();
|
101 |
+
}
|
102 |
+
?>
|
includes/css/bp-media-admin.css
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Used on backend */
|
2 |
+
#wpbody-content div.metabox-fixed{
|
3 |
+
width: 22%;
|
4 |
+
margin-right: 10px;
|
5 |
+
clear: both;
|
6 |
+
}
|
7 |
+
#wpbody-content div.wrap.bp-media-admin{
|
8 |
+
overflow: hidden;
|
9 |
+
width: 76%;
|
10 |
+
}
|
11 |
+
#icon-bp-media{
|
12 |
+
background:url('../img/logo_medibp_32.png') no-repeat scroll 0 0 transparent;
|
13 |
+
}.bp-media-social{
|
14 |
+
background: url('../img/bp_media_social.png');
|
15 |
+
height: 35px;
|
16 |
+
width: 35px;
|
17 |
+
display: inline-block;
|
18 |
+
font-size: 0px;
|
19 |
+
margin-right:5px;
|
20 |
+
}
|
21 |
+
.bp-media-facebook{
|
22 |
+
background-position: 0px 0px;
|
23 |
+
}
|
24 |
+
.bp-media-facebook:hover{
|
25 |
+
background-position: 0px 36px;
|
26 |
+
}
|
27 |
+
.bp-media-twitter{
|
28 |
+
background-position: 80px 0px;
|
29 |
+
}
|
30 |
+
.bp-media-twitter:hover{
|
31 |
+
background-position: 80px 36px;
|
32 |
+
}
|
33 |
+
.bp-media-rss{
|
34 |
+
background-position: 35px 0px;
|
35 |
+
}
|
36 |
+
.bp-media-rss:hover{
|
37 |
+
background-position: 35px 36px;
|
38 |
+
}
|
39 |
+
|
includes/css/bp-media-style.css
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Default stylesheet for BuddyPress Media Component
|
3 |
+
*/
|
4 |
+
.bp_media_content img{
|
5 |
+
max-width:98%;
|
6 |
+
}
|
7 |
+
.bp_media_title {
|
8 |
+
display:block;
|
9 |
+
font-size:20px;
|
10 |
+
font-weight:bold;
|
11 |
+
}
|
12 |
+
.bp_media_description {
|
13 |
+
display:block;
|
14 |
+
}
|
15 |
+
ul.bp-media-gallery{
|
16 |
+
overflow:hidden;
|
17 |
+
}
|
18 |
+
ul.bp-media-gallery li{
|
19 |
+
float:left;
|
20 |
+
margin:1%;
|
21 |
+
width:18%;
|
22 |
+
border-bottom:none;
|
23 |
+
}
|
24 |
+
ul.bp-media-gallery li img{
|
25 |
+
max-width:150px;
|
26 |
+
width:100%;
|
27 |
+
height:auto;
|
28 |
+
-moz-box-shadow: 1px 1px 10px #a0a0a0;
|
29 |
+
-webkit-box-shadow: 1px 1px 10px #a0a0a0;
|
30 |
+
box-shadow: 1px 1px 10px #a0a0a0;
|
31 |
+
-moz-transition: box-shadow 0.2s linear;
|
32 |
+
-webkit-transition: box-shadow 0.2s linear;
|
33 |
+
transition: box-shadow 0.2s linear;
|
34 |
+
}
|
35 |
+
ul.bp-media-gallery li img:hover{
|
36 |
+
-moz-box-shadow: 1px 1px 10px #333;
|
37 |
+
-webkit-box-shadow: 1px 1px 10px #333;
|
38 |
+
box-shadow: 1px 1px 10px #333;
|
39 |
+
|
40 |
+
}
|
41 |
+
ul.bp-media-gallery h3{
|
42 |
+
max-width:150px;
|
43 |
+
overflow: hidden;
|
44 |
+
text-align: center;
|
45 |
+
font-size:110%;
|
46 |
+
white-space: nowrap;
|
47 |
+
height:20px;
|
48 |
+
}
|
49 |
+
ul.bp-media-gallery a{
|
50 |
+
width:150px;
|
51 |
+
}
|
52 |
+
.bp-media-single .activity-list .activity-content,.bp-media-single div.activity-comments{
|
53 |
+
margin-left:0;
|
54 |
+
}
|
55 |
+
li.media div.activity-content div.activity-inner p{
|
56 |
+
display:none;
|
57 |
+
}
|
58 |
+
div.bp_media_title{
|
59 |
+
margin-bottom:5px;
|
60 |
+
}
|
61 |
+
#bp-media-footer {
|
62 |
+
color: #4D4D4D;
|
63 |
+
text-align: center;
|
64 |
+
text-shadow: #FAFAFA 1px 1px 0;
|
65 |
+
}
|
includes/img/audio_thumb.png
ADDED
Binary file
|
includes/img/bp_media_social.png
ADDED
Binary file
|
includes/img/image_thumb.png
ADDED
Binary file
|
includes/img/logo_medibp_32.png
ADDED
Binary file
|
includes/img/video_thumb.png
ADDED
Binary file
|
includes/js/bp-media.js
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* BuddyPress Media Default JS
|
3 |
+
*/
|
4 |
+
|
5 |
+
function bp_media_create_element(id){
|
6 |
+
jQuery('#'+id).mediaelementplayer({
|
7 |
+
enableKeyboard: false,
|
8 |
+
startVolume: 1,
|
9 |
+
success: function(mediaElement,domElement){
|
10 |
+
var $thisMediaElement = (mediaElement.id) ? jQuery("#"+mediaElement.id) : jQuery(mediaElement);
|
11 |
+
$thisMediaElement.parents('.mejs-container').find(".mejs-volume-current").css("top","8px");
|
12 |
+
$thisMediaElement.parents('.mejs-container').find(".mejs-volume-handle").css("top","5px");
|
13 |
+
}
|
14 |
+
});
|
15 |
+
}
|
includes/lib/MP4Info.php
ADDED
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* MP4Info main class
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.1.20090611 $Id: MP4Info.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
class MP4Info {
|
21 |
+
// {{{ Audio codec types
|
22 |
+
const MP4_AUDIO_CODEC_UNCOMPRESSED = 0x00;
|
23 |
+
const MP4_AUDIO_CODEC_MP3 = 0x02;
|
24 |
+
const MP4_AUDIO_CODEC_AAC = 0xe0;
|
25 |
+
// }}}
|
26 |
+
|
27 |
+
// {{{ Video codec types
|
28 |
+
const MP4_VIDEO_CODEC_H264 = 0xe0;
|
29 |
+
// }}}
|
30 |
+
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Get information from MP4 file
|
34 |
+
*
|
35 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
36 |
+
* @param string $file
|
37 |
+
* @return array
|
38 |
+
* @access public
|
39 |
+
* @static
|
40 |
+
*/
|
41 |
+
public static function getInfo($file) {
|
42 |
+
// Open file
|
43 |
+
$f = fopen($file,'rb');
|
44 |
+
if (!$f) {
|
45 |
+
throw new Exception('Cannot open file: '.$file);
|
46 |
+
}
|
47 |
+
|
48 |
+
// Get all boxes
|
49 |
+
try {
|
50 |
+
while (($box = MP4Info_Box::fromStream($f))) {
|
51 |
+
$boxes[] = $box;
|
52 |
+
}
|
53 |
+
} catch (Exception $e) { }
|
54 |
+
|
55 |
+
// Close
|
56 |
+
fclose($f);
|
57 |
+
|
58 |
+
// Return info
|
59 |
+
return self::getInfoFromBoxes($boxes);
|
60 |
+
} // getInfo method
|
61 |
+
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Get information from MP4 boxes
|
65 |
+
*
|
66 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
67 |
+
* @param string $file
|
68 |
+
* @return array
|
69 |
+
* @access public
|
70 |
+
* @static
|
71 |
+
*/
|
72 |
+
public static function getInfoFromBoxes($boxes, &$context=null) {
|
73 |
+
if ($context === null) {
|
74 |
+
$context = new stdClass();
|
75 |
+
$context->hasVideo = false;
|
76 |
+
$context->hasAudio = false;
|
77 |
+
$context->video = new stdClass();
|
78 |
+
$context->audio = new stdClass();
|
79 |
+
}
|
80 |
+
|
81 |
+
foreach ($boxes as &$box) {
|
82 |
+
// Interpret box
|
83 |
+
switch ($box->getBoxTypeStr()) {
|
84 |
+
case 'hdlr':
|
85 |
+
switch ($box->getHandlerType()) {
|
86 |
+
case MP4Info_Box_hdlr::HANDLER_VIDEO:
|
87 |
+
$context->hasVideo = true;
|
88 |
+
break;
|
89 |
+
case MP4Info_Box_hdlr::HANDLER_SOUND:
|
90 |
+
$context->hasAudio = true;
|
91 |
+
break;
|
92 |
+
}
|
93 |
+
break;
|
94 |
+
case 'mvhd':
|
95 |
+
$context->duration = $box->getRealDuration();
|
96 |
+
break;
|
97 |
+
case 'ilst':
|
98 |
+
if ($box->hasValue('©too')) {
|
99 |
+
$context->encoder = $box->getValue('©too');
|
100 |
+
}
|
101 |
+
break;
|
102 |
+
case 'uuid':
|
103 |
+
$meta = $box->getXMPMetaData();
|
104 |
+
if ($meta !== false) {
|
105 |
+
// Try to get duration
|
106 |
+
if (!isset($context->duration)) {
|
107 |
+
if (preg_match('/<(|[a-z]+:)duration[\s\n\r]([^>]*)>/im',$meta,$m)) {
|
108 |
+
if (preg_match_all('/xmpDM:([a-z]+)="([^"]+)"/',$m[2],$mm)) {
|
109 |
+
$value = $scale = false;
|
110 |
+
foreach ($mm[1] as $k=>$v) {
|
111 |
+
if (($v == 'value') || ($v == 'scale')) {
|
112 |
+
if (preg_match('/^1\/([0-9]+)$/',$mm[2][$k],$mmm)) {
|
113 |
+
$mm[2][$k] = 1/$mmm[1];
|
114 |
+
}
|
115 |
+
$$v = $mm[2][$k];
|
116 |
+
}
|
117 |
+
}
|
118 |
+
if (($value !== false) && ($scale !== false)) {
|
119 |
+
$context->duration = $value*$scale;
|
120 |
+
}
|
121 |
+
}
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
// Try to get size
|
126 |
+
if ((!isset($context->width)) || (!isset($context->height))) {
|
127 |
+
if (preg_match('/<(|[a-z]+:)videoFrameSize[\s\n\r]([^>]*)>/im',$meta,$m)) {
|
128 |
+
if (preg_match_all('/[a-z]:([a-z]+)="([^"]+)"/',$m[2],$mm)) {
|
129 |
+
$w = $h = false;
|
130 |
+
foreach ($mm[1] as $k=>$v) {
|
131 |
+
if (($v == 'w') || ($v == 'h')) {
|
132 |
+
$$v = $mm[2][$k];
|
133 |
+
}
|
134 |
+
}
|
135 |
+
if ($w != false) {
|
136 |
+
$context->video->width = $w;
|
137 |
+
$context->hasVideo = true;
|
138 |
+
}
|
139 |
+
if ($h != false) {
|
140 |
+
$context->video->height = $h;
|
141 |
+
$context->hasVideo = true;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
// Try to get encoder
|
148 |
+
if (preg_match('/softwareAgent="([^"]+)"/i',$meta,$m)) {
|
149 |
+
$context->encoder = $m[1];
|
150 |
+
}
|
151 |
+
|
152 |
+
// Try to get audio channels
|
153 |
+
if (preg_match('/audioChannelType="([^"]+)"/i',$meta,$m)) {
|
154 |
+
switch (strtolower($m[1])) {
|
155 |
+
case 'stereo':
|
156 |
+
case '2':
|
157 |
+
$context->audio->channels = 2;
|
158 |
+
$context->hasAudio = true;
|
159 |
+
break;
|
160 |
+
case 'mono':
|
161 |
+
case '1':
|
162 |
+
$context->audio->channels = 1;
|
163 |
+
$context->hasAudio = true;
|
164 |
+
break;
|
165 |
+
case '5.1':
|
166 |
+
case '5':
|
167 |
+
$context->audio->channels = 5;
|
168 |
+
$context->hasAudio = true;
|
169 |
+
break;
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
+
// Try to get audio frequency
|
174 |
+
if (preg_match('/audioSampleRate="([^"]+)"/i',$meta,$m)) {
|
175 |
+
$context->audio->frequency = $m[1]/1000;
|
176 |
+
$context->hasAudio = true;
|
177 |
+
}
|
178 |
+
|
179 |
+
// Try to get video frame rate
|
180 |
+
if (preg_match('/videoFrameRate="([^"]+)"/i',$meta,$m)) {
|
181 |
+
$context->video->fps = $m[1];
|
182 |
+
$context->hasVideo = true;
|
183 |
+
}
|
184 |
+
|
185 |
+
//print htmlentities($meta);
|
186 |
+
}
|
187 |
+
break;
|
188 |
+
case 'stsd':
|
189 |
+
$values = $box->getValues();
|
190 |
+
foreach (array_keys($values) as $codec) {
|
191 |
+
switch ($codec) {
|
192 |
+
case '.mp3':
|
193 |
+
$context->audio->codec = self::MP4_AUDIO_CODEC_MP3;
|
194 |
+
$context->audio->codecStr = 'MP3';
|
195 |
+
$context->hasAudio = true;
|
196 |
+
break;
|
197 |
+
case 'mp4a':
|
198 |
+
case 'mp4s':
|
199 |
+
$context->audio->codec = self::MP4_AUDIO_CODEC_AAC;
|
200 |
+
$context->audio->codecStr = 'AAC';
|
201 |
+
$context->hasAudio = true;
|
202 |
+
break;
|
203 |
+
case 'avc1':
|
204 |
+
case 'h264':
|
205 |
+
case 'H264':
|
206 |
+
$context->video->codec = self::MP4_VIDEO_CODEC_H264;
|
207 |
+
$context->video->codecStr = 'H.264';
|
208 |
+
$context->hasVideo = true;
|
209 |
+
break;
|
210 |
+
}
|
211 |
+
}
|
212 |
+
break;
|
213 |
+
case 'tkhd':
|
214 |
+
if ($box->getWidth() > 0) {
|
215 |
+
$context->hasVideo = true;
|
216 |
+
$context->video->width = $box->getWidth();
|
217 |
+
$context->video->height = $box->getHeight();
|
218 |
+
$context->hasVideo = true;
|
219 |
+
}
|
220 |
+
break;
|
221 |
+
}
|
222 |
+
|
223 |
+
// Process children
|
224 |
+
if ($box->hasChildren()) {
|
225 |
+
self::getInfoFromBoxes($box->children(), $context);
|
226 |
+
}
|
227 |
+
}
|
228 |
+
|
229 |
+
return $context;
|
230 |
+
} // getInfoFromBoxes method
|
231 |
+
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Display boxes for debugging
|
235 |
+
*
|
236 |
+
* @param MP4Info_Box[] $boxes
|
237 |
+
* @param int $level
|
238 |
+
* @access public
|
239 |
+
* @static
|
240 |
+
*/
|
241 |
+
public static function displayBoxes($boxes,$level=0) {
|
242 |
+
foreach ($boxes as $box) {
|
243 |
+
print str_repeat(' ',$level*4) . $box->toString() . '<br>';
|
244 |
+
if ($box->hasChildren()) {
|
245 |
+
$this->displayBoxes($box->children(), $level+1);
|
246 |
+
}
|
247 |
+
}
|
248 |
+
} // displayBoxes method
|
249 |
+
} // MP4Info class
|
250 |
+
|
251 |
+
// ---
|
252 |
+
|
253 |
+
// {{{ Dependencies
|
254 |
+
include "MP4Info/Helper.php";
|
255 |
+
include "MP4Info/Exception.php";
|
256 |
+
include "MP4Info/Box.php";
|
257 |
+
// }}} Dependencies
|
includes/lib/MP4Info/Box.php
ADDED
@@ -0,0 +1,446 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box.php $
|
10 |
+
*
|
11 |
+
* Based on:
|
12 |
+
* - http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
|
13 |
+
* - http://neuron2.net/library/avc/c041828_ISO_IEC_14496-12_2005(E).pdf
|
14 |
+
* - http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf
|
15 |
+
*/
|
16 |
+
|
17 |
+
// ---
|
18 |
+
|
19 |
+
/**
|
20 |
+
* MP4Info General Box
|
21 |
+
*
|
22 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
23 |
+
* @version 1.1.20090611 $Id: Box.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
24 |
+
*/
|
25 |
+
class MP4Info_Box {
|
26 |
+
/**
|
27 |
+
* Total box size, including box header (8 bytes)
|
28 |
+
*
|
29 |
+
* @var int
|
30 |
+
*/
|
31 |
+
protected $totalSize;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Box type, numeric
|
35 |
+
*
|
36 |
+
* @var int
|
37 |
+
*/
|
38 |
+
protected $boxType;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Box type, string
|
42 |
+
*
|
43 |
+
* @var string
|
44 |
+
*/
|
45 |
+
protected $boxTypeStr;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Box data
|
49 |
+
*
|
50 |
+
* @var string(binary)
|
51 |
+
*/
|
52 |
+
protected $data;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Parent
|
56 |
+
*
|
57 |
+
* @var MP4Info_Box|false
|
58 |
+
*/
|
59 |
+
protected $parent;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Children
|
63 |
+
*
|
64 |
+
* @var MP4Info_Box[]
|
65 |
+
*/
|
66 |
+
protected $children = array();
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Constructor
|
70 |
+
*
|
71 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
72 |
+
* @param int $totalSize
|
73 |
+
* @param int $boxType
|
74 |
+
* @param file|string $f
|
75 |
+
* @param MP4Info_Box $parent
|
76 |
+
* @access public
|
77 |
+
*/
|
78 |
+
public function __construct($totalSize, $boxType, $f, $parent=false) {
|
79 |
+
$this->totalSize = $totalSize;
|
80 |
+
$this->boxType = $boxType;
|
81 |
+
$this->boxTypeStr = pack('N',$boxType);
|
82 |
+
$this->data = self::getDataFrom3rd($f,$totalSize);
|
83 |
+
$this->parent = $parent;
|
84 |
+
if ($parent != false) {
|
85 |
+
$parent->addChild($this);
|
86 |
+
}
|
87 |
+
} // Constructor
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Add a child to this box
|
91 |
+
*
|
92 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
93 |
+
* @param MP4Info_Box $child
|
94 |
+
* @access public
|
95 |
+
*/
|
96 |
+
public function addChild(&$child) {
|
97 |
+
if (!$child instanceof MP4Info_Box) {
|
98 |
+
throw new Exception('Child is not MP4Info_Box');
|
99 |
+
}
|
100 |
+
$this->children[] = &$child;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Check if the box has children
|
105 |
+
*
|
106 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
107 |
+
* @return bool
|
108 |
+
* @access public
|
109 |
+
*/
|
110 |
+
public function hasChildren() {
|
111 |
+
return count($this->children) > 0;
|
112 |
+
} // hasChildren method
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Get boxes' children
|
116 |
+
*
|
117 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
118 |
+
* @return MP4Info_Box[]
|
119 |
+
* @access public
|
120 |
+
*/
|
121 |
+
public function children() {
|
122 |
+
return $this->children;
|
123 |
+
} // children method
|
124 |
+
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get data from 3rd argument (file or string)
|
128 |
+
*
|
129 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
130 |
+
* @param file|string $f
|
131 |
+
* @param int $totalSize
|
132 |
+
* @return string
|
133 |
+
* @access public
|
134 |
+
* @static
|
135 |
+
*/
|
136 |
+
public static function getDataFrom3rd($f, $totalSize) {
|
137 |
+
// Get data
|
138 |
+
if ($f === false) {
|
139 |
+
return '';
|
140 |
+
} else if (is_string($f)) {
|
141 |
+
$data = substr($f,0,$totalSize-8);
|
142 |
+
} else {
|
143 |
+
$data = fread($f,$totalSize-8);
|
144 |
+
}
|
145 |
+
|
146 |
+
return $data;
|
147 |
+
} // getDataFrom3rd method
|
148 |
+
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Create an MP4Info_Box object from data
|
152 |
+
*
|
153 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
154 |
+
* @param int $totalSize
|
155 |
+
* @param int $boxType
|
156 |
+
* @param file|string $f
|
157 |
+
* @param MP4Info_Box|false $parent
|
158 |
+
* @return MP4Info_Box
|
159 |
+
* @access public
|
160 |
+
* @static
|
161 |
+
*/
|
162 |
+
public static function factory($totalSize, $boxType, $f, $parent=false) {
|
163 |
+
if (MP4Info_Box_Container::isCompatible($boxType,$parent)) {
|
164 |
+
$box = new MP4Info_Box_Container($totalSize, $boxType, $f, $parent);
|
165 |
+
} else if (MP4Info_Box_ftyp::isCompatible($boxType,$parent)) {
|
166 |
+
$box = new MP4Info_Box_ftyp($totalSize, $boxType, $f, $parent);
|
167 |
+
} else if (MP4Info_Box_uuid::isCompatible($boxType,$parent)) {
|
168 |
+
$box = new MP4Info_Box_uuid($totalSize, $boxType, $f, $parent);
|
169 |
+
} else if (MP4Info_Box_hdlr::isCompatible($boxType,$parent)) {
|
170 |
+
$box = new MP4Info_Box_hdlr($totalSize, $boxType, $f, $parent);
|
171 |
+
} else if (MP4Info_Box_mvhd::isCompatible($boxType,$parent)) {
|
172 |
+
$box = new MP4Info_Box_mvhd($totalSize, $boxType, $f, $parent);
|
173 |
+
} else if (MP4Info_Box_tkhd::isCompatible($boxType,$parent)) {
|
174 |
+
$box = new MP4Info_Box_tkhd($totalSize, $boxType, $f, $parent);
|
175 |
+
} else if (MP4Info_Box_mdhd::isCompatible($boxType,$parent)) {
|
176 |
+
$box = new MP4Info_Box_mdhd($totalSize, $boxType, $f, $parent);
|
177 |
+
} else if (MP4Info_Box_meta::isCompatible($boxType,$parent)) {
|
178 |
+
$box = new MP4Info_Box_meta($totalSize, $boxType, $f, $parent);
|
179 |
+
} else if (MP4Info_Box_stsd::isCompatible($boxType,$parent)) {
|
180 |
+
$box = new MP4Info_Box_stsd($totalSize, $boxType, $f, $parent);
|
181 |
+
} else if (MP4Info_Box_ilst::isCompatible($boxType,$parent)) {
|
182 |
+
$box = new MP4Info_Box_ilst($totalSize, $boxType, $f, $parent);
|
183 |
+
} else if (MP4Info_Box_ilst_sub::isCompatible($boxType,$parent)) {
|
184 |
+
$box = new MP4Info_Box_ilst_sub($totalSize, $boxType, $f, $parent);
|
185 |
+
} else {
|
186 |
+
throw new Exception('Media type error');
|
187 |
+
}
|
188 |
+
|
189 |
+
// Return box
|
190 |
+
return $box;
|
191 |
+
} // factory method
|
192 |
+
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Create a box from string
|
196 |
+
*
|
197 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
198 |
+
* @param string $data
|
199 |
+
* @param MP4Info_Box|false $parent
|
200 |
+
* @return MP4Info_Box
|
201 |
+
* @access public
|
202 |
+
* @static
|
203 |
+
*/
|
204 |
+
public static function fromString(&$data,$parent=false) {
|
205 |
+
if (strlen($data) < 8) {
|
206 |
+
throw new Exception('Not enough data, need at least 8 bytes!');
|
207 |
+
}
|
208 |
+
|
209 |
+
$ar = unpack('NtotalSize/NboxType',$data);
|
210 |
+
if ($ar['totalSize'] == 1) {
|
211 |
+
// Size is bigger than 4GB :-O die
|
212 |
+
// Skip ExtendedSize(UI64) and try to decode anyway
|
213 |
+
$ar2 = unpack('N2extSize',substr($data,8));
|
214 |
+
if ($ar2['extSize1'] > 0) {
|
215 |
+
throw new Exception('Extended size not supported');
|
216 |
+
} else {
|
217 |
+
$ar['totalSize'] = $ar2['extSize2'];
|
218 |
+
}
|
219 |
+
$skip = 8;
|
220 |
+
} else {
|
221 |
+
$skip = 0;
|
222 |
+
}
|
223 |
+
|
224 |
+
// Check if we need to skip
|
225 |
+
if (self::skipBoxType($ar['boxType'])) {
|
226 |
+
//print '+++ Skipping box '.pack('N',$ar['boxType']).'<br>';
|
227 |
+
$data = substr($data,$ar['totalSize']);
|
228 |
+
return self::fromString($data,$parent);
|
229 |
+
}
|
230 |
+
|
231 |
+
// Check if box is a container, and skip to content if so
|
232 |
+
if (self::ignoreBoxType($ar['boxType'])) {
|
233 |
+
//print '+++ Ignoring box '.pack('N',$ar['boxType']).'<br>';
|
234 |
+
$data = substr($data,8+$skip);
|
235 |
+
return self::fromString($data,$parent);
|
236 |
+
}
|
237 |
+
|
238 |
+
// Create box
|
239 |
+
$box = self::factory($ar['totalSize'],$ar['boxType'],substr($data,8+$skip),$parent);
|
240 |
+
if ($box instanceof MP4Info_Box) {
|
241 |
+
$data = substr($data,$box->getTotalSize());
|
242 |
+
}
|
243 |
+
|
244 |
+
return $box;
|
245 |
+
} // fromString method
|
246 |
+
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Create a box from file stream
|
250 |
+
*
|
251 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
252 |
+
* @param file $f
|
253 |
+
* @param MP4Info_Box|false $parent
|
254 |
+
* @return MP4Info_Box
|
255 |
+
* @access public
|
256 |
+
* @static
|
257 |
+
*/
|
258 |
+
public static function fromStream($f,$parent=false) {
|
259 |
+
// Get box header
|
260 |
+
$buf = fread($f,8);
|
261 |
+
if (strlen($buf) < 8) {
|
262 |
+
return false;
|
263 |
+
}
|
264 |
+
$ar = unpack('NtotalSize/NboxType',$buf);
|
265 |
+
if ($ar['totalSize'] == 1) {
|
266 |
+
// Size is bigger than 4GB :-O die
|
267 |
+
// Skip ExtendedSize(UI64) and try to decode anyway
|
268 |
+
$buf = fread($f,8);
|
269 |
+
$ar2 = unpack('N2extSize',$buf);
|
270 |
+
if ($ar2['extSize1'] > 0) {
|
271 |
+
throw new Exception('Extended size not supported');
|
272 |
+
} else {
|
273 |
+
$ar['totalSize'] = $ar2['extSize2'];
|
274 |
+
}
|
275 |
+
}
|
276 |
+
|
277 |
+
// Check if we need to skip
|
278 |
+
if (self::skipBoxType($ar['boxType'])) {
|
279 |
+
//print '+++ Skipping box '.pack('N',$ar['boxType']).'<br>';
|
280 |
+
fseek($f,$ar['totalSize']-8,SEEK_CUR);
|
281 |
+
return self::fromStream($f,$parent);
|
282 |
+
}
|
283 |
+
|
284 |
+
// Check if box is a container, and skip it if so
|
285 |
+
if (self::ignoreBoxType($ar['boxType'])) {
|
286 |
+
//print '+++ Ignoring box '.pack('N',$ar['boxType']).' of size '.$ar['totalSize'].'<br>';
|
287 |
+
return self::fromStream($f,$parent);
|
288 |
+
}
|
289 |
+
|
290 |
+
// Get box content
|
291 |
+
if ($ar['totalSize'] > 0) {
|
292 |
+
if ($ar['totalSize'] < 256*1024) {
|
293 |
+
$data = fread($f,$ar['totalSize']-8);
|
294 |
+
} else {
|
295 |
+
$data = $f;
|
296 |
+
}
|
297 |
+
} else {
|
298 |
+
$data = '';
|
299 |
+
}
|
300 |
+
|
301 |
+
// Create box object
|
302 |
+
$box = MP4Info_Box::factory($ar['totalSize'], $ar['boxType'], $data, $parent);
|
303 |
+
//print 'Got box from stream of type 0x'.dechex($ar['boxType']).'('.pack('N',$ar['boxType']).') and size '.$ar['totalSize'].' bytes: '.$box->toString().'<br>';
|
304 |
+
return $box;
|
305 |
+
} // fromStream method
|
306 |
+
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Check if we need to ignore that box, based on type
|
310 |
+
*
|
311 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
312 |
+
* @param int $boxType
|
313 |
+
* @return bool
|
314 |
+
* @access public
|
315 |
+
* @static
|
316 |
+
* @todo Cleanup, legacy stuff
|
317 |
+
*/
|
318 |
+
public static function ignoreBoxType($boxType) {
|
319 |
+
return false;
|
320 |
+
} // ignoreBoxType method
|
321 |
+
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Check if we need to skip a box based on type
|
325 |
+
*
|
326 |
+
* @param int $boxType
|
327 |
+
* @return bool
|
328 |
+
* @access public
|
329 |
+
* @static
|
330 |
+
*/
|
331 |
+
public static function skipBoxType($boxType) {
|
332 |
+
switch ($boxType) {
|
333 |
+
case 0x696f6473: // iods 5.1 Initial Object Descriptor Box
|
334 |
+
case 0x55c40000: // ??? ??
|
335 |
+
case 0x6d646174: // mdat ?? Movie Data
|
336 |
+
case 0x736d6864: // smhd 8.11.3 Sound Media Header Box
|
337 |
+
case 0x766d6864: // vmhd 8.11.2 Video Media Header Box
|
338 |
+
case 0x6e6d6864: // nmhd 8.11.5 Null Media Header Box
|
339 |
+
case 0x64696e66: // dinf ??
|
340 |
+
case 0x73747473: // stts 8.15.2 Decoding Time to Sample Box
|
341 |
+
case 0x73747363: // stsc 8.18 Sample To Chunk Box
|
342 |
+
case 0x7374737a: // stsz 8.17 Sample Size Boxes
|
343 |
+
case 0x7374636f: // stco 8.19 Chunk Offset Box
|
344 |
+
case 0x636f3634: // co64 8.19 Chunk Offset Box
|
345 |
+
case 0x63747473: // ctts 8.15.3 Composition Time to Sample Box
|
346 |
+
case 0x73747373: // stss 8.20 Sync Sample Box
|
347 |
+
case 0x74726566: // tref 8.6 Track Reference Box
|
348 |
+
return true;
|
349 |
+
default:
|
350 |
+
return false;
|
351 |
+
}
|
352 |
+
} // skipBoxType method
|
353 |
+
|
354 |
+
|
355 |
+
/**
|
356 |
+
* Total size getter
|
357 |
+
*
|
358 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
359 |
+
* @return int
|
360 |
+
* @access public
|
361 |
+
*/
|
362 |
+
public function getTotalSize() {
|
363 |
+
return $this->totalSize;
|
364 |
+
} // getTotalSize method
|
365 |
+
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Box type getter
|
369 |
+
*
|
370 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
371 |
+
* @return int
|
372 |
+
* @access public
|
373 |
+
*/
|
374 |
+
public function getBoxType() {
|
375 |
+
return $this->boxType;
|
376 |
+
} // getBoxType method
|
377 |
+
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Box type string getter
|
381 |
+
*
|
382 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
383 |
+
* @return string
|
384 |
+
* @access public
|
385 |
+
*/
|
386 |
+
public function getBoxTypeStr() {
|
387 |
+
return $this->boxTypeStr;
|
388 |
+
} // getBoxTypeStr method
|
389 |
+
|
390 |
+
|
391 |
+
/**
|
392 |
+
* Data getter
|
393 |
+
*
|
394 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
395 |
+
* @return string(binary)
|
396 |
+
* @access public
|
397 |
+
*/
|
398 |
+
public function getData() {
|
399 |
+
return $this->data;
|
400 |
+
} // getData method
|
401 |
+
|
402 |
+
|
403 |
+
/**
|
404 |
+
* stdClass converter
|
405 |
+
*
|
406 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
407 |
+
* @return stdClass
|
408 |
+
* @access public
|
409 |
+
*/
|
410 |
+
public function toStdClass() {
|
411 |
+
$a = new stdClass();
|
412 |
+
foreach ($this as $propName=>$prop) {
|
413 |
+
if (($propName != 'children') && ($propName != 'parent') && ($propName != 'boxes')) {
|
414 |
+
$a->{$propName} = $prop;
|
415 |
+
}
|
416 |
+
}
|
417 |
+
return $a;
|
418 |
+
} // toStdClass method
|
419 |
+
|
420 |
+
|
421 |
+
/**
|
422 |
+
* String converter
|
423 |
+
*
|
424 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
425 |
+
* @return string
|
426 |
+
* @access public
|
427 |
+
*/
|
428 |
+
public function toString() {
|
429 |
+
return '[MP4Info_Box[0x'.dechex($this->boxType).'('.pack('N',$this->boxType).']]';
|
430 |
+
} // toString method
|
431 |
+
} // MP4Info_Box class
|
432 |
+
|
433 |
+
|
434 |
+
// {{{ Dependencies
|
435 |
+
include "Box/Container.php";
|
436 |
+
include "Box/ftyp.php";
|
437 |
+
include "Box/uuid.php";
|
438 |
+
include "Box/hdlr.php";
|
439 |
+
include "Box/tkhd.php";
|
440 |
+
include "Box/mvhd.php";
|
441 |
+
include "Box/mdhd.php";
|
442 |
+
include "Box/meta.php";
|
443 |
+
include "Box/stsd.php";
|
444 |
+
include "Box/ilst.php";
|
445 |
+
include "Box/ilst_sub.php";
|
446 |
+
// }}} Dependencies
|
includes/lib/MP4Info/Box/Container.php
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/Container.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Generic container box
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.1.20090611 $Id: Container.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
class MP4Info_Box_Container extends MP4Info_Box {
|
21 |
+
/**
|
22 |
+
* Constructor
|
23 |
+
*
|
24 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
25 |
+
* @param int $totalSize
|
26 |
+
* @param int $boxType
|
27 |
+
* @param file|string $data
|
28 |
+
* @param MP4Info_Box $parent
|
29 |
+
* @return MP4Info_Box_Container
|
30 |
+
* @access public
|
31 |
+
* @throws MP4Info_Exception
|
32 |
+
*/
|
33 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
34 |
+
if (!self::isCompatible($boxType, $parent)) {
|
35 |
+
throw new MP4Info_Exception('This box isn\'t a container',MP4Info_Exception::CODE_INCOMPATIBLE,$boxType);
|
36 |
+
}
|
37 |
+
|
38 |
+
// Call ancestor
|
39 |
+
parent::__construct($totalSize, $boxType, false, $parent);
|
40 |
+
|
41 |
+
// Unpack
|
42 |
+
if (is_string($data)) {
|
43 |
+
while ($data != '') {
|
44 |
+
try {
|
45 |
+
$box = MP4Info_Box::fromString($data, $this);
|
46 |
+
if (!$box instanceof MP4Info_Box) {
|
47 |
+
break;
|
48 |
+
}
|
49 |
+
} catch (Exception $e) {
|
50 |
+
break;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
} else {
|
54 |
+
do {
|
55 |
+
try {
|
56 |
+
$box = MP4Info_Box::fromStream($data, $this);
|
57 |
+
if (!$box instanceof MP4Info_Box) {
|
58 |
+
break;
|
59 |
+
}
|
60 |
+
} catch (Exception $e) {
|
61 |
+
break;
|
62 |
+
}
|
63 |
+
} while ($box !== false);
|
64 |
+
}
|
65 |
+
} // Constructor
|
66 |
+
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Check if block is compatible with class
|
70 |
+
*
|
71 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
72 |
+
* @param int $boxType
|
73 |
+
* @param MP4Info_Box $parent
|
74 |
+
* @return bool
|
75 |
+
* @access public
|
76 |
+
* @static
|
77 |
+
*/
|
78 |
+
public static function isCompatible($boxType, $parent) {
|
79 |
+
return ($boxType == 0x6D6F6F76) || // moov
|
80 |
+
($boxType == 0x7472616B) || // trak
|
81 |
+
($boxType == 0x6d646961) || // mdia
|
82 |
+
($boxType == 0x6D696E66) || // minf
|
83 |
+
($boxType == 0x7374626c) || // stbl
|
84 |
+
($boxType == 0x75647461) || // udta
|
85 |
+
false;
|
86 |
+
} // isCompatible method
|
87 |
+
|
88 |
+
|
89 |
+
/**
|
90 |
+
* String converter
|
91 |
+
*
|
92 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
93 |
+
* @return string
|
94 |
+
* @access public
|
95 |
+
*/
|
96 |
+
public function toString() {
|
97 |
+
return '[MP4Info_Box_Container['.$this->boxTypeStr.']:'.count($this->children).']';
|
98 |
+
} // toString method
|
99 |
+
} // MP4Info_Box_Container method
|
includes/lib/MP4Info/Box/ftyp.php
ADDED
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/ftyp.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* 4.3 File Type Box (FTYP)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.1.20090611 $Id: ftyp.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
class MP4Info_Box_ftyp extends MP4Info_Box {
|
21 |
+
/**
|
22 |
+
* Major brand
|
23 |
+
*
|
24 |
+
* @var int
|
25 |
+
*/
|
26 |
+
protected $majorBrand;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Minor brand
|
30 |
+
*
|
31 |
+
* @var int
|
32 |
+
*/
|
33 |
+
protected $minorBrand;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Compatible brands
|
37 |
+
*
|
38 |
+
* @var int[]
|
39 |
+
*/
|
40 |
+
protected $compatibleBrands;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Major Brands' names
|
44 |
+
*
|
45 |
+
* @var {n:Str,n:Str,...}
|
46 |
+
* @static
|
47 |
+
*/
|
48 |
+
protected static $brandNames = array(
|
49 |
+
'3g2a' => '3GPP2 Media (.3G2)',
|
50 |
+
'3ge6' => '3GPP (.3GP) Release 6 MBMS Extended Presentations',
|
51 |
+
'3ge7' => '3GPP (.3GP) Release 7 MBMS Extended Presentations',
|
52 |
+
'3gg6' => '3GPP Release 6 General Profile',
|
53 |
+
'3gp1' => '3GPP Media (.3GP) Release 1 ? (non-existent)',
|
54 |
+
'3gp2' => '3GPP Media (.3GP) Release 2 ? (non-existent)',
|
55 |
+
'3gp3' => '3GPP Media (.3GP) Release 3 ? (non-existent)',
|
56 |
+
'3gp4' => '3GPP Media (.3GP) Release 4',
|
57 |
+
'3gp5' => '3GPP Media (.3GP) Release 5',
|
58 |
+
'3gp6' => '3GPP Media (.3GP) Release 6 Basic Profile',
|
59 |
+
'3gr6' => '3GPP Media (.3GP) Release 6 Progressive Download',
|
60 |
+
'3gs6' => '3GPP Media (.3GP) Release 6 Streaming Servers',
|
61 |
+
'3gs7' => '3GPP Media (.3GP) Release 7 Streaming Servers',
|
62 |
+
'avc1' => 'MP4 Base w/ AVC ext [ISO 14496-12:2005]',
|
63 |
+
'caep' => 'Canon Digital Camera',
|
64 |
+
'caqv' => 'Casio Digital Camera',
|
65 |
+
'cdes' => 'Convergent Design',
|
66 |
+
'f4v' => 'Video for Adobe Flash Player 9+ (.F4V)',
|
67 |
+
'f4p' => 'Protected Video for Adobe Flash Player 9+ (.F4P)',
|
68 |
+
'f4a' => 'Audio for Adobe Flash Player 9+ (.F4A)',
|
69 |
+
'f4b' => 'Audio Book for Adobe Flash Player 9+ (.F4B)',
|
70 |
+
'isc2' => 'ISMACryp 2.0 Encrypted File',
|
71 |
+
'iso2' => 'MP4 Base Media v2 [ISO 14496-12:2005]',
|
72 |
+
'isom' => 'MP4 Base Media v1 [IS0 14496-12:2003]',
|
73 |
+
'jp2' => 'JPEG 2000 Image (.JP2) [ISO 15444-1 ?]',
|
74 |
+
'jp20' => 'Unknown, from GPAC samples (prob non-existent)',
|
75 |
+
'jpm' => 'JPEG 2000 Compound Image (.JPM) [ISO 15444-6]',
|
76 |
+
'jpx' => 'JPEG 2000 w/ extensions (.JPX) [ISO 15444-2]',
|
77 |
+
'kddi' => '3GPP2 EZmovie for KDDI 3G Cellphones',
|
78 |
+
'm4a ' => 'Apple iTunes AAC-LC (.M4A) Audio',
|
79 |
+
'm4b ' => 'Apple iTunes AAC-LC (.M4B) Audio Book',
|
80 |
+
'm4p ' => 'Apple iTunes AAC-LC (.M4P) AES Protected Audio',
|
81 |
+
'm4v ' => 'Apple iTunes Video (.M4V) Video',
|
82 |
+
'm4vh' => 'Apple TV (.M4V)',
|
83 |
+
'm4vp' => 'Apple iPhone (.M4V)',
|
84 |
+
'mj2s' => 'Motion JPEG 2000 [ISO 15444-3] Simple Profile',
|
85 |
+
'mjp2' => 'Motion JPEG 2000 [ISO 15444-3] General Profile',
|
86 |
+
'mmp4' => 'MPEG-4/3GPP Mobile Profile (.MP4 / .3GP) (for NTT)',
|
87 |
+
'mp21' => 'MPEG-21 [ISO/IEC 21000-9]',
|
88 |
+
'mp41' => 'MP4 v1 [ISO 14496-1:ch13]',
|
89 |
+
'mp42' => 'MP4 v2 [ISO 14496-14]',
|
90 |
+
'mp71' => 'MP4 w/ MPEG-7 Metadata [per ISO 14496-12]',
|
91 |
+
'mppi' => 'Photo Player, MAF [ISO/IEC 23000-3]',
|
92 |
+
'mqt' => 'Sony / Mobile QuickTime (.MQV)',
|
93 |
+
'msnv' => 'MPEG-4 (.MP4) for SonyPSP',
|
94 |
+
'ndas' => 'MP4 v2 [ISO 14496-14] Nero Digital AAC Audio',
|
95 |
+
'ndsc' => 'MPEG-4 (.MP4) Nero Cinema Profile',
|
96 |
+
'ndsh' => 'MPEG-4 (.MP4) Nero HDTV Profile',
|
97 |
+
'ndsm' => 'MPEG-4 (.MP4) Nero Mobile Profile',
|
98 |
+
'ndsp' => 'MPEG-4 (.MP4) Nero Portable Profile',
|
99 |
+
'ndss' => 'MPEG-4 (.MP4) Nero Standard Profile',
|
100 |
+
'ndxc' => 'H.264/MPEG-4 AVC (.MP4) Nero Cinema Profile',
|
101 |
+
'ndxh' => 'H.264/MPEG-4 AVC (.MP4) Nero HDTV Profile',
|
102 |
+
'ndxm' => 'H.264/MPEG-4 AVC (.MP4) Nero Mobile Profile',
|
103 |
+
'ndxp' => 'H.264/MPEG-4 AVC (.MP4) Nero Portable Profile',
|
104 |
+
'ndxs' => 'H.264/MPEG-4 AVC (.MP4) Nero Standard Profile',
|
105 |
+
'odcf ' => 'OMA DCF DRM Format 2.0 (OMA-TS-DRM-DCF-V2_0-20060303-A)',
|
106 |
+
'opf2 ' => 'OMA PDCF DRM Format 2.1 (OMA-TS-DRM-DCF-V2_1-20070724-C)',
|
107 |
+
'opx2 ' => 'OMA PDCF DRM + XBS extensions (OMA-TS-DRM_XBS-V1_0-20070529-C)',
|
108 |
+
'qt ' => 'Apple QuickTime (.MOV/QT)',
|
109 |
+
'sdv' => 'SD Memory Card Video',
|
110 |
+
);
|
111 |
+
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Constructor
|
115 |
+
*
|
116 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
117 |
+
* @param int $totalSize
|
118 |
+
* @param int $boxType
|
119 |
+
* @param file|string $data
|
120 |
+
* @param MP4Info_Box $parent
|
121 |
+
* @return MP4Info_Box_ftyp
|
122 |
+
* @access public
|
123 |
+
* @throws MP4Info_Exception
|
124 |
+
*/
|
125 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
126 |
+
if (!self::isCompatible($boxType, $parent)) {
|
127 |
+
throw new MP4Info_Exception('This box isn\'t "ftyp"',MP4Info_Exception::CODE_INCOMPATIBLE,$boxType);
|
128 |
+
}
|
129 |
+
|
130 |
+
// Call ancestor
|
131 |
+
parent::__construct($totalSize, $boxType, false, $parent);
|
132 |
+
|
133 |
+
// Get data
|
134 |
+
$data = self::getDataFrom3rd($data, $totalSize);
|
135 |
+
|
136 |
+
// Unpack
|
137 |
+
$ar = unpack('NmajorBrand/NminorVersion/N*compatibleBrands',$data);
|
138 |
+
$compatibleBrands = array();
|
139 |
+
foreach ($ar as $k=>$v) {
|
140 |
+
if (substr($k,0,16) == 'compatibleBrands') {
|
141 |
+
$compatibleBrands[] = $v;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
// Save properties
|
146 |
+
$this->majorBrand = $ar['majorBrand'];
|
147 |
+
$this->minorVersion = $ar['minorVersion'];
|
148 |
+
$this->compatibleBrands = $compatibleBrands;
|
149 |
+
} // Constructor
|
150 |
+
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Check if block is compatible with class
|
154 |
+
*
|
155 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
156 |
+
* @param int $boxType
|
157 |
+
* @param MP4Info_Box $parent
|
158 |
+
* @return bool
|
159 |
+
* @access public
|
160 |
+
* @static
|
161 |
+
*/
|
162 |
+
static function isCompatible($boxType, $parent) {
|
163 |
+
return $boxType == 0x66747970;
|
164 |
+
} // isCompatible method
|
165 |
+
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Major brand getter
|
169 |
+
*
|
170 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
171 |
+
* @return int
|
172 |
+
* @access public
|
173 |
+
*/
|
174 |
+
public function getMajorBrand() {
|
175 |
+
return $this->majorBrand;
|
176 |
+
} // getMajorBrand method
|
177 |
+
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Minor version getter
|
181 |
+
*
|
182 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
183 |
+
* @return int
|
184 |
+
* @access public
|
185 |
+
*/
|
186 |
+
public function getMinorVersion() {
|
187 |
+
return $this->minorVersion;
|
188 |
+
} // getMinorVersion method
|
189 |
+
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Compatible brands getter
|
193 |
+
*
|
194 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
195 |
+
* @return int[]
|
196 |
+
* @access public
|
197 |
+
*/
|
198 |
+
public function getCompatibleBrands() {
|
199 |
+
return $this->compatibleBrands;
|
200 |
+
} // getCompatibleBrands method
|
201 |
+
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Convert a brand 32bit code to a string
|
205 |
+
*
|
206 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
207 |
+
* @param int $brand
|
208 |
+
* @return string
|
209 |
+
* @access public
|
210 |
+
* @static
|
211 |
+
*/
|
212 |
+
public static function brandToString($brand) {
|
213 |
+
if (isset(self::$$brandNames[$brand])) {
|
214 |
+
return self::$$brandNames[$brand];
|
215 |
+
} else {
|
216 |
+
return $brand;
|
217 |
+
}
|
218 |
+
} // brandToString method
|
219 |
+
|
220 |
+
|
221 |
+
/**
|
222 |
+
* String converter
|
223 |
+
*
|
224 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
225 |
+
* @return string
|
226 |
+
* @access public
|
227 |
+
*/
|
228 |
+
public function toString() {
|
229 |
+
return '[MP4Info_Box_ftyp]';
|
230 |
+
} // toString method
|
231 |
+
} // MP4Info_Box_ftyp method
|
includes/lib/MP4Info/Box/hdlr.php
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/hdlr.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* 8.9 Handler Reference Box (HDLR)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090601 $Id: hdlr.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
* @todo Factor this into a fullbox
|
20 |
+
*/
|
21 |
+
class MP4Info_Box_hdlr extends MP4Info_Box {
|
22 |
+
// {{{ Constants
|
23 |
+
const HANDLER_VIDEO = 'vide';
|
24 |
+
const HANDLER_SOUND = 'soun';
|
25 |
+
// }}} Constants
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Handler type
|
29 |
+
*
|
30 |
+
* @var uint32
|
31 |
+
*/
|
32 |
+
protected $handlerType;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Name
|
36 |
+
*
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
protected $name;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Timezone
|
43 |
+
*
|
44 |
+
* @var int
|
45 |
+
* @static
|
46 |
+
*/
|
47 |
+
protected static $timezone = false;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Constructor
|
51 |
+
*
|
52 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
53 |
+
* @param int $totalSize
|
54 |
+
* @param int $boxType
|
55 |
+
* @param file|string $data
|
56 |
+
* @param MP4Info_Box $parent
|
57 |
+
* @return MP4Info_Box_hdlr
|
58 |
+
* @access public
|
59 |
+
* @throws MP4Info_Exception
|
60 |
+
*/
|
61 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
62 |
+
if (!self::isCompatible($boxType, $parent)) {
|
63 |
+
throw new Exception('This box isn\'t "ftyp"');
|
64 |
+
}
|
65 |
+
|
66 |
+
// Get timezone
|
67 |
+
if (self::$timezone === false) {
|
68 |
+
self::$timezone = date('Z');
|
69 |
+
}
|
70 |
+
|
71 |
+
// Call ancestor
|
72 |
+
parent::__construct($totalSize,$boxType,'',$parent);
|
73 |
+
|
74 |
+
// Get data
|
75 |
+
$data = self::getDataFrom3rd($data,$totalSize);
|
76 |
+
|
77 |
+
// Unpack
|
78 |
+
$ar = unpack('Cversion/C3flags',$data);
|
79 |
+
if ($ar['version'] == 0) {
|
80 |
+
// 32 bit
|
81 |
+
$ar2 = unpack('Nctime/Nmtime/NtimeScale/Nduration',substr($data,4));
|
82 |
+
$len = 6*4;
|
83 |
+
} else if ($ar['version'] == 1) {
|
84 |
+
// 64 bit
|
85 |
+
$ar2 = unpack('N2ctime/N2mtime/NtimeScale/N2duration',substr($data,4));
|
86 |
+
$len = 9*4;
|
87 |
+
} else {
|
88 |
+
throw new Exception('Unhandled version: '.$ar['version']);
|
89 |
+
}
|
90 |
+
|
91 |
+
// Save
|
92 |
+
$this->version = $ar['version'];
|
93 |
+
$this->flags = $ar['flags1']*65536+$ar['flags1']*256+$ar['flags1']*1;
|
94 |
+
$this->ctime = date('r',(isset($ar2['ctime']) ? $ar2['ctime'] : $ar2['ctime1'])-2082826800-self::$timezone);
|
95 |
+
$this->mtime = date('r',(isset($ar2['mtime']) ? $ar2['mtime'] : $ar2['mtime1'])-2082826800-self::$timezone);
|
96 |
+
$this->timeScale = $ar2['timeScale'];
|
97 |
+
$this->duration = (isset($ar2['duration']) ? $ar2['duration'] : $ar2['duration1']);
|
98 |
+
$this->handlerType = substr($data,$len,4);
|
99 |
+
$this->name = substr($data,$len+8,-1);
|
100 |
+
} // Constructor
|
101 |
+
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Check if block is compatible with class
|
105 |
+
*
|
106 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
107 |
+
* @param int $boxType
|
108 |
+
* @param MP4Info_Box $parent
|
109 |
+
* @return bool
|
110 |
+
* @access public
|
111 |
+
* @static
|
112 |
+
*/
|
113 |
+
static public function isCompatible($boxType, $parent) {
|
114 |
+
return $boxType == 0x68646c72;
|
115 |
+
} // isCompatible method
|
116 |
+
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Handler type getter
|
120 |
+
*
|
121 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
122 |
+
* @return int
|
123 |
+
* @access public
|
124 |
+
*/
|
125 |
+
public function getHandlerType() {
|
126 |
+
return $this->handlerType;
|
127 |
+
} // getHandlerType method
|
128 |
+
|
129 |
+
|
130 |
+
/**
|
131 |
+
* String converter
|
132 |
+
*
|
133 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
134 |
+
* @return string
|
135 |
+
* @access public
|
136 |
+
*/
|
137 |
+
public function toString() {
|
138 |
+
return '[MP4Info_Box_hdlr:'.$this->handlerType.']';
|
139 |
+
} // toString method
|
140 |
+
} // MP4Info_Box_hdlr class
|
includes/lib/MP4Info/Box/ilst.php
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/ilst.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* x.x ??? (ILST)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090601 $Id: ilst.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
class MP4Info_Box_ilst extends MP4Info_Box_Container {
|
21 |
+
/**
|
22 |
+
* Values
|
23 |
+
*
|
24 |
+
* @var {}
|
25 |
+
* @access protected
|
26 |
+
*/
|
27 |
+
protected $values = array();
|
28 |
+
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Constructor
|
32 |
+
*
|
33 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
34 |
+
* @param int $totalSize
|
35 |
+
* @param int $boxType
|
36 |
+
* @param file|string $data
|
37 |
+
* @param MP4Info_Box $parent
|
38 |
+
* @return MP4Info_Box_ilst
|
39 |
+
* @access public
|
40 |
+
* @throws MP4Info_Exception
|
41 |
+
*/
|
42 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
43 |
+
if (!self::isCompatible($boxType, $parent)) {
|
44 |
+
throw new MP4Info_Exception('This box isn\'t "ilst"', MP4Info_Exception::CODE_INCOMPATIBLE, $boxType);
|
45 |
+
}
|
46 |
+
|
47 |
+
// Call ancestor
|
48 |
+
parent::__construct($totalSize, $boxType, $data, $parent);
|
49 |
+
} // Constructor
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Check if block is compatible with class
|
54 |
+
*
|
55 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
56 |
+
* @param int $boxType
|
57 |
+
* @param MP4Info_Box $parent
|
58 |
+
* @return bool
|
59 |
+
* @access public
|
60 |
+
* @static
|
61 |
+
*/
|
62 |
+
static public function isCompatible($boxType, $parent) {
|
63 |
+
return $boxType == 0x696C7374;
|
64 |
+
} // isCompatible method
|
65 |
+
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Check if a given key has a value
|
69 |
+
*
|
70 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
71 |
+
* @param string $k
|
72 |
+
* @return bool
|
73 |
+
* @access public
|
74 |
+
*/
|
75 |
+
public function hasValue($k) {
|
76 |
+
return (isset($this->values[$k])) || (isset($this->values[utf8_decode($k)]));
|
77 |
+
} // hasValue method
|
78 |
+
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Get the value of a given key
|
82 |
+
*
|
83 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
84 |
+
* @param string $k
|
85 |
+
* @return mixed
|
86 |
+
* @access public
|
87 |
+
*/
|
88 |
+
public function getValue($k) {
|
89 |
+
if (isset($this->values[$k])) {
|
90 |
+
return $this->values[$k];
|
91 |
+
} else if (isset($this->values[utf8_decode($k)])) {
|
92 |
+
return $this->values[utf8_decode($k)];
|
93 |
+
} else {
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
} // getValue method
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Set a value for a given key
|
101 |
+
*
|
102 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
103 |
+
* @param string $k
|
104 |
+
* @param mixed $v
|
105 |
+
* @access public
|
106 |
+
*/
|
107 |
+
public function setKeyValue($k,$v) {
|
108 |
+
$this->values[$k] = $v;
|
109 |
+
} // setKeyValue method
|
110 |
+
|
111 |
+
|
112 |
+
/**
|
113 |
+
* String converter
|
114 |
+
*
|
115 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
116 |
+
* @return string
|
117 |
+
* @access public
|
118 |
+
*/
|
119 |
+
public function toString() {
|
120 |
+
return '[MP4Info_Box_ilst:'.count($this->boxes).']';
|
121 |
+
} // toString method
|
122 |
+
} // MP4Info_Box_ilst class
|
includes/lib/MP4Info/Box/ilst_sub.php
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/ilst_sub.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* x.x ILST sub blocks (numerous)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.1.20090611 $Id: ilst_sub.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
class MP4Info_Box_ilst_sub extends MP4Info_Box {
|
21 |
+
/**
|
22 |
+
* Constructor
|
23 |
+
*
|
24 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
25 |
+
* @param int $totalSize
|
26 |
+
* @param int $boxType
|
27 |
+
* @param file|string $f
|
28 |
+
* @param MP4Info_Box $parent
|
29 |
+
* @return MP4Info_Box_ilst_sub
|
30 |
+
* @access public
|
31 |
+
* @throws MP4Info_Exception
|
32 |
+
*/
|
33 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
34 |
+
if (!$parent instanceof MP4Info_Box_ilst) {
|
35 |
+
throw new MP4Info_Exception('This box isn\'t "islt" child', MP4Info_Exception::CODE_INCOMPATIBLE, $boxType);
|
36 |
+
}
|
37 |
+
|
38 |
+
// Call ancestor
|
39 |
+
parent::__construct($totalSize,$boxType,$data,$parent);
|
40 |
+
|
41 |
+
// Get data
|
42 |
+
$data = $this->data;
|
43 |
+
|
44 |
+
// Unpack
|
45 |
+
$type = self::getType($this->boxType);
|
46 |
+
$ar = unpack('Nlen',$data);
|
47 |
+
if (substr($data,4,4) == 'data') {
|
48 |
+
$info = substr($data,8,$ar['len']-8);
|
49 |
+
switch ($type) {
|
50 |
+
case 'uint8':
|
51 |
+
$info = reset(unpack('C',$info));
|
52 |
+
break;
|
53 |
+
case 'uint16':
|
54 |
+
$info = reset(unpack('n',$info));
|
55 |
+
break;
|
56 |
+
case 'uint32':
|
57 |
+
$info = reset(unpack('N',$info));
|
58 |
+
break;
|
59 |
+
case 'text':
|
60 |
+
break;
|
61 |
+
}
|
62 |
+
$this->data = $info;
|
63 |
+
$parent->setKeyValue($this->boxTypeStr, $info);
|
64 |
+
} else {
|
65 |
+
throw new MP4Info_Exception('Didn\'t get the "data" code');
|
66 |
+
}
|
67 |
+
} // Constructor
|
68 |
+
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Check if block is compatible with class
|
72 |
+
*
|
73 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
74 |
+
* @param int $boxType
|
75 |
+
* @param MP4Info_Box $parent
|
76 |
+
* @return bool
|
77 |
+
* @access public
|
78 |
+
* @static
|
79 |
+
*/
|
80 |
+
static public function isCompatible($boxType, $parent) {
|
81 |
+
return ($parent instanceof MP4Info_Box_ilst);
|
82 |
+
} // isCompatible method
|
83 |
+
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Get sub type
|
87 |
+
* http://atomicparsley.sourceforge.net/mpeg-4files.html
|
88 |
+
*
|
89 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
90 |
+
* @param int $boxType
|
91 |
+
* @return string
|
92 |
+
* @access protected
|
93 |
+
* @static
|
94 |
+
* @todo The © codes should be chr(...), as utf8 encoding messes things up
|
95 |
+
*/
|
96 |
+
static protected function getType($boxType) {
|
97 |
+
switch (pack('N',$boxType)) {
|
98 |
+
case '©alb':
|
99 |
+
case '©art':
|
100 |
+
case 'aART':
|
101 |
+
case '©cmt':
|
102 |
+
case '©day':
|
103 |
+
case '©nam':
|
104 |
+
case '©gen':
|
105 |
+
case '©wrt':
|
106 |
+
case '©too':
|
107 |
+
case 'cprt':
|
108 |
+
case '©grp':
|
109 |
+
case 'catg':
|
110 |
+
case 'desc':
|
111 |
+
case '©lyr':
|
112 |
+
case 'tvnn':
|
113 |
+
case 'tvsh':
|
114 |
+
case 'tven':
|
115 |
+
case 'purd':
|
116 |
+
return 'text';
|
117 |
+
|
118 |
+
case 'gnre':
|
119 |
+
case 'trkn':
|
120 |
+
case 'disk':
|
121 |
+
case 'tmpo':
|
122 |
+
case 'cpil':
|
123 |
+
case 'rtng':
|
124 |
+
case 'stik':
|
125 |
+
case 'pcst':
|
126 |
+
case 'purl':
|
127 |
+
case 'egid':
|
128 |
+
case 'tvsn':
|
129 |
+
case 'tves':
|
130 |
+
case 'pgap':
|
131 |
+
return 'uint8';
|
132 |
+
default:
|
133 |
+
return '';
|
134 |
+
}
|
135 |
+
} // getType method
|
136 |
+
|
137 |
+
|
138 |
+
/**
|
139 |
+
* String converter
|
140 |
+
*
|
141 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
142 |
+
* @return string
|
143 |
+
* @access public
|
144 |
+
*/
|
145 |
+
public function toString() {
|
146 |
+
return '[MP4Info_Box_ilst_sub['.$this->boxTypeStr.']:'.$this->getData().']';
|
147 |
+
} // toString converter
|
148 |
+
} // MP4Info_Box_ilst_sub class
|
includes/lib/MP4Info/Box/mdhd.php
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/mdhd.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* 8.8 Media Header Box (MDHD)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090611 $Id: mdhd.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
* @todo Factor this into a fullbox
|
20 |
+
*/
|
21 |
+
class MP4Info_Box_mdhd extends MP4Info_Box {
|
22 |
+
/**
|
23 |
+
* Version
|
24 |
+
*
|
25 |
+
* @var int
|
26 |
+
*/
|
27 |
+
protected $version;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Flags
|
31 |
+
*
|
32 |
+
* @var int
|
33 |
+
*/
|
34 |
+
protected $flags;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Creation time
|
38 |
+
*
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected $ctime;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Modification time
|
45 |
+
*
|
46 |
+
* @var unknown_type
|
47 |
+
*/
|
48 |
+
protected $mtime;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Time scale
|
52 |
+
*
|
53 |
+
* @var int
|
54 |
+
*/
|
55 |
+
protected $timeScale;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Duration
|
59 |
+
*
|
60 |
+
* @var int
|
61 |
+
*/
|
62 |
+
protected $duration;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Time zone
|
66 |
+
*
|
67 |
+
* @var int
|
68 |
+
* @static
|
69 |
+
*/
|
70 |
+
protected static $timezone = false;
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Constructor
|
75 |
+
*
|
76 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
77 |
+
* @param int $totalSize
|
78 |
+
* @param int $boxType
|
79 |
+
* @param file|string $data
|
80 |
+
* @param MP4Info_Box $parent
|
81 |
+
* @return MP4Info_Box_mdhd
|
82 |
+
* @access public
|
83 |
+
* @throws MP4Info_Exception
|
84 |
+
*/
|
85 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
86 |
+
if (!self::isCompatible($boxType, $parent)) {
|
87 |
+
throw new Exception('This box isn\'t "mdhd"');
|
88 |
+
}
|
89 |
+
|
90 |
+
// Get timezone
|
91 |
+
if (self::$timezone === false) {
|
92 |
+
self::$timezone = date('Z');
|
93 |
+
}
|
94 |
+
|
95 |
+
// Call ancestor
|
96 |
+
parent::__construct($totalSize, $boxType, '', $parent);
|
97 |
+
|
98 |
+
// Unpack
|
99 |
+
$ar = unpack('Cversion/C3flags',$data);
|
100 |
+
if ($ar['version'] == 0) {
|
101 |
+
// 32 bit
|
102 |
+
$ar2 = unpack('Nctime/Nmtime/NtimeScale/Nduration/nlanguage/ndummy',substr($data,4));
|
103 |
+
} else if ($ar['version'] == 1) {
|
104 |
+
// 64 bit
|
105 |
+
$ar2 = unpack('N2ctime/N2mtime/NtimeScale/N2duration/nlanguage/ndummy',substr($data,4));
|
106 |
+
} else {
|
107 |
+
throw new Exception('Unhandled version: '.$ar['version']);
|
108 |
+
}
|
109 |
+
|
110 |
+
// Save
|
111 |
+
$this->version = $ar['version'];
|
112 |
+
$this->flags = $ar['flags1']*65536+$ar['flags1']*256+$ar['flags1']*1;
|
113 |
+
$this->ctime = date('r',(isset($ar2['ctime']) ? $ar2['ctime'] : $ar2['ctime1'])-2082826800-self::$timezone);
|
114 |
+
$this->mtime = date('r',(isset($ar2['mtime']) ? $ar2['mtime'] : $ar2['mtime1'])-2082826800-self::$timezone);
|
115 |
+
$this->timeScale = $ar2['timeScale'];
|
116 |
+
$this->duration = (isset($ar2['duration']) ? $ar2['duration'] : $ar2['duration1']);
|
117 |
+
$this->language = MP4Info_Helper::fromPackedLetters($ar2['language'],1);
|
118 |
+
} // Constructor
|
119 |
+
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Check if block is compatible with class
|
123 |
+
*
|
124 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
125 |
+
* @param int $boxType
|
126 |
+
* @param MP4Info_Box $parent
|
127 |
+
* @return bool
|
128 |
+
* @access public
|
129 |
+
* @static
|
130 |
+
*/
|
131 |
+
static function isCompatible($boxType, $parent) {
|
132 |
+
return $boxType == 0x6d646864;
|
133 |
+
} // isCompatible method
|
134 |
+
|
135 |
+
|
136 |
+
/**
|
137 |
+
* String converter
|
138 |
+
*
|
139 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
140 |
+
* @return string
|
141 |
+
* @access public
|
142 |
+
*/
|
143 |
+
public function toString() {
|
144 |
+
return '[MP4Info_Box_mdhd]';
|
145 |
+
} // toString method
|
146 |
+
} // MP4Info_Box_mdhd class
|
includes/lib/MP4Info/Box/meta.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/meta.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* x.x Meta (META)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090601 $Id: meta.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
class MP4Info_Box_meta extends MP4Info_Box_container {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Constructor
|
24 |
+
*
|
25 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
26 |
+
* @param int $totalSize
|
27 |
+
* @param int $boxType
|
28 |
+
* @param file|string $f
|
29 |
+
* @param MP4Info_Box_meta $parent
|
30 |
+
* @access public
|
31 |
+
* @throws MP4Info_Exception
|
32 |
+
*/
|
33 |
+
public function __construct($totalSize, $boxType, $data, $parent=false) {
|
34 |
+
if (!self::isCompatible($boxType, $parent)) {
|
35 |
+
throw new MP4Info_Exception('This box isn\'t "meta"',MP4Info_Exception::CODE_INCOMPATIBLE,false,$boxType);
|
36 |
+
}
|
37 |
+
|
38 |
+
$ar = unpack('Nlen',$data);
|
39 |
+
|
40 |
+
parent::__construct($totalSize, $boxType, substr($data,4,$ar['len']), $parent);
|
41 |
+
} // Constructor
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Check if block is compatible with class
|
46 |
+
*
|
47 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
48 |
+
* @param int $boxType
|
49 |
+
* @param MP4Info_Box $parent
|
50 |
+
* @return bool
|
51 |
+
* @access public
|
52 |
+
* @static
|
53 |
+
*/
|
54 |
+
static public function isCompatible($boxType, $parent) {
|
55 |
+
return $boxType == 0x6D657461;
|
56 |
+
} // isCompatible method
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* String converter
|
61 |
+
*
|
62 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
63 |
+
* @return string
|
64 |
+
* @access public
|
65 |
+
*/
|
66 |
+
public function toString() {
|
67 |
+
return '[MP4Info_Box_meta:'.count($this->boxes).']';
|
68 |
+
} // toString method
|
69 |
+
} // MP4Info_Box_meta class
|
includes/lib/MP4Info/Box/mvhd.php
ADDED
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/mvhd.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* x.x Movie Header (MVHD)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090601 $Id: mvhd.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
* @todo Factor this into a fullbox
|
20 |
+
*/
|
21 |
+
class MP4Info_Box_mvhd extends MP4Info_Box {
|
22 |
+
/**
|
23 |
+
* Version
|
24 |
+
*
|
25 |
+
* @var int
|
26 |
+
*/
|
27 |
+
protected $version;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Flags
|
31 |
+
*
|
32 |
+
* @var int
|
33 |
+
*/
|
34 |
+
protected $flags;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Creation time
|
38 |
+
*
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected $ctime;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Modification time
|
45 |
+
*
|
46 |
+
* @var unknown_type
|
47 |
+
*/
|
48 |
+
protected $mtime;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Time scale
|
52 |
+
*
|
53 |
+
* @var int
|
54 |
+
*/
|
55 |
+
protected $timeScale;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Duration
|
59 |
+
*
|
60 |
+
* @var int
|
61 |
+
*/
|
62 |
+
protected $duration;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Rate
|
66 |
+
*
|
67 |
+
* @var int
|
68 |
+
*/
|
69 |
+
protected $rate;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Volume
|
73 |
+
*
|
74 |
+
* @var int
|
75 |
+
*/
|
76 |
+
protected $volume;
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Time zone
|
80 |
+
*
|
81 |
+
* @var int
|
82 |
+
* @static
|
83 |
+
*/
|
84 |
+
protected static $timezone = false;
|
85 |
+
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Constructor
|
89 |
+
*
|
90 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
91 |
+
* @param int $totalSize
|
92 |
+
* @param int $boxType
|
93 |
+
* @param file|string $data
|
94 |
+
* @param MP4Info_Box $parent
|
95 |
+
* @return MP4Info_Box_mvhd
|
96 |
+
* @access public
|
97 |
+
* @throws MP4Info_Exception
|
98 |
+
*/
|
99 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
100 |
+
if (!self::isCompatible($boxType)) {
|
101 |
+
throw new Exception('This box isn\'t "mvhd"');
|
102 |
+
}
|
103 |
+
|
104 |
+
// Get timezone
|
105 |
+
if (self::$timezone === false) {
|
106 |
+
self::$timezone = date('Z');
|
107 |
+
}
|
108 |
+
|
109 |
+
// Call ancestor's constructor
|
110 |
+
parent::__construct($totalSize,$boxType,'',$parent);
|
111 |
+
|
112 |
+
// Unpack
|
113 |
+
$ar = unpack('Cversion/C3flags',$data);
|
114 |
+
if ($ar['version'] == 0) {
|
115 |
+
// 32 bit
|
116 |
+
$ar2 = unpack('Nctime/Nmtime/NtimeScale/Nduration/Nrate/nvolume/ndummy/N2dummy2/N9matrix/N3dummy3/NnextTrack',substr($data,4));
|
117 |
+
} else if ($ar['version'] == 1) {
|
118 |
+
// 64 bit
|
119 |
+
$ar2 = unpack('N2ctime/N2mtime/NtimeScale/N2duration/Nrate/nvolume/ndummy/N2dummy2/N9matrix/N3dummy3/NnextTrack',substr($data,4));
|
120 |
+
} else {
|
121 |
+
throw new Exception('Unhandled version: '.$ar['version']);
|
122 |
+
}
|
123 |
+
|
124 |
+
// Save
|
125 |
+
$this->version = $ar['version'];
|
126 |
+
$this->flags = $ar['flags1']*65536+$ar['flags1']*256+$ar['flags1']*1;
|
127 |
+
$this->ctime = date('r',(isset($ar2['ctime']) ? $ar2['ctime'] : $ar2['ctime1'])-2082826800-self::$timezone);
|
128 |
+
$this->mtime = date('r',(isset($ar2['mtime']) ? $ar2['mtime'] : $ar2['mtime1'])-2082826800-self::$timezone);
|
129 |
+
$this->timeScale = $ar2['timeScale'];
|
130 |
+
$this->duration = (isset($ar2['duration']) ? $ar2['duration'] : $ar2['duration1']);
|
131 |
+
$this->rate = MP4Info_Helper::fromFixed16($ar2['rate']);
|
132 |
+
$this->volume = MP4Info_Helper::fromFixed8($ar2['volume']);
|
133 |
+
} // Constructor
|
134 |
+
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Check if block is compatible with class
|
138 |
+
*
|
139 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
140 |
+
* @param int $boxType
|
141 |
+
* @param MP4Info_Box $parent
|
142 |
+
* @return bool
|
143 |
+
* @access public
|
144 |
+
* @static
|
145 |
+
*/
|
146 |
+
static public function isCompatible($boxType) {
|
147 |
+
return $boxType == 0x6D766864;
|
148 |
+
} // isCompatible method
|
149 |
+
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Creation time getter
|
153 |
+
*
|
154 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
155 |
+
* @return int
|
156 |
+
* @access public
|
157 |
+
*/
|
158 |
+
public function getCreationTime() {
|
159 |
+
return $this->ctime;
|
160 |
+
} // getCreationTime method
|
161 |
+
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Time scale getter
|
165 |
+
*
|
166 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
167 |
+
* @return int
|
168 |
+
* @access public
|
169 |
+
*/
|
170 |
+
public function getTimeScale() {
|
171 |
+
return $this->timeScale;
|
172 |
+
} // getTimeScale method
|
173 |
+
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Duration getter
|
177 |
+
*
|
178 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
179 |
+
* @return int
|
180 |
+
* @access public
|
181 |
+
*/
|
182 |
+
public function getDuration() {
|
183 |
+
return $this->duration;
|
184 |
+
} // getDuration method
|
185 |
+
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Real duration getter
|
189 |
+
*
|
190 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
191 |
+
* @return float
|
192 |
+
* @access public
|
193 |
+
*/
|
194 |
+
public function getRealDuration() {
|
195 |
+
return $this->duration/$this->timeScale;
|
196 |
+
} // getRealDuration method
|
197 |
+
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Rate getter
|
201 |
+
*
|
202 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
203 |
+
* @return int
|
204 |
+
* @access public
|
205 |
+
*/
|
206 |
+
public function getRate() {
|
207 |
+
return $this->rate();
|
208 |
+
} // getRate method
|
209 |
+
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Volume getter
|
213 |
+
*
|
214 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
215 |
+
* @return int
|
216 |
+
* @access public
|
217 |
+
*/
|
218 |
+
public function getVolume() {
|
219 |
+
return $this->volume();
|
220 |
+
} // getVolume method
|
221 |
+
|
222 |
+
|
223 |
+
/**
|
224 |
+
* String converter
|
225 |
+
*
|
226 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
227 |
+
* @return string
|
228 |
+
* @access public
|
229 |
+
*/
|
230 |
+
public function toString() {
|
231 |
+
return '[MP4Info_Box_mvhd]';
|
232 |
+
} // toString method
|
233 |
+
}
|
includes/lib/MP4Info/Box/stsd.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/stsd.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* x.x ??? (STSD)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090601 $Id: stsd.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
* @todo Factor this into a fullbox
|
20 |
+
*/
|
21 |
+
class MP4Info_Box_stsd extends MP4Info_Box {
|
22 |
+
/**
|
23 |
+
* Version
|
24 |
+
*
|
25 |
+
* @var int
|
26 |
+
*/
|
27 |
+
protected $version;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Flags
|
31 |
+
*
|
32 |
+
* @var int
|
33 |
+
*/
|
34 |
+
protected $flags;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Count
|
38 |
+
*
|
39 |
+
* @var int
|
40 |
+
*/
|
41 |
+
protected $count;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Values
|
45 |
+
*
|
46 |
+
* @var string{}
|
47 |
+
*/
|
48 |
+
protected $values = array();
|
49 |
+
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Constructor
|
53 |
+
*
|
54 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
55 |
+
* @param int $totalSize
|
56 |
+
* @param int $boxType
|
57 |
+
* @param file|string $data
|
58 |
+
* @param MP4Info_Box $parent
|
59 |
+
* @return MP4Info_Box_stsd
|
60 |
+
* @access public
|
61 |
+
* @throws MP4Info_Exception
|
62 |
+
*/
|
63 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
64 |
+
if (!self::isCompatible($boxType, $parent)) {
|
65 |
+
throw new Exception('This box isn\'t "stsd"');
|
66 |
+
}
|
67 |
+
|
68 |
+
// Call ancestor
|
69 |
+
parent::__construct($totalSize,$boxType,'',$parent);
|
70 |
+
|
71 |
+
// Get data
|
72 |
+
$data = self::getDataFrom3rd($data, $totalSize);
|
73 |
+
|
74 |
+
// Unpack
|
75 |
+
$ar = unpack('Cversion/C3flags/Ncount',$data);
|
76 |
+
$this->version = $ar['version'];
|
77 |
+
$this->flags = $ar['flags1']*65536+$ar['flags1']*256+$ar['flags1']*1;
|
78 |
+
$this->count = $ar['count'];
|
79 |
+
|
80 |
+
// Unpack SAMPLEDESCRIPTION
|
81 |
+
$desc = substr($data,8);
|
82 |
+
for ($i=0;$i<$this->count;$i++) {
|
83 |
+
$ar = unpack('Nlen',$desc);
|
84 |
+
$type = substr($desc,4,4);
|
85 |
+
$info = substr($desc,8,$ar['len']-8);
|
86 |
+
$desc = substr($desc,$ar['len']);
|
87 |
+
$this->values[$type] = $info;
|
88 |
+
}
|
89 |
+
} // Constructor
|
90 |
+
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Check if block is compatible with class
|
94 |
+
*
|
95 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
96 |
+
* @param int $boxType
|
97 |
+
* @param MP4Info_Box $parent
|
98 |
+
* @return bool
|
99 |
+
* @access public
|
100 |
+
* @static
|
101 |
+
*/
|
102 |
+
static public function isCompatible($boxType, $parent) {
|
103 |
+
return $boxType == 0x73747364;
|
104 |
+
} // isCompatible method
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Values getter
|
108 |
+
*
|
109 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
110 |
+
* @return string{}
|
111 |
+
* @access public
|
112 |
+
*/
|
113 |
+
public function getValues() {
|
114 |
+
return $this->values;
|
115 |
+
} // getValues method
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Value getter
|
119 |
+
*
|
120 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
121 |
+
* @param string $key
|
122 |
+
* @return string
|
123 |
+
* @access public
|
124 |
+
*/
|
125 |
+
public function getValue($key) {
|
126 |
+
return isset($this->values[$key]) ? $this->values[$key] : false;
|
127 |
+
} // getValue method
|
128 |
+
|
129 |
+
/**
|
130 |
+
* String converter
|
131 |
+
*
|
132 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
133 |
+
* @return string
|
134 |
+
* @access public
|
135 |
+
*/
|
136 |
+
public function toString() {
|
137 |
+
return '[MP4Info_Box_stsd:'.implode(',',array_keys($this->values)).']';
|
138 |
+
} // toString method
|
139 |
+
} // MP4Info_Box_stsd class
|
includes/lib/MP4Info/Box/tkhd.php
ADDED
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/tkhd.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* x.x Track Header (TKHD)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.1.20090611 $Id: tkhd.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
* @todo Factor this into a fullbox
|
20 |
+
*/
|
21 |
+
class MP4Info_Box_tkhd extends MP4Info_Box {
|
22 |
+
/**
|
23 |
+
* Version
|
24 |
+
*
|
25 |
+
* @var int
|
26 |
+
*/
|
27 |
+
protected $version;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Flags
|
31 |
+
*
|
32 |
+
* @var int
|
33 |
+
*/
|
34 |
+
protected $flags;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Creation time
|
38 |
+
*
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected $ctime;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Modification time
|
45 |
+
*
|
46 |
+
* @var unknown_type
|
47 |
+
*/
|
48 |
+
protected $mtime;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Time scale
|
52 |
+
*
|
53 |
+
* @var int
|
54 |
+
*/
|
55 |
+
protected $timeScale;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Duration
|
59 |
+
*
|
60 |
+
* @var int
|
61 |
+
*/
|
62 |
+
protected $duration;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Layer
|
66 |
+
*
|
67 |
+
* @var int
|
68 |
+
*/
|
69 |
+
protected $layer;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Volume
|
73 |
+
*
|
74 |
+
* @var float
|
75 |
+
*/
|
76 |
+
protected $volume;
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Width
|
80 |
+
*
|
81 |
+
* @var float
|
82 |
+
*/
|
83 |
+
protected $width;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Height
|
87 |
+
*
|
88 |
+
* @var float
|
89 |
+
*/
|
90 |
+
protected $height;
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Time zone
|
94 |
+
*
|
95 |
+
* @var int
|
96 |
+
* @static
|
97 |
+
*/
|
98 |
+
protected static $timezone = false;
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Constructor
|
102 |
+
*
|
103 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
104 |
+
* @param int $totalSize
|
105 |
+
* @param int $boxType
|
106 |
+
* @param file|string $data
|
107 |
+
* @param MP4Info_Box $parent
|
108 |
+
* @return MP4Info_Box_tkhd
|
109 |
+
* @access public
|
110 |
+
* @throws MP4Info_Exception
|
111 |
+
*/
|
112 |
+
public function __construct($totalSize, $boxType, $data, $parent=false) {
|
113 |
+
if (!self::isCompatible($boxType,$parent)) {
|
114 |
+
throw new Exception('This box isn\'t "tkhd"');
|
115 |
+
}
|
116 |
+
|
117 |
+
// Get timezone
|
118 |
+
if (self::$timezone === false) {
|
119 |
+
self::$timezone = date('Z');
|
120 |
+
}
|
121 |
+
|
122 |
+
// Call ancestor's constructor
|
123 |
+
parent::__construct($totalSize,$boxType,'',$parent);
|
124 |
+
|
125 |
+
// Get data
|
126 |
+
$data = self::getDataFrom3rd($data,$totalSize);
|
127 |
+
|
128 |
+
// Unpack
|
129 |
+
$ar = unpack('Cversion/C3flags',$data);
|
130 |
+
if ($ar['version'] == 0) {
|
131 |
+
// 32 bit
|
132 |
+
$ar2 = unpack('Nctime/Nmtime/NtrackId/Ndummy/Nduration/N2dummy1/nlayer/naltGroup/nvolume/ndummy2/N9matrix/Nwidth/Nheight',substr($data,4));
|
133 |
+
} else if ($ar['version'] == 1) {
|
134 |
+
// 64 bit
|
135 |
+
$ar2 = unpack('N2ctime/N2mtime/NtrackId/Ndummy/N2duration/N2dummy1/nlayer/naltGroup/nvolume/ndummy2/N9matrix/Nwidth/Nheight',substr($data,4));
|
136 |
+
} else {
|
137 |
+
throw new Exception('Unhandled version: '.$ar['version']);
|
138 |
+
}
|
139 |
+
|
140 |
+
// Save
|
141 |
+
$this->version = $ar['version'];
|
142 |
+
$this->flags = $ar['flags1']*65536+$ar['flags1']*256+$ar['flags1']*1;
|
143 |
+
$this->ctime = date('r',(isset($ar2['ctime']) ? $ar2['ctime'] : $ar2['ctime1'])-2082826800-self::$timezone);
|
144 |
+
$this->mtime = date('r',(isset($ar2['mtime']) ? $ar2['mtime'] : $ar2['mtime1'])-2082826800-self::$timezone);
|
145 |
+
$this->trackId = $ar2['trackId'];
|
146 |
+
$this->duration = (isset($ar2['duration']) ? $ar2['duration'] : $ar2['duration1']);
|
147 |
+
$this->layer = ($ar2['layer']>32767 ? $ar2['layer']-65536 : $ar2['layer']);
|
148 |
+
$this->volume = MP4Info_Helper::fromFixed8($ar2['volume']);
|
149 |
+
$this->width = MP4Info_Helper::fromFixed16($ar2['width']);
|
150 |
+
$this->height = MP4Info_Helper::fromFixed16($ar2['height']);
|
151 |
+
} // Constructor
|
152 |
+
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Check if block is compatible with class
|
156 |
+
*
|
157 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
158 |
+
* @param int $boxType
|
159 |
+
* @param MP4Info_Box $parent
|
160 |
+
* @return bool
|
161 |
+
* @access public
|
162 |
+
* @static
|
163 |
+
*/
|
164 |
+
static public function isCompatible($boxType, $parent) {
|
165 |
+
return $boxType == 0x746b6864;
|
166 |
+
} // isCompatible method
|
167 |
+
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Width getter
|
171 |
+
*
|
172 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
173 |
+
* @return float
|
174 |
+
* @access public
|
175 |
+
*/
|
176 |
+
public function getWidth() {
|
177 |
+
return $this->width;
|
178 |
+
} // getWidth method
|
179 |
+
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Height getter
|
183 |
+
*
|
184 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
185 |
+
* @return float
|
186 |
+
* @access public
|
187 |
+
*/
|
188 |
+
public function getHeight() {
|
189 |
+
return $this->height;
|
190 |
+
} // getHeight method
|
191 |
+
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Duration getter
|
195 |
+
*
|
196 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
197 |
+
* @return int
|
198 |
+
* @access public
|
199 |
+
*/
|
200 |
+
public function getDuration() {
|
201 |
+
return $this->duration;
|
202 |
+
} // getDuration method
|
203 |
+
|
204 |
+
|
205 |
+
/**
|
206 |
+
* String converter
|
207 |
+
*
|
208 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
209 |
+
* @return string
|
210 |
+
* @access public
|
211 |
+
*/
|
212 |
+
public function toString() {
|
213 |
+
return '[MP4Info_Box_tkhd]';
|
214 |
+
} // toString method
|
215 |
+
} // MP4Info_Box_tkhd class
|
includes/lib/MP4Info/Box/uuid.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Box/uuid.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* x.x ??? (UUID)
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090601 $Id: uuid.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
* @todo Limited to XMP meta data... extend
|
20 |
+
*/
|
21 |
+
class MP4Info_Box_uuid extends MP4Info_Box {
|
22 |
+
// {{{ Constants
|
23 |
+
const UUID_XMP_METADATA = 'BE7ACFCB97A942';
|
24 |
+
// }}} Constants
|
25 |
+
|
26 |
+
/**
|
27 |
+
* UUID
|
28 |
+
*
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected $uuid;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* XMP data
|
35 |
+
*
|
36 |
+
* @var string
|
37 |
+
*/
|
38 |
+
protected $xmp;
|
39 |
+
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Constructor
|
43 |
+
*
|
44 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
45 |
+
* @param int $totalSize
|
46 |
+
* @param int $boxType
|
47 |
+
* @param file|string $data
|
48 |
+
* @param MP4Info_Box $parent
|
49 |
+
* @return MP4Info_Box_uuid
|
50 |
+
* @access public
|
51 |
+
* @throws MP4Info_Exception
|
52 |
+
*/
|
53 |
+
public function __construct($totalSize, $boxType, $data, $parent) {
|
54 |
+
if (!self::isCompatible($boxType, $parent)) {
|
55 |
+
throw new Exception('This box isn\'t "uuid"');
|
56 |
+
}
|
57 |
+
|
58 |
+
// Call ancestor
|
59 |
+
parent::__construct($totalSize,$boxType,'',$parent);
|
60 |
+
|
61 |
+
// Unpack
|
62 |
+
$data = self::getDataFrom3rd($data,$totalSize);
|
63 |
+
$this->uuid = bin2hex(substr($data,0,16));
|
64 |
+
$this->xmp = substr($data,16);
|
65 |
+
} // Constructor
|
66 |
+
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Check if block is compatible with class
|
70 |
+
*
|
71 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
72 |
+
* @param int $boxType
|
73 |
+
* @param MP4Info_Box $parent
|
74 |
+
* @return bool
|
75 |
+
* @access public
|
76 |
+
* @static
|
77 |
+
*/
|
78 |
+
static public function isCompatible($boxType, $parent) {
|
79 |
+
return $boxType == 0x75756964;
|
80 |
+
} // isCompatible method
|
81 |
+
|
82 |
+
|
83 |
+
/**
|
84 |
+
* UUID getter
|
85 |
+
*
|
86 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
87 |
+
* @return string
|
88 |
+
* @access public
|
89 |
+
*/
|
90 |
+
public function getUUID() {
|
91 |
+
return strtoupper($this->uuid);
|
92 |
+
} // getUUID method
|
93 |
+
|
94 |
+
|
95 |
+
/**
|
96 |
+
* XMP Meta data getter
|
97 |
+
*
|
98 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
99 |
+
* @return string
|
100 |
+
* @access public
|
101 |
+
*/
|
102 |
+
public function getXMPMetaData() {
|
103 |
+
return (substr(strtoupper($this->uuid),0,14) == self::UUID_XMP_METADATA) ? $this->xmp : false;
|
104 |
+
} // getXMPMetaData method
|
105 |
+
|
106 |
+
|
107 |
+
/**
|
108 |
+
* String converter
|
109 |
+
*
|
110 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
111 |
+
* @return string
|
112 |
+
* @access public
|
113 |
+
*/
|
114 |
+
public function toString() {
|
115 |
+
return '[MP4Info_Box_uuid]';
|
116 |
+
} // toString method
|
117 |
+
} // MP4Info_Box_uuid class
|
includes/lib/MP4Info/Exception.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Exception.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* MP4Info Exception Class
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.1.20090611 $Id: Exception.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
|
21 |
+
class MP4Info_Exception extends Exception {
|
22 |
+
// {{{ Constants
|
23 |
+
const CODE_UNKNOWN = 0x00;
|
24 |
+
const CODE_INCOMPATIBLE = 0x01;
|
25 |
+
// }}} Constants
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Box type
|
29 |
+
*
|
30 |
+
* @var int
|
31 |
+
*/
|
32 |
+
protected $boxType;
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Constructor
|
37 |
+
*
|
38 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
39 |
+
* @param string $message
|
40 |
+
* @param int $code
|
41 |
+
* @param int $boxType
|
42 |
+
* @return MP4Info_Exception
|
43 |
+
* @access public
|
44 |
+
*/
|
45 |
+
public function __construct($message, $code = 0, $boxType=false) {
|
46 |
+
parent::__construct($message, $code);
|
47 |
+
$this->boxType = $boxType;
|
48 |
+
} // Constructor
|
49 |
+
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Box type getter
|
53 |
+
*
|
54 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
55 |
+
* @return int
|
56 |
+
* @access public
|
57 |
+
*/
|
58 |
+
public function getBoxType() {
|
59 |
+
return $this->boxType;
|
60 |
+
} // getBoxType method
|
61 |
+
} // MP4Info_Exception class
|
includes/lib/MP4Info/Helper.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* MP4Info
|
4 |
+
*
|
5 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
6 |
+
* @copyright Copyright (c) 2006-2009 Tommy Lacroix
|
7 |
+
* @license LGPL version 3, http://www.gnu.org/licenses/lgpl.html
|
8 |
+
* @package php-mp4info
|
9 |
+
* @link $HeadURL: https://php-mp4info.googlecode.com/svn/trunk/MP4Info/Helper.php $
|
10 |
+
*/
|
11 |
+
|
12 |
+
// ---
|
13 |
+
|
14 |
+
/**
|
15 |
+
* MP4Info helper functions
|
16 |
+
*
|
17 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
18 |
+
* @version 1.0.20090601 $Id: Helper.php 2 2009-06-11 14:12:31Z lacroix.tommy@gmail.com $
|
19 |
+
*/
|
20 |
+
class MP4Info_Helper {
|
21 |
+
/**
|
22 |
+
* Convert a short to a float
|
23 |
+
*
|
24 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
25 |
+
* @param int $n
|
26 |
+
* @return float
|
27 |
+
* @access public
|
28 |
+
* @static
|
29 |
+
*/
|
30 |
+
public static function fromFixed8($n) {
|
31 |
+
return $n / 256;
|
32 |
+
} // fromFixed8 method
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Convert a long to a float
|
37 |
+
*
|
38 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
39 |
+
* @param int $n
|
40 |
+
* @return float
|
41 |
+
* @access public
|
42 |
+
* @static
|
43 |
+
*/
|
44 |
+
public static function fromFixed16($n) {
|
45 |
+
return $n / 65536;
|
46 |
+
} // fromFixed16 method
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Convert binary packed (5bit) letters to string
|
51 |
+
*
|
52 |
+
* @author Tommy Lacroix <lacroix.tommy@gmail.com>
|
53 |
+
* @param int $n
|
54 |
+
* @param int $pad
|
55 |
+
* @return string
|
56 |
+
* @access public
|
57 |
+
* @static
|
58 |
+
*/
|
59 |
+
public static function fromPackedLetters($n, $pad=1) {
|
60 |
+
$s = decbin($n);
|
61 |
+
$s .= str_repeat('0',8-(strlen($s)%8));
|
62 |
+
$s = substr($s,0,-$pad);
|
63 |
+
$out = '';
|
64 |
+
while (strlen($s)>=5) {
|
65 |
+
$letter = substr($s,0,5);
|
66 |
+
$nl = bindec($letter) + 0x60;
|
67 |
+
$out .= chr($nl);
|
68 |
+
$s = substr($s,5);
|
69 |
+
}
|
70 |
+
return $out;
|
71 |
+
} // fromPackedLetters method
|
72 |
+
} // MP4Info_Helper class
|
includes/media-element/background.png
ADDED
Binary file
|
includes/media-element/bigplay.png
ADDED
Binary file
|
includes/media-element/controls-ted.png
ADDED
Binary file
|
includes/media-element/controls-wmp-bg.png
ADDED
Binary file
|
includes/media-element/controls-wmp.png
ADDED
Binary file
|
includes/media-element/controls.png
ADDED
Binary file
|
includes/media-element/flashmediaelement.swf
ADDED
Binary file
|
includes/media-element/loading.gif
ADDED
Binary file
|
includes/media-element/mediaelement-and-player.js
ADDED
@@ -0,0 +1,4262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* MediaElement.js
|
3 |
+
* HTML5 <video> and <audio> shim and player
|
4 |
+
* http://mediaelementjs.com/
|
5 |
+
*
|
6 |
+
* Creates a JavaScript object that mimics HTML5 MediaElement API
|
7 |
+
* for browsers that don't understand HTML5 or can't play the provided codec
|
8 |
+
* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
|
9 |
+
*
|
10 |
+
* Copyright 2010-2012, John Dyer (http://j.hn)
|
11 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
12 |
+
*
|
13 |
+
*/
|
14 |
+
// Namespace
|
15 |
+
var mejs = mejs || {};
|
16 |
+
|
17 |
+
// version number
|
18 |
+
mejs.version = '2.9.1';
|
19 |
+
|
20 |
+
// player number (for missing, same id attr)
|
21 |
+
mejs.meIndex = 0;
|
22 |
+
|
23 |
+
// media types accepted by plugins
|
24 |
+
mejs.plugins = {
|
25 |
+
silverlight: [
|
26 |
+
{version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
|
27 |
+
],
|
28 |
+
flash: [
|
29 |
+
{version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg', 'video/youtube', 'video/x-youtube']}
|
30 |
+
//,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!)
|
31 |
+
],
|
32 |
+
youtube: [
|
33 |
+
{version: null, types: ['video/youtube', 'video/x-youtube']}
|
34 |
+
],
|
35 |
+
vimeo: [
|
36 |
+
{version: null, types: ['video/vimeo']}
|
37 |
+
]
|
38 |
+
};
|
39 |
+
|
40 |
+
/*
|
41 |
+
Utility methods
|
42 |
+
*/
|
43 |
+
mejs.Utility = {
|
44 |
+
encodeUrl: function(url) {
|
45 |
+
return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
|
46 |
+
},
|
47 |
+
escapeHTML: function(s) {
|
48 |
+
return s.toString().split('&').join('&').split('<').join('<').split('"').join('"');
|
49 |
+
},
|
50 |
+
absolutizeUrl: function(url) {
|
51 |
+
var el = document.createElement('div');
|
52 |
+
el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
|
53 |
+
return el.firstChild.href;
|
54 |
+
},
|
55 |
+
getScriptPath: function(scriptNames) {
|
56 |
+
var
|
57 |
+
i = 0,
|
58 |
+
j,
|
59 |
+
path = '',
|
60 |
+
name = '',
|
61 |
+
script,
|
62 |
+
scripts = document.getElementsByTagName('script'),
|
63 |
+
il = scripts.length,
|
64 |
+
jl = scriptNames.length;
|
65 |
+
|
66 |
+
for (; i < il; i++) {
|
67 |
+
script = scripts[i].src;
|
68 |
+
for (j = 0; j < jl; j++) {
|
69 |
+
name = scriptNames[j];
|
70 |
+
if (script.indexOf(name) > -1) {
|
71 |
+
path = script.substring(0, script.indexOf(name));
|
72 |
+
break;
|
73 |
+
}
|
74 |
+
}
|
75 |
+
if (path !== '') {
|
76 |
+
break;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
return path;
|
80 |
+
},
|
81 |
+
secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
|
82 |
+
//add framecount
|
83 |
+
if (typeof showFrameCount == 'undefined') {
|
84 |
+
showFrameCount=false;
|
85 |
+
} else if(typeof fps == 'undefined') {
|
86 |
+
fps = 25;
|
87 |
+
}
|
88 |
+
|
89 |
+
var hours = Math.floor(time / 3600) % 24,
|
90 |
+
minutes = Math.floor(time / 60) % 60,
|
91 |
+
seconds = Math.floor(time % 60),
|
92 |
+
frames = Math.floor(((time % 1)*fps).toFixed(3)),
|
93 |
+
result =
|
94 |
+
( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
|
95 |
+
+ (minutes < 10 ? '0' + minutes : minutes) + ':'
|
96 |
+
+ (seconds < 10 ? '0' + seconds : seconds)
|
97 |
+
+ ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
|
98 |
+
|
99 |
+
return result;
|
100 |
+
},
|
101 |
+
|
102 |
+
timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
|
103 |
+
if (typeof showFrameCount == 'undefined') {
|
104 |
+
showFrameCount=false;
|
105 |
+
} else if(typeof fps == 'undefined') {
|
106 |
+
fps = 25;
|
107 |
+
}
|
108 |
+
|
109 |
+
var tc_array = hh_mm_ss_ff.split(":"),
|
110 |
+
tc_hh = parseInt(tc_array[0], 10),
|
111 |
+
tc_mm = parseInt(tc_array[1], 10),
|
112 |
+
tc_ss = parseInt(tc_array[2], 10),
|
113 |
+
tc_ff = 0,
|
114 |
+
tc_in_seconds = 0;
|
115 |
+
|
116 |
+
if (showFrameCount) {
|
117 |
+
tc_ff = parseInt(tc_array[3])/fps;
|
118 |
+
}
|
119 |
+
|
120 |
+
tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
|
121 |
+
|
122 |
+
return tc_in_seconds;
|
123 |
+
},
|
124 |
+
|
125 |
+
/* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
|
126 |
+
removeSwf: function(id) {
|
127 |
+
var obj = document.getElementById(id);
|
128 |
+
if (obj && obj.nodeName == "OBJECT") {
|
129 |
+
if (mejs.MediaFeatures.isIE) {
|
130 |
+
obj.style.display = "none";
|
131 |
+
(function(){
|
132 |
+
if (obj.readyState == 4) {
|
133 |
+
mejs.Utility.removeObjectInIE(id);
|
134 |
+
} else {
|
135 |
+
setTimeout(arguments.callee, 10);
|
136 |
+
}
|
137 |
+
})();
|
138 |
+
} else {
|
139 |
+
obj.parentNode.removeChild(obj);
|
140 |
+
}
|
141 |
+
}
|
142 |
+
},
|
143 |
+
removeObjectInIE: function(id) {
|
144 |
+
var obj = document.getElementById(id);
|
145 |
+
if (obj) {
|
146 |
+
for (var i in obj) {
|
147 |
+
if (typeof obj[i] == "function") {
|
148 |
+
obj[i] = null;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
obj.parentNode.removeChild(obj);
|
152 |
+
}
|
153 |
+
}
|
154 |
+
};
|
155 |
+
|
156 |
+
|
157 |
+
// Core detector, plugins are added below
|
158 |
+
mejs.PluginDetector = {
|
159 |
+
|
160 |
+
// main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
|
161 |
+
hasPluginVersion: function(plugin, v) {
|
162 |
+
var pv = this.plugins[plugin];
|
163 |
+
v[1] = v[1] || 0;
|
164 |
+
v[2] = v[2] || 0;
|
165 |
+
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
|
166 |
+
},
|
167 |
+
|
168 |
+
// cached values
|
169 |
+
nav: window.navigator,
|
170 |
+
ua: window.navigator.userAgent.toLowerCase(),
|
171 |
+
|
172 |
+
// stored version numbers
|
173 |
+
plugins: [],
|
174 |
+
|
175 |
+
// runs detectPlugin() and stores the version number
|
176 |
+
addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
|
177 |
+
this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
|
178 |
+
},
|
179 |
+
|
180 |
+
// get the version number from the mimetype (all but IE) or ActiveX (IE)
|
181 |
+
detectPlugin: function(pluginName, mimeType, activeX, axDetect) {
|
182 |
+
|
183 |
+
var version = [0,0,0],
|
184 |
+
description,
|
185 |
+
i,
|
186 |
+
ax;
|
187 |
+
|
188 |
+
// Firefox, Webkit, Opera
|
189 |
+
if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
|
190 |
+
description = this.nav.plugins[pluginName].description;
|
191 |
+
if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
|
192 |
+
version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
|
193 |
+
for (i=0; i<version.length; i++) {
|
194 |
+
version[i] = parseInt(version[i].match(/\d+/), 10);
|
195 |
+
}
|
196 |
+
}
|
197 |
+
// Internet Explorer / ActiveX
|
198 |
+
} else if (typeof(window.ActiveXObject) != 'undefined') {
|
199 |
+
try {
|
200 |
+
ax = new ActiveXObject(activeX);
|
201 |
+
if (ax) {
|
202 |
+
version = axDetect(ax);
|
203 |
+
}
|
204 |
+
}
|
205 |
+
catch (e) { }
|
206 |
+
}
|
207 |
+
return version;
|
208 |
+
}
|
209 |
+
};
|
210 |
+
|
211 |
+
// Add Flash detection
|
212 |
+
mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
|
213 |
+
// adapted from SWFObject
|
214 |
+
var version = [],
|
215 |
+
d = ax.GetVariable("$version");
|
216 |
+
if (d) {
|
217 |
+
d = d.split(" ")[1].split(",");
|
218 |
+
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
219 |
+
}
|
220 |
+
return version;
|
221 |
+
});
|
222 |
+
|
223 |
+
// Add Silverlight detection
|
224 |
+
mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
|
225 |
+
// Silverlight cannot report its version number to IE
|
226 |
+
// but it does have a isVersionSupported function, so we have to loop through it to get a version number.
|
227 |
+
// adapted from http://www.silverlightversion.com/
|
228 |
+
var v = [0,0,0,0],
|
229 |
+
loopMatch = function(ax, v, i, n) {
|
230 |
+
while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
|
231 |
+
v[i]+=n;
|
232 |
+
}
|
233 |
+
v[i] -= n;
|
234 |
+
};
|
235 |
+
loopMatch(ax, v, 0, 1);
|
236 |
+
loopMatch(ax, v, 1, 1);
|
237 |
+
loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
|
238 |
+
loopMatch(ax, v, 2, 1000);
|
239 |
+
loopMatch(ax, v, 2, 100);
|
240 |
+
loopMatch(ax, v, 2, 10);
|
241 |
+
loopMatch(ax, v, 2, 1);
|
242 |
+
loopMatch(ax, v, 3, 1);
|
243 |
+
|
244 |
+
return v;
|
245 |
+
});
|
246 |
+
// add adobe acrobat
|
247 |
+
/*
|
248 |
+
PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) {
|
249 |
+
var version = [],
|
250 |
+
d = ax.GetVersions().split(',')[0].split('=')[1].split('.');
|
251 |
+
|
252 |
+
if (d) {
|
253 |
+
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
254 |
+
}
|
255 |
+
return version;
|
256 |
+
});
|
257 |
+
*/
|
258 |
+
// necessary detection (fixes for <IE9)
|
259 |
+
mejs.MediaFeatures = {
|
260 |
+
init: function() {
|
261 |
+
var
|
262 |
+
t = this,
|
263 |
+
d = document,
|
264 |
+
nav = mejs.PluginDetector.nav,
|
265 |
+
ua = mejs.PluginDetector.ua.toLowerCase(),
|
266 |
+
i,
|
267 |
+
v,
|
268 |
+
html5Elements = ['source','track','audio','video'];
|
269 |
+
|
270 |
+
// detect browsers (only the ones that have some kind of quirk we need to work around)
|
271 |
+
t.isiPad = (ua.match(/ipad/i) !== null);
|
272 |
+
t.isiPhone = (ua.match(/iphone/i) !== null);
|
273 |
+
t.isiOS = t.isiPhone || t.isiPad;
|
274 |
+
t.isAndroid = (ua.match(/android/i) !== null);
|
275 |
+
t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
|
276 |
+
t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
|
277 |
+
t.isChrome = (ua.match(/chrome/gi) !== null);
|
278 |
+
t.isFirefox = (ua.match(/firefox/gi) !== null);
|
279 |
+
t.isWebkit = (ua.match(/webkit/gi) !== null);
|
280 |
+
t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit;
|
281 |
+
t.isOpera = (ua.match(/opera/gi) !== null);
|
282 |
+
t.hasTouch = ('ontouchstart' in window);
|
283 |
+
|
284 |
+
// create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
|
285 |
+
for (i=0; i<html5Elements.length; i++) {
|
286 |
+
v = document.createElement(html5Elements[i]);
|
287 |
+
}
|
288 |
+
|
289 |
+
t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid);
|
290 |
+
|
291 |
+
// detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails)
|
292 |
+
|
293 |
+
// iOS
|
294 |
+
t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined');
|
295 |
+
|
296 |
+
// Webkit/firefox
|
297 |
+
t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
|
298 |
+
t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined');
|
299 |
+
|
300 |
+
t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen);
|
301 |
+
t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen;
|
302 |
+
if (t.hasMozNativeFullScreen) {
|
303 |
+
t.nativeFullScreenEnabled = v.mozFullScreenEnabled;
|
304 |
+
}
|
305 |
+
|
306 |
+
|
307 |
+
if (this.isChrome) {
|
308 |
+
t.hasSemiNativeFullScreen = false;
|
309 |
+
}
|
310 |
+
|
311 |
+
if (t.hasTrueNativeFullScreen) {
|
312 |
+
t.fullScreenEventName = (t.hasWebkitNativeFullScreen) ? 'webkitfullscreenchange' : 'mozfullscreenchange';
|
313 |
+
|
314 |
+
|
315 |
+
t.isFullScreen = function() {
|
316 |
+
if (v.mozRequestFullScreen) {
|
317 |
+
return d.mozFullScreen;
|
318 |
+
} else if (v.webkitRequestFullScreen) {
|
319 |
+
return d.webkitIsFullScreen;
|
320 |
+
}
|
321 |
+
}
|
322 |
+
|
323 |
+
t.requestFullScreen = function(el) {
|
324 |
+
|
325 |
+
if (t.hasWebkitNativeFullScreen) {
|
326 |
+
el.webkitRequestFullScreen();
|
327 |
+
} else if (t.hasMozNativeFullScreen) {
|
328 |
+
el.mozRequestFullScreen();
|
329 |
+
}
|
330 |
+
}
|
331 |
+
|
332 |
+
t.cancelFullScreen = function() {
|
333 |
+
if (t.hasWebkitNativeFullScreen) {
|
334 |
+
document.webkitCancelFullScreen();
|
335 |
+
} else if (t.hasMozNativeFullScreen) {
|
336 |
+
document.mozCancelFullScreen();
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
}
|
341 |
+
|
342 |
+
|
343 |
+
// OS X 10.5 can't do this even if it says it can :(
|
344 |
+
if (t.hasSemiNativeFullScreen && ua.match(/mac os x 10_5/i)) {
|
345 |
+
t.hasNativeFullScreen = false;
|
346 |
+
t.hasSemiNativeFullScreen = false;
|
347 |
+
}
|
348 |
+
|
349 |
+
}
|
350 |
+
};
|
351 |
+
mejs.MediaFeatures.init();
|
352 |
+
|
353 |
+
|
354 |
+
/*
|
355 |
+
extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
|
356 |
+
*/
|
357 |
+
mejs.HtmlMediaElement = {
|
358 |
+
pluginType: 'native',
|
359 |
+
isFullScreen: false,
|
360 |
+
|
361 |
+
setCurrentTime: function (time) {
|
362 |
+
this.currentTime = time;
|
363 |
+
},
|
364 |
+
|
365 |
+
setMuted: function (muted) {
|
366 |
+
this.muted = muted;
|
367 |
+
},
|
368 |
+
|
369 |
+
setVolume: function (volume) {
|
370 |
+
this.volume = volume;
|
371 |
+
},
|
372 |
+
|
373 |
+
// for parity with the plugin versions
|
374 |
+
stop: function () {
|
375 |
+
this.pause();
|
376 |
+
},
|
377 |
+
|
378 |
+
// This can be a url string
|
379 |
+
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
380 |
+
setSrc: function (url) {
|
381 |
+
|
382 |
+
// Fix for IE9 which can't set .src when there are <source> elements. Awesome, right?
|
383 |
+
var
|
384 |
+
existingSources = this.getElementsByTagName('source');
|
385 |
+
while (existingSources.length > 0){
|
386 |
+
this.removeChild(existingSources[0]);
|
387 |
+
}
|
388 |
+
|
389 |
+
if (typeof url == 'string') {
|
390 |
+
this.src = url;
|
391 |
+
} else {
|
392 |
+
var i, media;
|
393 |
+
|
394 |
+
for (i=0; i<url.length; i++) {
|
395 |
+
media = url[i];
|
396 |
+
if (this.canPlayType(media.type)) {
|
397 |
+
this.src = media.src;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
}
|
401 |
+
},
|
402 |
+
|
403 |
+
setVideoSize: function (width, height) {
|
404 |
+
this.width = width;
|
405 |
+
this.height = height;
|
406 |
+
}
|
407 |
+
};
|
408 |
+
|
409 |
+
/*
|
410 |
+
Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember]
|
411 |
+
*/
|
412 |
+
mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
|
413 |
+
this.id = pluginid;
|
414 |
+
this.pluginType = pluginType;
|
415 |
+
this.src = mediaUrl;
|
416 |
+
this.events = {};
|
417 |
+
};
|
418 |
+
|
419 |
+
// JavaScript values and ExternalInterface methods that match HTML5 video properties methods
|
420 |
+
// http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html
|
421 |
+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
422 |
+
mejs.PluginMediaElement.prototype = {
|
423 |
+
|
424 |
+
// special
|
425 |
+
pluginElement: null,
|
426 |
+
pluginType: '',
|
427 |
+
isFullScreen: false,
|
428 |
+
|
429 |
+
// not implemented :(
|
430 |
+
playbackRate: -1,
|
431 |
+
defaultPlaybackRate: -1,
|
432 |
+
seekable: [],
|
433 |
+
played: [],
|
434 |
+
|
435 |
+
// HTML5 read-only properties
|
436 |
+
paused: true,
|
437 |
+
ended: false,
|
438 |
+
seeking: false,
|
439 |
+
duration: 0,
|
440 |
+
error: null,
|
441 |
+
tagName: '',
|
442 |
+
|
443 |
+
// HTML5 get/set properties, but only set (updated by event handlers)
|
444 |
+
muted: false,
|
445 |
+
volume: 1,
|
446 |
+
currentTime: 0,
|
447 |
+
|
448 |
+
// HTML5 methods
|
449 |
+
play: function () {
|
450 |
+
if (this.pluginApi != null) {
|
451 |
+
if (this.pluginType == 'youtube') {
|
452 |
+
this.pluginApi.playVideo();
|
453 |
+
} else {
|
454 |
+
this.pluginApi.playMedia();
|
455 |
+
}
|
456 |
+
this.paused = false;
|
457 |
+
}
|
458 |
+
},
|
459 |
+
load: function () {
|
460 |
+
if (this.pluginApi != null) {
|
461 |
+
if (this.pluginType == 'youtube') {
|
462 |
+
} else {
|
463 |
+
this.pluginApi.loadMedia();
|
464 |
+
}
|
465 |
+
|
466 |
+
this.paused = false;
|
467 |
+
}
|
468 |
+
},
|
469 |
+
pause: function () {
|
470 |
+
if (this.pluginApi != null) {
|
471 |
+
if (this.pluginType == 'youtube') {
|
472 |
+
this.pluginApi.pauseVideo();
|
473 |
+
} else {
|
474 |
+
this.pluginApi.pauseMedia();
|
475 |
+
}
|
476 |
+
|
477 |
+
|
478 |
+
this.paused = true;
|
479 |
+
}
|
480 |
+
},
|
481 |
+
stop: function () {
|
482 |
+
if (this.pluginApi != null) {
|
483 |
+
if (this.pluginType == 'youtube') {
|
484 |
+
this.pluginApi.stopVideo();
|
485 |
+
} else {
|
486 |
+
this.pluginApi.stopMedia();
|
487 |
+
}
|
488 |
+
this.paused = true;
|
489 |
+
}
|
490 |
+
},
|
491 |
+
canPlayType: function(type) {
|
492 |
+
var i,
|
493 |
+
j,
|
494 |
+
pluginInfo,
|
495 |
+
pluginVersions = mejs.plugins[this.pluginType];
|
496 |
+
|
497 |
+
for (i=0; i<pluginVersions.length; i++) {
|
498 |
+
pluginInfo = pluginVersions[i];
|
499 |
+
|
500 |
+
// test if user has the correct plugin version
|
501 |
+
if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) {
|
502 |
+
|
503 |
+
// test for plugin playback types
|
504 |
+
for (j=0; j<pluginInfo.types.length; j++) {
|
505 |
+
// find plugin that can play the type
|
506 |
+
if (type == pluginInfo.types[j]) {
|
507 |
+
return true;
|
508 |
+
}
|
509 |
+
}
|
510 |
+
}
|
511 |
+
}
|
512 |
+
|
513 |
+
return false;
|
514 |
+
},
|
515 |
+
|
516 |
+
positionFullscreenButton: function(x,y,visibleAndAbove) {
|
517 |
+
if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) {
|
518 |
+
this.pluginApi.positionFullscreenButton(x,y,visibleAndAbove);
|
519 |
+
}
|
520 |
+
},
|
521 |
+
|
522 |
+
hideFullscreenButton: function() {
|
523 |
+
if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) {
|
524 |
+
this.pluginApi.hideFullscreenButton();
|
525 |
+
}
|
526 |
+
},
|
527 |
+
|
528 |
+
|
529 |
+
// custom methods since not all JavaScript implementations support get/set
|
530 |
+
|
531 |
+
// This can be a url string
|
532 |
+
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
533 |
+
setSrc: function (url) {
|
534 |
+
if (typeof url == 'string') {
|
535 |
+
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url));
|
536 |
+
this.src = mejs.Utility.absolutizeUrl(url);
|
537 |
+
} else {
|
538 |
+
var i, media;
|
539 |
+
|
540 |
+
for (i=0; i<url.length; i++) {
|
541 |
+
media = url[i];
|
542 |
+
if (this.canPlayType(media.type)) {
|
543 |
+
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
|
544 |
+
this.src = mejs.Utility.absolutizeUrl(url);
|
545 |
+
}
|
546 |
+
}
|
547 |
+
}
|
548 |
+
|
549 |
+
},
|
550 |
+
setCurrentTime: function (time) {
|
551 |
+
if (this.pluginApi != null) {
|
552 |
+
if (this.pluginType == 'youtube') {
|
553 |
+
this.pluginApi.seekTo(time);
|
554 |
+
} else {
|
555 |
+
this.pluginApi.setCurrentTime(time);
|
556 |
+
}
|
557 |
+
|
558 |
+
|
559 |
+
|
560 |
+
this.currentTime = time;
|
561 |
+
}
|
562 |
+
},
|
563 |
+
setVolume: function (volume) {
|
564 |
+
if (this.pluginApi != null) {
|
565 |
+
// same on YouTube and MEjs
|
566 |
+
if (this.pluginType == 'youtube') {
|
567 |
+
this.pluginApi.setVolume(volume * 100);
|
568 |
+
} else {
|
569 |
+
this.pluginApi.setVolume(volume);
|
570 |
+
}
|
571 |
+
this.volume = volume;
|
572 |
+
}
|
573 |
+
},
|
574 |
+
setMuted: function (muted) {
|
575 |
+
if (this.pluginApi != null) {
|
576 |
+
if (this.pluginType == 'youtube') {
|
577 |
+
if (muted) {
|
578 |
+
this.pluginApi.mute();
|
579 |
+
} else {
|
580 |
+
this.pluginApi.unMute();
|
581 |
+
}
|
582 |
+
this.muted = muted;
|
583 |
+
this.dispatchEvent('volumechange');
|
584 |
+
} else {
|
585 |
+
this.pluginApi.setMuted(muted);
|
586 |
+
}
|
587 |
+
this.muted = muted;
|
588 |
+
}
|
589 |
+
},
|
590 |
+
|
591 |
+
// additional non-HTML5 methods
|
592 |
+
setVideoSize: function (width, height) {
|
593 |
+
|
594 |
+
//if (this.pluginType == 'flash' || this.pluginType == 'silverlight') {
|
595 |
+
if ( this.pluginElement.style) {
|
596 |
+
this.pluginElement.style.width = width + 'px';
|
597 |
+
this.pluginElement.style.height = height + 'px';
|
598 |
+
}
|
599 |
+
if (this.pluginApi != null && this.pluginApi.setVideoSize) {
|
600 |
+
this.pluginApi.setVideoSize(width, height);
|
601 |
+
}
|
602 |
+
//}
|
603 |
+
},
|
604 |
+
|
605 |
+
setFullscreen: function (fullscreen) {
|
606 |
+
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
607 |
+
this.pluginApi.setFullscreen(fullscreen);
|
608 |
+
}
|
609 |
+
},
|
610 |
+
|
611 |
+
enterFullScreen: function() {
|
612 |
+
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
613 |
+
this.setFullscreen(true);
|
614 |
+
}
|
615 |
+
|
616 |
+
},
|
617 |
+
|
618 |
+
exitFullScreen: function() {
|
619 |
+
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
620 |
+
this.setFullscreen(false);
|
621 |
+
}
|
622 |
+
},
|
623 |
+
|
624 |
+
// start: fake events
|
625 |
+
addEventListener: function (eventName, callback, bubble) {
|
626 |
+
this.events[eventName] = this.events[eventName] || [];
|
627 |
+
this.events[eventName].push(callback);
|
628 |
+
},
|
629 |
+
removeEventListener: function (eventName, callback) {
|
630 |
+
if (!eventName) { this.events = {}; return true; }
|
631 |
+
var callbacks = this.events[eventName];
|
632 |
+
if (!callbacks) return true;
|
633 |
+
if (!callback) { this.events[eventName] = []; return true; }
|
634 |
+
for (i = 0; i < callbacks.length; i++) {
|
635 |
+
if (callbacks[i] === callback) {
|
636 |
+
this.events[eventName].splice(i, 1);
|
637 |
+
return true;
|
638 |
+
}
|
639 |
+
}
|
640 |
+
return false;
|
641 |
+
},
|
642 |
+
dispatchEvent: function (eventName) {
|
643 |
+
var i,
|
644 |
+
args,
|
645 |
+
callbacks = this.events[eventName];
|
646 |
+
|
647 |
+
if (callbacks) {
|
648 |
+
args = Array.prototype.slice.call(arguments, 1);
|
649 |
+
for (i = 0; i < callbacks.length; i++) {
|
650 |
+
callbacks[i].apply(null, args);
|
651 |
+
}
|
652 |
+
}
|
653 |
+
},
|
654 |
+
// end: fake events
|
655 |
+
|
656 |
+
// fake DOM attribute methods
|
657 |
+
attributes: {},
|
658 |
+
hasAttribute: function(name){
|
659 |
+
return (name in this.attributes);
|
660 |
+
},
|
661 |
+
removeAttribute: function(name){
|
662 |
+
delete this.attributes[name];
|
663 |
+
},
|
664 |
+
getAttribute: function(name){
|
665 |
+
if (this.hasAttribute(name)) {
|
666 |
+
return this.attributes[name];
|
667 |
+
}
|
668 |
+
return '';
|
669 |
+
},
|
670 |
+
setAttribute: function(name, value){
|
671 |
+
this.attributes[name] = value;
|
672 |
+
},
|
673 |
+
|
674 |
+
remove: function() {
|
675 |
+
mejs.Utility.removeSwf(this.pluginElement.id);
|
676 |
+
}
|
677 |
+
};
|
678 |
+
|
679 |
+
// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
|
680 |
+
mejs.MediaPluginBridge = {
|
681 |
+
|
682 |
+
pluginMediaElements:{},
|
683 |
+
htmlMediaElements:{},
|
684 |
+
|
685 |
+
registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
|
686 |
+
this.pluginMediaElements[id] = pluginMediaElement;
|
687 |
+
this.htmlMediaElements[id] = htmlMediaElement;
|
688 |
+
},
|
689 |
+
|
690 |
+
// when Flash/Silverlight is ready, it calls out to this method
|
691 |
+
initPlugin: function (id) {
|
692 |
+
|
693 |
+
var pluginMediaElement = this.pluginMediaElements[id],
|
694 |
+
htmlMediaElement = this.htmlMediaElements[id];
|
695 |
+
|
696 |
+
if (pluginMediaElement) {
|
697 |
+
// find the javascript bridge
|
698 |
+
switch (pluginMediaElement.pluginType) {
|
699 |
+
case "flash":
|
700 |
+
pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
|
701 |
+
break;
|
702 |
+
case "silverlight":
|
703 |
+
pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
|
704 |
+
pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
|
705 |
+
break;
|
706 |
+
}
|
707 |
+
|
708 |
+
if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
|
709 |
+
pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
|
710 |
+
}
|
711 |
+
}
|
712 |
+
},
|
713 |
+
|
714 |
+
// receives events from Flash/Silverlight and sends them out as HTML5 media events
|
715 |
+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
716 |
+
fireEvent: function (id, eventName, values) {
|
717 |
+
|
718 |
+
var
|
719 |
+
e,
|
720 |
+
i,
|
721 |
+
bufferedTime,
|
722 |
+
pluginMediaElement = this.pluginMediaElements[id];
|
723 |
+
|
724 |
+
pluginMediaElement.ended = false;
|
725 |
+
pluginMediaElement.paused = true;
|
726 |
+
|
727 |
+
// fake event object to mimic real HTML media event.
|
728 |
+
e = {
|
729 |
+
type: eventName,
|
730 |
+
target: pluginMediaElement
|
731 |
+
};
|
732 |
+
|
733 |
+
// attach all values to element and event object
|
734 |
+
for (i in values) {
|
735 |
+
pluginMediaElement[i] = values[i];
|
736 |
+
e[i] = values[i];
|
737 |
+
}
|
738 |
+
|
739 |
+
// fake the newer W3C buffered TimeRange (loaded and total have been removed)
|
740 |
+
bufferedTime = values.bufferedTime || 0;
|
741 |
+
|
742 |
+
e.target.buffered = e.buffered = {
|
743 |
+
start: function(index) {
|
744 |
+
return 0;
|
745 |
+
},
|
746 |
+
end: function (index) {
|
747 |
+
return bufferedTime;
|
748 |
+
},
|
749 |
+
length: 1
|
750 |
+
};
|
751 |
+
|
752 |
+
pluginMediaElement.dispatchEvent(e.type, e);
|
753 |
+
}
|
754 |
+
};
|
755 |
+
|
756 |
+
/*
|
757 |
+
Default options
|
758 |
+
*/
|
759 |
+
mejs.MediaElementDefaults = {
|
760 |
+
// allows testing on HTML5, flash, silverlight
|
761 |
+
// auto: attempts to detect what the browser can do
|
762 |
+
// native: forces HTML5 playback
|
763 |
+
// shim: disallows HTML5, will attempt either Flash or Silverlight
|
764 |
+
// none: forces fallback view
|
765 |
+
mode: 'auto',
|
766 |
+
// remove or reorder to change plugin priority and availability
|
767 |
+
plugins: ['flash','silverlight','youtube','vimeo'],
|
768 |
+
// shows debug errors on screen
|
769 |
+
enablePluginDebug: false,
|
770 |
+
// overrides the type specified, useful for dynamic instantiation
|
771 |
+
type: '',
|
772 |
+
// path to Flash and Silverlight plugins
|
773 |
+
pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
|
774 |
+
// name of flash file
|
775 |
+
flashName: 'flashmediaelement.swf',
|
776 |
+
// turns on the smoothing filter in Flash
|
777 |
+
enablePluginSmoothing: false,
|
778 |
+
// name of silverlight file
|
779 |
+
silverlightName: 'silverlightmediaelement.xap',
|
780 |
+
// default if the <video width> is not specified
|
781 |
+
defaultVideoWidth: 480,
|
782 |
+
// default if the <video height> is not specified
|
783 |
+
defaultVideoHeight: 270,
|
784 |
+
// overrides <video width>
|
785 |
+
pluginWidth: -1,
|
786 |
+
// overrides <video height>
|
787 |
+
pluginHeight: -1,
|
788 |
+
// additional plugin variables in 'key=value' form
|
789 |
+
pluginVars: [],
|
790 |
+
// rate in milliseconds for Flash and Silverlight to fire the timeupdate event
|
791 |
+
// larger number is less accurate, but less strain on plugin->JavaScript bridge
|
792 |
+
timerRate: 250,
|
793 |
+
// initial volume for player
|
794 |
+
startVolume: 0.8,
|
795 |
+
success: function () { },
|
796 |
+
error: function () { }
|
797 |
+
};
|
798 |
+
|
799 |
+
/*
|
800 |
+
Determines if a browser supports the <video> or <audio> element
|
801 |
+
and returns either the native element or a Flash/Silverlight version that
|
802 |
+
mimics HTML5 MediaElement
|
803 |
+
*/
|
804 |
+
mejs.MediaElement = function (el, o) {
|
805 |
+
return mejs.HtmlMediaElementShim.create(el,o);
|
806 |
+
};
|
807 |
+
|
808 |
+
mejs.HtmlMediaElementShim = {
|
809 |
+
|
810 |
+
create: function(el, o) {
|
811 |
+
var
|
812 |
+
options = mejs.MediaElementDefaults,
|
813 |
+
htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el,
|
814 |
+
tagName = htmlMediaElement.tagName.toLowerCase(),
|
815 |
+
isMediaTag = (tagName === 'audio' || tagName === 'video'),
|
816 |
+
src = (isMediaTag) ? htmlMediaElement.getAttribute('src') : htmlMediaElement.getAttribute('href'),
|
817 |
+
poster = htmlMediaElement.getAttribute('poster'),
|
818 |
+
autoplay = htmlMediaElement.getAttribute('autoplay'),
|
819 |
+
preload = htmlMediaElement.getAttribute('preload'),
|
820 |
+
controls = htmlMediaElement.getAttribute('controls'),
|
821 |
+
playback,
|
822 |
+
prop;
|
823 |
+
|
824 |
+
// extend options
|
825 |
+
for (prop in o) {
|
826 |
+
options[prop] = o[prop];
|
827 |
+
}
|
828 |
+
|
829 |
+
// clean up attributes
|
830 |
+
src = (typeof src == 'undefined' || src === null || src == '') ? null : src;
|
831 |
+
poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
|
832 |
+
preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
|
833 |
+
autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
|
834 |
+
controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
|
835 |
+
|
836 |
+
// test for HTML5 and plugin capabilities
|
837 |
+
playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
|
838 |
+
playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '';
|
839 |
+
|
840 |
+
if (playback.method == 'native') {
|
841 |
+
// second fix for android
|
842 |
+
if (mejs.MediaFeatures.isBustedAndroid) {
|
843 |
+
htmlMediaElement.src = playback.url;
|
844 |
+
htmlMediaElement.addEventListener('click', function() {
|
845 |
+
htmlMediaElement.play();
|
846 |
+
}, false);
|
847 |
+
}
|
848 |
+
|
849 |
+
// add methods to native HTMLMediaElement
|
850 |
+
return this.updateNative(playback, options, autoplay, preload);
|
851 |
+
} else if (playback.method !== '') {
|
852 |
+
// create plugin to mimic HTMLMediaElement
|
853 |
+
|
854 |
+
return this.createPlugin( playback, options, poster, autoplay, preload, controls);
|
855 |
+
} else {
|
856 |
+
// boo, no HTML5, no Flash, no Silverlight.
|
857 |
+
this.createErrorMessage( playback, options, poster );
|
858 |
+
|
859 |
+
return this;
|
860 |
+
}
|
861 |
+
},
|
862 |
+
|
863 |
+
determinePlayback: function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) {
|
864 |
+
var
|
865 |
+
mediaFiles = [],
|
866 |
+
i,
|
867 |
+
j,
|
868 |
+
k,
|
869 |
+
l,
|
870 |
+
n,
|
871 |
+
type,
|
872 |
+
result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')},
|
873 |
+
pluginName,
|
874 |
+
pluginVersions,
|
875 |
+
pluginInfo,
|
876 |
+
dummy;
|
877 |
+
|
878 |
+
// STEP 1: Get URL and type from <video src> or <source src>
|
879 |
+
|
880 |
+
// supplied type overrides <video type> and <source type>
|
881 |
+
if (typeof options.type != 'undefined' && options.type !== '') {
|
882 |
+
|
883 |
+
// accept either string or array of types
|
884 |
+
if (typeof options.type == 'string') {
|
885 |
+
mediaFiles.push({type:options.type, url:src});
|
886 |
+
} else {
|
887 |
+
|
888 |
+
for (i=0; i<options.type.length; i++) {
|
889 |
+
mediaFiles.push({type:options.type[i], url:src});
|
890 |
+
}
|
891 |
+
}
|
892 |
+
|
893 |
+
// test for src attribute first
|
894 |
+
} else if (src !== null) {
|
895 |
+
type = this.formatType(src, htmlMediaElement.getAttribute('type'));
|
896 |
+
mediaFiles.push({type:type, url:src});
|
897 |
+
|
898 |
+
// then test for <source> elements
|
899 |
+
} else {
|
900 |
+
// test <source> types to see if they are usable
|
901 |
+
for (i = 0; i < htmlMediaElement.childNodes.length; i++) {
|
902 |
+
n = htmlMediaElement.childNodes[i];
|
903 |
+
if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
|
904 |
+
src = n.getAttribute('src');
|
905 |
+
type = this.formatType(src, n.getAttribute('type'));
|
906 |
+
mediaFiles.push({type:type, url:src});
|
907 |
+
}
|
908 |
+
}
|
909 |
+
}
|
910 |
+
|
911 |
+
// in the case of dynamicly created players
|
912 |
+
// check for audio types
|
913 |
+
if (!isMediaTag && mediaFiles.length > 0 && mediaFiles[0].url !== null && this.getTypeFromFile(mediaFiles[0].url).indexOf('audio') > -1) {
|
914 |
+
result.isVideo = false;
|
915 |
+
}
|
916 |
+
|
917 |
+
|
918 |
+
// STEP 2: Test for playback method
|
919 |
+
|
920 |
+
// special case for Android which sadly doesn't implement the canPlayType function (always returns '')
|
921 |
+
if (mejs.MediaFeatures.isBustedAndroid) {
|
922 |
+
htmlMediaElement.canPlayType = function(type) {
|
923 |
+
return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : '';
|
924 |
+
};
|
925 |
+
}
|
926 |
+
|
927 |
+
|
928 |
+
// test for native playback first
|
929 |
+
if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'native')) {
|
930 |
+
|
931 |
+
if (!isMediaTag) {
|
932 |
+
|
933 |
+
// create a real HTML5 Media Element
|
934 |
+
dummy = document.createElement( result.isVideo ? 'video' : 'audio');
|
935 |
+
htmlMediaElement.parentNode.insertBefore(dummy, htmlMediaElement);
|
936 |
+
htmlMediaElement.style.display = 'none';
|
937 |
+
|
938 |
+
// use this one from now on
|
939 |
+
result.htmlMediaElement = htmlMediaElement = dummy;
|
940 |
+
}
|
941 |
+
|
942 |
+
for (i=0; i<mediaFiles.length; i++) {
|
943 |
+
// normal check
|
944 |
+
if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
|
945 |
+
// special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
|
946 |
+
|| htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
|
947 |
+
result.method = 'native';
|
948 |
+
result.url = mediaFiles[i].url;
|
949 |
+
break;
|
950 |
+
}
|
951 |
+
}
|
952 |
+
|
953 |
+
if (result.method === 'native') {
|
954 |
+
if (result.url !== null) {
|
955 |
+
htmlMediaElement.src = result.url;
|
956 |
+
}
|
957 |
+
|
958 |
+
return result;
|
959 |
+
}
|
960 |
+
}
|
961 |
+
|
962 |
+
// if native playback didn't work, then test plugins
|
963 |
+
if (options.mode === 'auto' || options.mode === 'shim') {
|
964 |
+
for (i=0; i<mediaFiles.length; i++) {
|
965 |
+
type = mediaFiles[i].type;
|
966 |
+
|
967 |
+
// test all plugins in order of preference [silverlight, flash]
|
968 |
+
for (j=0; j<options.plugins.length; j++) {
|
969 |
+
|
970 |
+
pluginName = options.plugins[j];
|
971 |
+
|
972 |
+
// test version of plugin (for future features)
|
973 |
+
pluginVersions = mejs.plugins[pluginName];
|
974 |
+
|
975 |
+
for (k=0; k<pluginVersions.length; k++) {
|
976 |
+
pluginInfo = pluginVersions[k];
|
977 |
+
|
978 |
+
// test if user has the correct plugin version
|
979 |
+
|
980 |
+
// for youtube/vimeo
|
981 |
+
if (pluginInfo.version == null ||
|
982 |
+
|
983 |
+
mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
|
984 |
+
|
985 |
+
// test for plugin playback types
|
986 |
+
for (l=0; l<pluginInfo.types.length; l++) {
|
987 |
+
// find plugin that can play the type
|
988 |
+
if (type == pluginInfo.types[l]) {
|
989 |
+
result.method = pluginName;
|
990 |
+
result.url = mediaFiles[i].url;
|
991 |
+
return result;
|
992 |
+
}
|
993 |
+
}
|
994 |
+
}
|
995 |
+
}
|
996 |
+
}
|
997 |
+
}
|
998 |
+
}
|
999 |
+
|
1000 |
+
// what if there's nothing to play? just grab the first available
|
1001 |
+
if (result.method === '' && mediaFiles.length > 0) {
|
1002 |
+
result.url = mediaFiles[0].url;
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
return result;
|
1006 |
+
},
|
1007 |
+
|
1008 |
+
formatType: function(url, type) {
|
1009 |
+
var ext;
|
1010 |
+
|
1011 |
+
// if no type is supplied, fake it with the extension
|
1012 |
+
if (url && !type) {
|
1013 |
+
return this.getTypeFromFile(url);
|
1014 |
+
} else {
|
1015 |
+
// only return the mime part of the type in case the attribute contains the codec
|
1016 |
+
// see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
|
1017 |
+
// `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4`
|
1018 |
+
|
1019 |
+
if (type && ~type.indexOf(';')) {
|
1020 |
+
return type.substr(0, type.indexOf(';'));
|
1021 |
+
} else {
|
1022 |
+
return type;
|
1023 |
+
}
|
1024 |
+
}
|
1025 |
+
},
|
1026 |
+
|
1027 |
+
getTypeFromFile: function(url) {
|
1028 |
+
var ext = url.substring(url.lastIndexOf('.') + 1);
|
1029 |
+
return (/(mp4|m4v|ogg|ogv|webm|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + ext;
|
1030 |
+
},
|
1031 |
+
|
1032 |
+
createErrorMessage: function(playback, options, poster) {
|
1033 |
+
var
|
1034 |
+
htmlMediaElement = playback.htmlMediaElement,
|
1035 |
+
errorContainer = document.createElement('div');
|
1036 |
+
|
1037 |
+
errorContainer.className = 'me-cannotplay';
|
1038 |
+
|
1039 |
+
try {
|
1040 |
+
errorContainer.style.width = htmlMediaElement.width + 'px';
|
1041 |
+
errorContainer.style.height = htmlMediaElement.height + 'px';
|
1042 |
+
} catch (e) {}
|
1043 |
+
|
1044 |
+
errorContainer.innerHTML = (poster !== '') ?
|
1045 |
+
'<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
|
1046 |
+
'<a href="' + playback.url + '"><span>Download File</span></a>';
|
1047 |
+
|
1048 |
+
htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
|
1049 |
+
htmlMediaElement.style.display = 'none';
|
1050 |
+
|
1051 |
+
options.error(htmlMediaElement);
|
1052 |
+
},
|
1053 |
+
|
1054 |
+
createPlugin:function(playback, options, poster, autoplay, preload, controls) {
|
1055 |
+
var
|
1056 |
+
htmlMediaElement = playback.htmlMediaElement,
|
1057 |
+
width = 1,
|
1058 |
+
height = 1,
|
1059 |
+
pluginid = 'me_' + playback.method + '_' + (mejs.meIndex++),
|
1060 |
+
pluginMediaElement = new mejs.PluginMediaElement(pluginid, playback.method, playback.url),
|
1061 |
+
container = document.createElement('div'),
|
1062 |
+
specialIEContainer,
|
1063 |
+
node,
|
1064 |
+
initVars;
|
1065 |
+
|
1066 |
+
// copy tagName from html media element
|
1067 |
+
pluginMediaElement.tagName = htmlMediaElement.tagName
|
1068 |
+
|
1069 |
+
// copy attributes from html media element to plugin media element
|
1070 |
+
for (var i = 0; i < htmlMediaElement.attributes.length; i++) {
|
1071 |
+
var attribute = htmlMediaElement.attributes[i];
|
1072 |
+
if (attribute.specified == true) {
|
1073 |
+
pluginMediaElement.setAttribute(attribute.name, attribute.value);
|
1074 |
+
}
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
// check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
|
1078 |
+
node = htmlMediaElement.parentNode;
|
1079 |
+
while (node !== null && node.tagName.toLowerCase() != 'body') {
|
1080 |
+
if (node.parentNode.tagName.toLowerCase() == 'p') {
|
1081 |
+
node.parentNode.parentNode.insertBefore(node, node.parentNode);
|
1082 |
+
break;
|
1083 |
+
}
|
1084 |
+
node = node.parentNode;
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
if (playback.isVideo) {
|
1088 |
+
width = (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
|
1089 |
+
height = (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
|
1090 |
+
|
1091 |
+
// in case of '%' make sure it's encoded
|
1092 |
+
width = mejs.Utility.encodeUrl(width);
|
1093 |
+
height = mejs.Utility.encodeUrl(height);
|
1094 |
+
|
1095 |
+
} else {
|
1096 |
+
if (options.enablePluginDebug) {
|
1097 |
+
width = 320;
|
1098 |
+
height = 240;
|
1099 |
+
}
|
1100 |
+
}
|
1101 |
+
|
1102 |
+
// register plugin
|
1103 |
+
pluginMediaElement.success = options.success;
|
1104 |
+
mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
|
1105 |
+
|
1106 |
+
// add container (must be added to DOM before inserting HTML for IE)
|
1107 |
+
container.className = 'me-plugin';
|
1108 |
+
container.id = pluginid + '_container';
|
1109 |
+
|
1110 |
+
if (playback.isVideo) {
|
1111 |
+
htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
|
1112 |
+
} else {
|
1113 |
+
document.body.insertBefore(container, document.body.childNodes[0]);
|
1114 |
+
}
|
1115 |
+
|
1116 |
+
// flash/silverlight vars
|
1117 |
+
initVars = [
|
1118 |
+
'id=' + pluginid,
|
1119 |
+
'isvideo=' + ((playback.isVideo) ? "true" : "false"),
|
1120 |
+
'autoplay=' + ((autoplay) ? "true" : "false"),
|
1121 |
+
'preload=' + preload,
|
1122 |
+
'width=' + width,
|
1123 |
+
'startvolume=' + options.startVolume,
|
1124 |
+
'timerrate=' + options.timerRate,
|
1125 |
+
'height=' + height];
|
1126 |
+
|
1127 |
+
if (playback.url !== null) {
|
1128 |
+
if (playback.method == 'flash') {
|
1129 |
+
initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
|
1130 |
+
} else {
|
1131 |
+
initVars.push('file=' + playback.url);
|
1132 |
+
}
|
1133 |
+
}
|
1134 |
+
if (options.enablePluginDebug) {
|
1135 |
+
initVars.push('debug=true');
|
1136 |
+
}
|
1137 |
+
if (options.enablePluginSmoothing) {
|
1138 |
+
initVars.push('smoothing=true');
|
1139 |
+
}
|
1140 |
+
if (controls) {
|
1141 |
+
initVars.push('controls=true'); // shows controls in the plugin if desired
|
1142 |
+
}
|
1143 |
+
if (options.pluginVars) {
|
1144 |
+
initVars = initVars.concat(options.pluginVars);
|
1145 |
+
}
|
1146 |
+
|
1147 |
+
switch (playback.method) {
|
1148 |
+
case 'silverlight':
|
1149 |
+
container.innerHTML =
|
1150 |
+
'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '">' +
|
1151 |
+
'<param name="initParams" value="' + initVars.join(',') + '" />' +
|
1152 |
+
'<param name="windowless" value="true" />' +
|
1153 |
+
'<param name="background" value="black" />' +
|
1154 |
+
'<param name="minRuntimeVersion" value="3.0.0.0" />' +
|
1155 |
+
'<param name="autoUpgrade" value="true" />' +
|
1156 |
+
'<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' +
|
1157 |
+
'</object>';
|
1158 |
+
break;
|
1159 |
+
|
1160 |
+
case 'flash':
|
1161 |
+
|
1162 |
+
if (mejs.MediaFeatures.isIE) {
|
1163 |
+
specialIEContainer = document.createElement('div');
|
1164 |
+
container.appendChild(specialIEContainer);
|
1165 |
+
specialIEContainer.outerHTML =
|
1166 |
+
'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
|
1167 |
+
'id="' + pluginid + '" width="' + width + '" height="' + height + '">' +
|
1168 |
+
'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
|
1169 |
+
'<param name="flashvars" value="' + initVars.join('&') + '" />' +
|
1170 |
+
'<param name="quality" value="high" />' +
|
1171 |
+
'<param name="bgcolor" value="#000000" />' +
|
1172 |
+
'<param name="wmode" value="transparent" />' +
|
1173 |
+
'<param name="allowScriptAccess" value="always" />' +
|
1174 |
+
'<param name="allowFullScreen" value="true" />' +
|
1175 |
+
'</object>';
|
1176 |
+
|
1177 |
+
} else {
|
1178 |
+
|
1179 |
+
container.innerHTML =
|
1180 |
+
'<embed id="' + pluginid + '" name="' + pluginid + '" ' +
|
1181 |
+
'play="true" ' +
|
1182 |
+
'loop="false" ' +
|
1183 |
+
'quality="high" ' +
|
1184 |
+
'bgcolor="#000000" ' +
|
1185 |
+
'wmode="transparent" ' +
|
1186 |
+
'allowScriptAccess="always" ' +
|
1187 |
+
'allowFullScreen="true" ' +
|
1188 |
+
'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' +
|
1189 |
+
'src="' + options.pluginPath + options.flashName + '" ' +
|
1190 |
+
'flashvars="' + initVars.join('&') + '" ' +
|
1191 |
+
'width="' + width + '" ' +
|
1192 |
+
'height="' + height + '"></embed>';
|
1193 |
+
}
|
1194 |
+
break;
|
1195 |
+
|
1196 |
+
case 'youtube':
|
1197 |
+
|
1198 |
+
|
1199 |
+
var
|
1200 |
+
videoId = playback.url.substr(playback.url.lastIndexOf('=')+1);
|
1201 |
+
youtubeSettings = {
|
1202 |
+
container: container,
|
1203 |
+
containerId: container.id,
|
1204 |
+
pluginMediaElement: pluginMediaElement,
|
1205 |
+
pluginId: pluginid,
|
1206 |
+
videoId: videoId,
|
1207 |
+
height: height,
|
1208 |
+
width: width
|
1209 |
+
};
|
1210 |
+
|
1211 |
+
if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) {
|
1212 |
+
mejs.YouTubeApi.createFlash(youtubeSettings);
|
1213 |
+
} else {
|
1214 |
+
mejs.YouTubeApi.enqueueIframe(youtubeSettings);
|
1215 |
+
}
|
1216 |
+
|
1217 |
+
break;
|
1218 |
+
|
1219 |
+
// DEMO Code. Does NOT work.
|
1220 |
+
case 'vimeo':
|
1221 |
+
console.log('vimeoid');
|
1222 |
+
|
1223 |
+
pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
|
1224 |
+
|
1225 |
+
container.innerHTML =
|
1226 |
+
'<object width="' + width + '" height="' + height + '">' +
|
1227 |
+
'<param name="allowfullscreen" value="true" />' +
|
1228 |
+
'<param name="allowscriptaccess" value="always" />' +
|
1229 |
+
'<param name="flashvars" value="api=1" />' +
|
1230 |
+
'<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" />' +
|
1231 |
+
'<embed src="//vimeo.com/moogaloop.swf?api=1&clip_id=' + pluginMediaElement.vimeoid + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '"></embed>' +
|
1232 |
+
'</object>';
|
1233 |
+
|
1234 |
+
break;
|
1235 |
+
}
|
1236 |
+
// hide original element
|
1237 |
+
htmlMediaElement.style.display = 'none';
|
1238 |
+
|
1239 |
+
// FYI: options.success will be fired by the MediaPluginBridge
|
1240 |
+
|
1241 |
+
return pluginMediaElement;
|
1242 |
+
},
|
1243 |
+
|
1244 |
+
updateNative: function(playback, options, autoplay, preload) {
|
1245 |
+
|
1246 |
+
var htmlMediaElement = playback.htmlMediaElement,
|
1247 |
+
m;
|
1248 |
+
|
1249 |
+
|
1250 |
+
// add methods to video object to bring it into parity with Flash Object
|
1251 |
+
for (m in mejs.HtmlMediaElement) {
|
1252 |
+
htmlMediaElement[m] = mejs.HtmlMediaElement[m];
|
1253 |
+
}
|
1254 |
+
|
1255 |
+
/*
|
1256 |
+
Chrome now supports preload="none"
|
1257 |
+
if (mejs.MediaFeatures.isChrome) {
|
1258 |
+
|
1259 |
+
// special case to enforce preload attribute (Chrome doesn't respect this)
|
1260 |
+
if (preload === 'none' && !autoplay) {
|
1261 |
+
|
1262 |
+
// forces the browser to stop loading (note: fails in IE9)
|
1263 |
+
htmlMediaElement.src = '';
|
1264 |
+
htmlMediaElement.load();
|
1265 |
+
htmlMediaElement.canceledPreload = true;
|
1266 |
+
|
1267 |
+
htmlMediaElement.addEventListener('play',function() {
|
1268 |
+
if (htmlMediaElement.canceledPreload) {
|
1269 |
+
htmlMediaElement.src = playback.url;
|
1270 |
+
htmlMediaElement.load();
|
1271 |
+
htmlMediaElement.play();
|
1272 |
+
htmlMediaElement.canceledPreload = false;
|
1273 |
+
}
|
1274 |
+
}, false);
|
1275 |
+
// for some reason Chrome forgets how to autoplay sometimes.
|
1276 |
+
} else if (autoplay) {
|
1277 |
+
htmlMediaElement.load();
|
1278 |
+
htmlMediaElement.play();
|
1279 |
+
}
|
1280 |
+
}
|
1281 |
+
*/
|
1282 |
+
|
1283 |
+
// fire success code
|
1284 |
+
options.success(htmlMediaElement, htmlMediaElement);
|
1285 |
+
|
1286 |
+
return htmlMediaElement;
|
1287 |
+
}
|
1288 |
+
};
|
1289 |
+
|
1290 |
+
/*
|
1291 |
+
- test on IE (object vs. embed)
|
1292 |
+
- determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE)
|
1293 |
+
- fullscreen?
|
1294 |
+
*/
|
1295 |
+
|
1296 |
+
// YouTube Flash and Iframe API
|
1297 |
+
mejs.YouTubeApi = {
|
1298 |
+
isIframeStarted: false,
|
1299 |
+
isIframeLoaded: false,
|
1300 |
+
loadIframeApi: function() {
|
1301 |
+
if (!this.isIframeStarted) {
|
1302 |
+
var tag = document.createElement('script');
|
1303 |
+
tag.src = "http://www.youtube.com/player_api";
|
1304 |
+
var firstScriptTag = document.getElementsByTagName('script')[0];
|
1305 |
+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
1306 |
+
this.isIframeStarted = true;
|
1307 |
+
}
|
1308 |
+
},
|
1309 |
+
iframeQueue: [],
|
1310 |
+
enqueueIframe: function(yt) {
|
1311 |
+
|
1312 |
+
if (this.isLoaded) {
|
1313 |
+
this.createIframe(yt);
|
1314 |
+
} else {
|
1315 |
+
this.loadIframeApi();
|
1316 |
+
this.iframeQueue.push(yt);
|
1317 |
+
}
|
1318 |
+
},
|
1319 |
+
createIframe: function(settings) {
|
1320 |
+
|
1321 |
+
var
|
1322 |
+
pluginMediaElement = settings.pluginMediaElement,
|
1323 |
+
player = new YT.Player(settings.containerId, {
|
1324 |
+
height: settings.height,
|
1325 |
+
width: settings.width,
|
1326 |
+
videoId: settings.videoId,
|
1327 |
+
playerVars: {controls:0},
|
1328 |
+
events: {
|
1329 |
+
'onReady': function() {
|
1330 |
+
|
1331 |
+
// hook up iframe object to MEjs
|
1332 |
+
settings.pluginMediaElement.pluginApi = player;
|
1333 |
+
|
1334 |
+
// init mejs
|
1335 |
+
mejs.MediaPluginBridge.initPlugin(settings.pluginId);
|
1336 |
+
|
1337 |
+
// create timer
|
1338 |
+
setInterval(function() {
|
1339 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
|
1340 |
+
}, 250);
|
1341 |
+
},
|
1342 |
+
'onStateChange': function(e) {
|
1343 |
+
|
1344 |
+
mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement);
|
1345 |
+
|
1346 |
+
}
|
1347 |
+
}
|
1348 |
+
});
|
1349 |
+
},
|
1350 |
+
|
1351 |
+
createEvent: function (player, pluginMediaElement, eventName) {
|
1352 |
+
var obj = {
|
1353 |
+
type: eventName,
|
1354 |
+
target: pluginMediaElement
|
1355 |
+
};
|
1356 |
+
|
1357 |
+
if (player && player.getDuration) {
|
1358 |
+
|
1359 |
+
// time
|
1360 |
+
pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime();
|
1361 |
+
pluginMediaElement.duration = obj.duration = player.getDuration();
|
1362 |
+
|
1363 |
+
// state
|
1364 |
+
obj.paused = pluginMediaElement.paused;
|
1365 |
+
obj.ended = pluginMediaElement.ended;
|
1366 |
+
|
1367 |
+
// sound
|
1368 |
+
obj.muted = player.isMuted();
|
1369 |
+
obj.volume = player.getVolume() / 100;
|
1370 |
+
|
1371 |
+
// progress
|
1372 |
+
obj.bytesTotal = player.getVideoBytesTotal();
|
1373 |
+
obj.bufferedBytes = player.getVideoBytesLoaded();
|
1374 |
+
|
1375 |
+
// fake the W3C buffered TimeRange
|
1376 |
+
var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration;
|
1377 |
+
|
1378 |
+
obj.target.buffered = obj.buffered = {
|
1379 |
+
start: function(index) {
|
1380 |
+
return 0;
|
1381 |
+
},
|
1382 |
+
end: function (index) {
|
1383 |
+
return bufferedTime;
|
1384 |
+
},
|
1385 |
+
length: 1
|
1386 |
+
};
|
1387 |
+
|
1388 |
+
}
|
1389 |
+
|
1390 |
+
// send event up the chain
|
1391 |
+
pluginMediaElement.dispatchEvent(obj.type, obj);
|
1392 |
+
},
|
1393 |
+
|
1394 |
+
iFrameReady: function() {
|
1395 |
+
|
1396 |
+
this.isLoaded = true;
|
1397 |
+
this.isIframeLoaded = true;
|
1398 |
+
|
1399 |
+
while (this.iframeQueue.length > 0) {
|
1400 |
+
var settings = this.iframeQueue.pop();
|
1401 |
+
this.createIframe(settings);
|
1402 |
+
}
|
1403 |
+
},
|
1404 |
+
|
1405 |
+
// FLASH!
|
1406 |
+
flashPlayers: {},
|
1407 |
+
createFlash: function(settings) {
|
1408 |
+
|
1409 |
+
this.flashPlayers[settings.pluginId] = settings;
|
1410 |
+
|
1411 |
+
/*
|
1412 |
+
settings.container.innerHTML =
|
1413 |
+
'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0" ' +
|
1414 |
+
'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; ">' +
|
1415 |
+
'<param name="allowScriptAccess" value="always">' +
|
1416 |
+
'<param name="wmode" value="transparent">' +
|
1417 |
+
'</object>';
|
1418 |
+
*/
|
1419 |
+
|
1420 |
+
var specialIEContainer,
|
1421 |
+
youtubeUrl = 'http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0';
|
1422 |
+
|
1423 |
+
if (mejs.MediaFeatures.isIE) {
|
1424 |
+
|
1425 |
+
specialIEContainer = document.createElement('div');
|
1426 |
+
settings.container.appendChild(specialIEContainer);
|
1427 |
+
specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
|
1428 |
+
'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '">' +
|
1429 |
+
'<param name="movie" value="' + youtubeUrl + '" />' +
|
1430 |
+
'<param name="wmode" value="transparent" />' +
|
1431 |
+
'<param name="allowScriptAccess" value="always" />' +
|
1432 |
+
'<param name="allowFullScreen" value="true" />' +
|
1433 |
+
'</object>';
|
1434 |
+
} else {
|
1435 |
+
settings.container.innerHTML =
|
1436 |
+
'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' +
|
1437 |
+
'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; ">' +
|
1438 |
+
'<param name="allowScriptAccess" value="always">' +
|
1439 |
+
'<param name="wmode" value="transparent">' +
|
1440 |
+
'</object>';
|
1441 |
+
}
|
1442 |
+
|
1443 |
+
},
|
1444 |
+
|
1445 |
+
flashReady: function(id) {
|
1446 |
+
var
|
1447 |
+
settings = this.flashPlayers[id],
|
1448 |
+
player = document.getElementById(id),
|
1449 |
+
pluginMediaElement = settings.pluginMediaElement;
|
1450 |
+
|
1451 |
+
// hook up and return to MediaELementPlayer.success
|
1452 |
+
pluginMediaElement.pluginApi =
|
1453 |
+
pluginMediaElement.pluginElement = player;
|
1454 |
+
mejs.MediaPluginBridge.initPlugin(id);
|
1455 |
+
|
1456 |
+
// load the youtube video
|
1457 |
+
player.cueVideoById(settings.videoId);
|
1458 |
+
|
1459 |
+
var callbackName = settings.containerId + '_callback'
|
1460 |
+
|
1461 |
+
window[callbackName] = function(e) {
|
1462 |
+
mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement);
|
1463 |
+
}
|
1464 |
+
|
1465 |
+
player.addEventListener('onStateChange', callbackName);
|
1466 |
+
|
1467 |
+
setInterval(function() {
|
1468 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
|
1469 |
+
}, 250);
|
1470 |
+
},
|
1471 |
+
|
1472 |
+
handleStateChange: function(youTubeState, player, pluginMediaElement) {
|
1473 |
+
switch (youTubeState) {
|
1474 |
+
case -1: // not started
|
1475 |
+
pluginMediaElement.paused = true;
|
1476 |
+
pluginMediaElement.ended = true;
|
1477 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata');
|
1478 |
+
//createYouTubeEvent(player, pluginMediaElement, 'loadeddata');
|
1479 |
+
break;
|
1480 |
+
case 0:
|
1481 |
+
pluginMediaElement.paused = false;
|
1482 |
+
pluginMediaElement.ended = true;
|
1483 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended');
|
1484 |
+
break;
|
1485 |
+
case 1:
|
1486 |
+
pluginMediaElement.paused = false;
|
1487 |
+
pluginMediaElement.ended = false;
|
1488 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play');
|
1489 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing');
|
1490 |
+
break;
|
1491 |
+
case 2:
|
1492 |
+
pluginMediaElement.paused = true;
|
1493 |
+
pluginMediaElement.ended = false;
|
1494 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause');
|
1495 |
+
break;
|
1496 |
+
case 3: // buffering
|
1497 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress');
|
1498 |
+
break;
|
1499 |
+
case 5:
|
1500 |
+
// cued?
|
1501 |
+
break;
|
1502 |
+
|
1503 |
+
}
|
1504 |
+
|
1505 |
+
}
|
1506 |
+
}
|
1507 |
+
// IFRAME
|
1508 |
+
function onYouTubePlayerAPIReady() {
|
1509 |
+
mejs.YouTubeApi.iFrameReady();
|
1510 |
+
}
|
1511 |
+
// FLASH
|
1512 |
+
function onYouTubePlayerReady(id) {
|
1513 |
+
mejs.YouTubeApi.flashReady(id);
|
1514 |
+
}
|
1515 |
+
|
1516 |
+
window.mejs = mejs;
|
1517 |
+
window.MediaElement = mejs.MediaElement;
|
1518 |
+
|
1519 |
+
/*!
|
1520 |
+
* MediaElementPlayer
|
1521 |
+
* http://mediaelementjs.com/
|
1522 |
+
*
|
1523 |
+
* Creates a controller bar for HTML5 <video> add <audio> tags
|
1524 |
+
* using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper)
|
1525 |
+
*
|
1526 |
+
* Copyright 2010-2012, John Dyer (http://j.hn/)
|
1527 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
1528 |
+
*
|
1529 |
+
*/
|
1530 |
+
if (typeof jQuery != 'undefined') {
|
1531 |
+
mejs.$ = jQuery;
|
1532 |
+
} else if (typeof ender != 'undefined') {
|
1533 |
+
mejs.$ = ender;
|
1534 |
+
}
|
1535 |
+
(function ($) {
|
1536 |
+
|
1537 |
+
// default player values
|
1538 |
+
mejs.MepDefaults = {
|
1539 |
+
// url to poster (to fix iOS 3.x)
|
1540 |
+
poster: '',
|
1541 |
+
// default if the <video width> is not specified
|
1542 |
+
defaultVideoWidth: 480,
|
1543 |
+
// default if the <video height> is not specified
|
1544 |
+
defaultVideoHeight: 270,
|
1545 |
+
// if set, overrides <video width>
|
1546 |
+
videoWidth: -1,
|
1547 |
+
// if set, overrides <video height>
|
1548 |
+
videoHeight: -1,
|
1549 |
+
// default if the user doesn't specify
|
1550 |
+
defaultAudioWidth: 400,
|
1551 |
+
// default if the user doesn't specify
|
1552 |
+
defaultAudioHeight: 30,
|
1553 |
+
// width of audio player
|
1554 |
+
audioWidth: -1,
|
1555 |
+
// height of audio player
|
1556 |
+
audioHeight: -1,
|
1557 |
+
// initial volume when the player starts (overrided by user cookie)
|
1558 |
+
startVolume: 0.8,
|
1559 |
+
// useful for <audio> player loops
|
1560 |
+
loop: false,
|
1561 |
+
// resize to media dimensions
|
1562 |
+
enableAutosize: true,
|
1563 |
+
// forces the hour marker (##:00:00)
|
1564 |
+
alwaysShowHours: false,
|
1565 |
+
|
1566 |
+
// show framecount in timecode (##:00:00:00)
|
1567 |
+
showTimecodeFrameCount: false,
|
1568 |
+
// used when showTimecodeFrameCount is set to true
|
1569 |
+
framesPerSecond: 25,
|
1570 |
+
|
1571 |
+
// automatically calculate the width of the progress bar based on the sizes of other elements
|
1572 |
+
autosizeProgress : true,
|
1573 |
+
// Hide controls when playing and mouse is not over the video
|
1574 |
+
alwaysShowControls: false,
|
1575 |
+
// force iPad's native controls
|
1576 |
+
iPadUseNativeControls: false,
|
1577 |
+
// force iPhone's native controls
|
1578 |
+
iPhoneUseNativeControls: false,
|
1579 |
+
// force Android's native controls
|
1580 |
+
AndroidUseNativeControls: false,
|
1581 |
+
// features to show
|
1582 |
+
features: ['playpause','current','progress','duration','tracks','volume','fullscreen'],
|
1583 |
+
// only for dynamic
|
1584 |
+
isVideo: true,
|
1585 |
+
|
1586 |
+
// turns keyboard support on and off for this instance
|
1587 |
+
enableKeyboard: true,
|
1588 |
+
|
1589 |
+
// whenthis player starts, it will pause other players
|
1590 |
+
pauseOtherPlayers: true,
|
1591 |
+
|
1592 |
+
// array of keyboard actions such as play pause
|
1593 |
+
keyActions: [
|
1594 |
+
{
|
1595 |
+
keys: [
|
1596 |
+
32, // SPACE
|
1597 |
+
179 // GOOGLE play/pause button
|
1598 |
+
],
|
1599 |
+
action: function(player, media) {
|
1600 |
+
if (media.paused || media.ended) {
|
1601 |
+
media.play();
|
1602 |
+
} else {
|
1603 |
+
media.pause();
|
1604 |
+
}
|
1605 |
+
}
|
1606 |
+
},
|
1607 |
+
{
|
1608 |
+
keys: [38], // UP
|
1609 |
+
action: function(player, media) {
|
1610 |
+
var newVolume = Math.min(media.volume + 0.1, 1);
|
1611 |
+
media.setVolume(newVolume);
|
1612 |
+
}
|
1613 |
+
},
|
1614 |
+
{
|
1615 |
+
keys: [40], // DOWN
|
1616 |
+
action: function(player, media) {
|
1617 |
+
var newVolume = Math.max(media.volume - 0.1, 0);
|
1618 |
+
media.setVolume(newVolume);
|
1619 |
+
}
|
1620 |
+
},
|
1621 |
+
{
|
1622 |
+
keys: [
|
1623 |
+
37, // LEFT
|
1624 |
+
227 // Google TV rewind
|
1625 |
+
],
|
1626 |
+
action: function(player, media) {
|
1627 |
+
if (!isNaN(media.duration) && media.duration > 0) {
|
1628 |
+
if (player.isVideo) {
|
1629 |
+
player.showControls();
|
1630 |
+
player.startControlsTimer();
|
1631 |
+
}
|
1632 |
+
|
1633 |
+
// 5%
|
1634 |
+
var newTime = Math.max(media.currentTime - (media.duration * 0.05), 0);
|
1635 |
+
media.setCurrentTime(newTime);
|
1636 |
+
}
|
1637 |
+
}
|
1638 |
+
},
|
1639 |
+
{
|
1640 |
+
keys: [
|
1641 |
+
39, // RIGHT
|
1642 |
+
228 // Google TV forward
|
1643 |
+
],
|
1644 |
+
action: function(player, media) {
|
1645 |
+
if (!isNaN(media.duration) && media.duration > 0) {
|
1646 |
+
if (player.isVideo) {
|
1647 |
+
player.showControls();
|
1648 |
+
player.startControlsTimer();
|
1649 |
+
}
|
1650 |
+
|
1651 |
+
// 5%
|
1652 |
+
var newTime = Math.min(media.currentTime + (media.duration * 0.05), media.duration);
|
1653 |
+
media.setCurrentTime(newTime);
|
1654 |
+
}
|
1655 |
+
}
|
1656 |
+
},
|
1657 |
+
{
|
1658 |
+
keys: [70], // f
|
1659 |
+
action: function(player, media) {
|
1660 |
+
if (typeof player.enterFullScreen != 'undefined') {
|
1661 |
+
if (player.isFullScreen) {
|
1662 |
+
player.exitFullScreen();
|
1663 |
+
} else {
|
1664 |
+
player.enterFullScreen();
|
1665 |
+
}
|
1666 |
+
}
|
1667 |
+
}
|
1668 |
+
}
|
1669 |
+
]
|
1670 |
+
};
|
1671 |
+
|
1672 |
+
mejs.mepIndex = 0;
|
1673 |
+
|
1674 |
+
mejs.players = [];
|
1675 |
+
|
1676 |
+
// wraps a MediaElement object in player controls
|
1677 |
+
mejs.MediaElementPlayer = function(node, o) {
|
1678 |
+
// enforce object, even without "new" (via John Resig)
|
1679 |
+
if ( !(this instanceof mejs.MediaElementPlayer) ) {
|
1680 |
+
return new mejs.MediaElementPlayer(node, o);
|
1681 |
+
}
|
1682 |
+
|
1683 |
+
var t = this;
|
1684 |
+
|
1685 |
+
// these will be reset after the MediaElement.success fires
|
1686 |
+
t.$media = t.$node = $(node);
|
1687 |
+
t.node = t.media = t.$media[0];
|
1688 |
+
|
1689 |
+
// check for existing player
|
1690 |
+
if (typeof t.node.player != 'undefined') {
|
1691 |
+
return t.node.player;
|
1692 |
+
} else {
|
1693 |
+
// attach player to DOM node for reference
|
1694 |
+
t.node.player = t;
|
1695 |
+
}
|
1696 |
+
|
1697 |
+
|
1698 |
+
// try to get options from data-mejsoptions
|
1699 |
+
if (typeof o == 'undefined') {
|
1700 |
+
o = t.$node.data('mejsoptions');
|
1701 |
+
}
|
1702 |
+
|
1703 |
+
// extend default options
|
1704 |
+
t.options = $.extend({},mejs.MepDefaults,o);
|
1705 |
+
|
1706 |
+
// add to player array (for focus events)
|
1707 |
+
mejs.players.push(t);
|
1708 |
+
|
1709 |
+
// start up
|
1710 |
+
t.init();
|
1711 |
+
|
1712 |
+
return t;
|
1713 |
+
};
|
1714 |
+
|
1715 |
+
// actual player
|
1716 |
+
mejs.MediaElementPlayer.prototype = {
|
1717 |
+
|
1718 |
+
hasFocus: false,
|
1719 |
+
|
1720 |
+
controlsAreVisible: true,
|
1721 |
+
|
1722 |
+
init: function() {
|
1723 |
+
|
1724 |
+
var
|
1725 |
+
t = this,
|
1726 |
+
mf = mejs.MediaFeatures,
|
1727 |
+
// options for MediaElement (shim)
|
1728 |
+
meOptions = $.extend(true, {}, t.options, {
|
1729 |
+
success: function(media, domNode) { t.meReady(media, domNode); },
|
1730 |
+
error: function(e) { t.handleError(e);}
|
1731 |
+
}),
|
1732 |
+
tagName = t.media.tagName.toLowerCase();
|
1733 |
+
|
1734 |
+
t.isDynamic = (tagName !== 'audio' && tagName !== 'video');
|
1735 |
+
|
1736 |
+
if (t.isDynamic) {
|
1737 |
+
// get video from src or href?
|
1738 |
+
t.isVideo = t.options.isVideo;
|
1739 |
+
} else {
|
1740 |
+
t.isVideo = (tagName !== 'audio' && t.options.isVideo);
|
1741 |
+
}
|
1742 |
+
|
1743 |
+
// use native controls in iPad, iPhone, and Android
|
1744 |
+
if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) {
|
1745 |
+
|
1746 |
+
// add controls and stop
|
1747 |
+
t.$media.attr('controls', 'controls');
|
1748 |
+
|
1749 |
+
// attempt to fix iOS 3 bug
|
1750 |
+
//t.$media.removeAttr('poster');
|
1751 |
+
// no Issue found on iOS3 -ttroxell
|
1752 |
+
|
1753 |
+
// override Apple's autoplay override for iPads
|
1754 |
+
if (mf.isiPad && t.media.getAttribute('autoplay') !== null) {
|
1755 |
+
t.media.load();
|
1756 |
+
t.media.play();
|
1757 |
+
}
|
1758 |
+
|
1759 |
+
} else if (mf.isAndroid && t.AndroidUseNativeControls) {
|
1760 |
+
|
1761 |
+
// leave default player
|
1762 |
+
|
1763 |
+
} else {
|
1764 |
+
|
1765 |
+
// DESKTOP: use MediaElementPlayer controls
|
1766 |
+
|
1767 |
+
// remove native controls
|
1768 |
+
t.$media.removeAttr('controls');
|
1769 |
+
|
1770 |
+
// unique ID
|
1771 |
+
t.id = 'mep_' + mejs.mepIndex++;
|
1772 |
+
|
1773 |
+
// build container
|
1774 |
+
t.container =
|
1775 |
+
$('<div id="' + t.id + '" class="mejs-container">'+
|
1776 |
+
'<div class="mejs-inner">'+
|
1777 |
+
'<div class="mejs-mediaelement"></div>'+
|
1778 |
+
'<div class="mejs-layers"></div>'+
|
1779 |
+
'<div class="mejs-controls"></div>'+
|
1780 |
+
'<div class="mejs-clear"></div>'+
|
1781 |
+
'</div>' +
|
1782 |
+
'</div>')
|
1783 |
+
.addClass(t.$media[0].className)
|
1784 |
+
.insertBefore(t.$media);
|
1785 |
+
|
1786 |
+
// add classes for user and content
|
1787 |
+
t.container.addClass(
|
1788 |
+
(mf.isAndroid ? 'mejs-android ' : '') +
|
1789 |
+
(mf.isiOS ? 'mejs-ios ' : '') +
|
1790 |
+
(mf.isiPad ? 'mejs-ipad ' : '') +
|
1791 |
+
(mf.isiPhone ? 'mejs-iphone ' : '') +
|
1792 |
+
(t.isVideo ? 'mejs-video ' : 'mejs-audio ')
|
1793 |
+
);
|
1794 |
+
|
1795 |
+
|
1796 |
+
// move the <video/video> tag into the right spot
|
1797 |
+
if (mf.isiOS) {
|
1798 |
+
|
1799 |
+
// sadly, you can't move nodes in iOS, so we have to destroy and recreate it!
|
1800 |
+
var $newMedia = t.$media.clone();
|
1801 |
+
|
1802 |
+
t.container.find('.mejs-mediaelement').append($newMedia);
|
1803 |
+
|
1804 |
+
t.$media.remove();
|
1805 |
+
t.$node = t.$media = $newMedia;
|
1806 |
+
t.node = t.media = $newMedia[0]
|
1807 |
+
|
1808 |
+
} else {
|
1809 |
+
|
1810 |
+
// normal way of moving it into place (doesn't work on iOS)
|
1811 |
+
t.container.find('.mejs-mediaelement').append(t.$media);
|
1812 |
+
}
|
1813 |
+
|
1814 |
+
// find parts
|
1815 |
+
t.controls = t.container.find('.mejs-controls');
|
1816 |
+
t.layers = t.container.find('.mejs-layers');
|
1817 |
+
|
1818 |
+
// determine the size
|
1819 |
+
|
1820 |
+
/* size priority:
|
1821 |
+
(1) videoWidth (forced),
|
1822 |
+
(2) style="width;height;"
|
1823 |
+
(3) width attribute,
|
1824 |
+
(4) defaultVideoWidth (for unspecified cases)
|
1825 |
+
*/
|
1826 |
+
|
1827 |
+
var capsTagName = tagName.substring(0,1).toUpperCase() + tagName.substring(1);
|
1828 |
+
|
1829 |
+
if (t.options[tagName + 'Width'] > 0 || t.options[tagName + 'Width'].toString().indexOf('%') > -1) {
|
1830 |
+
t.width = t.options[tagName + 'Width'];
|
1831 |
+
} else if (t.media.style.width !== '' && t.media.style.width !== null) {
|
1832 |
+
t.width = t.media.style.width;
|
1833 |
+
} else if (t.media.getAttribute('width') !== null) {
|
1834 |
+
t.width = t.$media.attr('width');
|
1835 |
+
} else {
|
1836 |
+
t.width = t.options['default' + capsTagName + 'Width'];
|
1837 |
+
}
|
1838 |
+
|
1839 |
+
if (t.options[tagName + 'Height'] > 0 || t.options[tagName + 'Height'].toString().indexOf('%') > -1) {
|
1840 |
+
t.height = t.options[tagName + 'Height'];
|
1841 |
+
} else if (t.media.style.height !== '' && t.media.style.height !== null) {
|
1842 |
+
t.height = t.media.style.height;
|
1843 |
+
} else if (t.$media[0].getAttribute('height') !== null) {
|
1844 |
+
t.height = t.$media.attr('height');
|
1845 |
+
} else {
|
1846 |
+
t.height = t.options['default' + capsTagName + 'Height'];
|
1847 |
+
}
|
1848 |
+
|
1849 |
+
// set the size, while we wait for the plugins to load below
|
1850 |
+
t.setPlayerSize(t.width, t.height);
|
1851 |
+
|
1852 |
+
// create MediaElementShim
|
1853 |
+
meOptions.pluginWidth = t.height;
|
1854 |
+
meOptions.pluginHeight = t.width;
|
1855 |
+
}
|
1856 |
+
|
1857 |
+
|
1858 |
+
|
1859 |
+
// create MediaElement shim
|
1860 |
+
mejs.MediaElement(t.$media[0], meOptions);
|
1861 |
+
},
|
1862 |
+
|
1863 |
+
showControls: function(doAnimation) {
|
1864 |
+
var t = this;
|
1865 |
+
|
1866 |
+
doAnimation = typeof doAnimation == 'undefined' || doAnimation;
|
1867 |
+
|
1868 |
+
if (t.controlsAreVisible)
|
1869 |
+
return;
|
1870 |
+
|
1871 |
+
if (doAnimation) {
|
1872 |
+
t.controls
|
1873 |
+
.css('visibility','visible')
|
1874 |
+
.stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
|
1875 |
+
|
1876 |
+
// any additional controls people might add and want to hide
|
1877 |
+
t.container.find('.mejs-control')
|
1878 |
+
.css('visibility','visible')
|
1879 |
+
.stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
|
1880 |
+
|
1881 |
+
} else {
|
1882 |
+
t.controls
|
1883 |
+
.css('visibility','visible')
|
1884 |
+
.css('display','block');
|
1885 |
+
|
1886 |
+
// any additional controls people might add and want to hide
|
1887 |
+
t.container.find('.mejs-control')
|
1888 |
+
.css('visibility','visible')
|
1889 |
+
.css('display','block');
|
1890 |
+
|
1891 |
+
t.controlsAreVisible = true;
|
1892 |
+
}
|
1893 |
+
|
1894 |
+
t.setControlsSize();
|
1895 |
+
|
1896 |
+
},
|
1897 |
+
|
1898 |
+
hideControls: function(doAnimation) {
|
1899 |
+
var t = this;
|
1900 |
+
|
1901 |
+
doAnimation = typeof doAnimation == 'undefined' || doAnimation;
|
1902 |
+
|
1903 |
+
if (!t.controlsAreVisible)
|
1904 |
+
return;
|
1905 |
+
|
1906 |
+
if (doAnimation) {
|
1907 |
+
// fade out main controls
|
1908 |
+
t.controls.stop(true, true).fadeOut(200, function() {
|
1909 |
+
$(this)
|
1910 |
+
.css('visibility','hidden')
|
1911 |
+
.css('display','block');
|
1912 |
+
|
1913 |
+
t.controlsAreVisible = false;
|
1914 |
+
});
|
1915 |
+
|
1916 |
+
// any additional controls people might add and want to hide
|
1917 |
+
t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() {
|
1918 |
+
$(this)
|
1919 |
+
.css('visibility','hidden')
|
1920 |
+
.css('display','block');
|
1921 |
+
});
|
1922 |
+
} else {
|
1923 |
+
|
1924 |
+
// hide main controls
|
1925 |
+
t.controls
|
1926 |
+
.css('visibility','hidden')
|
1927 |
+
.css('display','block');
|
1928 |
+
|
1929 |
+
// hide others
|
1930 |
+
t.container.find('.mejs-control')
|
1931 |
+
.css('visibility','hidden')
|
1932 |
+
.css('display','block');
|
1933 |
+
|
1934 |
+
t.controlsAreVisible = false;
|
1935 |
+
}
|
1936 |
+
},
|
1937 |
+
|
1938 |
+
controlsTimer: null,
|
1939 |
+
|
1940 |
+
startControlsTimer: function(timeout) {
|
1941 |
+
|
1942 |
+
var t = this;
|
1943 |
+
|
1944 |
+
timeout = typeof timeout != 'undefined' ? timeout : 1500;
|
1945 |
+
|
1946 |
+
t.killControlsTimer('start');
|
1947 |
+
|
1948 |
+
t.controlsTimer = setTimeout(function() {
|
1949 |
+
//console.log('timer fired');
|
1950 |
+
t.hideControls();
|
1951 |
+
t.killControlsTimer('hide');
|
1952 |
+
}, timeout);
|
1953 |
+
},
|
1954 |
+
|
1955 |
+
killControlsTimer: function(src) {
|
1956 |
+
|
1957 |
+
var t = this;
|
1958 |
+
|
1959 |
+
if (t.controlsTimer !== null) {
|
1960 |
+
clearTimeout(t.controlsTimer);
|
1961 |
+
delete t.controlsTimer;
|
1962 |
+
t.controlsTimer = null;
|
1963 |
+
}
|
1964 |
+
},
|
1965 |
+
|
1966 |
+
controlsEnabled: true,
|
1967 |
+
|
1968 |
+
disableControls: function() {
|
1969 |
+
var t= this;
|
1970 |
+
|
1971 |
+
t.killControlsTimer();
|
1972 |
+
t.hideControls(false);
|
1973 |
+
this.controlsEnabled = false;
|
1974 |
+
},
|
1975 |
+
|
1976 |
+
enableControls: function() {
|
1977 |
+
var t= this;
|
1978 |
+
|
1979 |
+
t.showControls(false);
|
1980 |
+
|
1981 |
+
t.controlsEnabled = true;
|
1982 |
+
},
|
1983 |
+
|
1984 |
+
|
1985 |
+
// Sets up all controls and events
|
1986 |
+
meReady: function(media, domNode) {
|
1987 |
+
|
1988 |
+
|
1989 |
+
var t = this,
|
1990 |
+
mf = mejs.MediaFeatures,
|
1991 |
+
autoplayAttr = domNode.getAttribute('autoplay'),
|
1992 |
+
autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'),
|
1993 |
+
featureIndex,
|
1994 |
+
feature;
|
1995 |
+
|
1996 |
+
// make sure it can't create itself again if a plugin reloads
|
1997 |
+
if (t.created)
|
1998 |
+
return;
|
1999 |
+
else
|
2000 |
+
t.created = true;
|
2001 |
+
|
2002 |
+
t.media = media;
|
2003 |
+
t.domNode = domNode;
|
2004 |
+
|
2005 |
+
if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) {
|
2006 |
+
|
2007 |
+
// two built in features
|
2008 |
+
t.buildposter(t, t.controls, t.layers, t.media);
|
2009 |
+
t.buildkeyboard(t, t.controls, t.layers, t.media);
|
2010 |
+
t.buildoverlays(t, t.controls, t.layers, t.media);
|
2011 |
+
|
2012 |
+
// grab for use by features
|
2013 |
+
t.findTracks();
|
2014 |
+
|
2015 |
+
// add user-defined features/controls
|
2016 |
+
for (featureIndex in t.options.features) {
|
2017 |
+
feature = t.options.features[featureIndex];
|
2018 |
+
if (t['build' + feature]) {
|
2019 |
+
try {
|
2020 |
+
t['build' + feature](t, t.controls, t.layers, t.media);
|
2021 |
+
} catch (e) {
|
2022 |
+
// TODO: report control error
|
2023 |
+
//throw e;
|
2024 |
+
//console.log('error building ' + feature);
|
2025 |
+
//console.log(e);
|
2026 |
+
}
|
2027 |
+
}
|
2028 |
+
}
|
2029 |
+
|
2030 |
+
t.container.trigger('controlsready');
|
2031 |
+
|
2032 |
+
// reset all layers and controls
|
2033 |
+
t.setPlayerSize(t.width, t.height);
|
2034 |
+
t.setControlsSize();
|
2035 |
+
|
2036 |
+
|
2037 |
+
// controls fade
|
2038 |
+
if (t.isVideo) {
|
2039 |
+
|
2040 |
+
if (mejs.MediaFeatures.hasTouch) {
|
2041 |
+
|
2042 |
+
// for touch devices (iOS, Android)
|
2043 |
+
// show/hide without animation on touch
|
2044 |
+
|
2045 |
+
t.$media.bind('touchstart', function() {
|
2046 |
+
|
2047 |
+
|
2048 |
+
// toggle controls
|
2049 |
+
if (t.controlsAreVisible) {
|
2050 |
+
t.hideControls(false);
|
2051 |
+
} else {
|
2052 |
+
if (t.controlsEnabled) {
|
2053 |
+
t.showControls(false);
|
2054 |
+
}
|
2055 |
+
}
|
2056 |
+
});
|
2057 |
+
|
2058 |
+
} else {
|
2059 |
+
// click controls
|
2060 |
+
var clickElement = (t.media.pluginType == 'native') ? t.$media : $(t.media.pluginElement);
|
2061 |
+
|
2062 |
+
// click to play/pause
|
2063 |
+
clickElement.click(function() {
|
2064 |
+
if (media.paused) {
|
2065 |
+
media.play();
|
2066 |
+
} else {
|
2067 |
+
media.pause();
|
2068 |
+
}
|
2069 |
+
});
|
2070 |
+
|
2071 |
+
|
2072 |
+
// show/hide controls
|
2073 |
+
t.container
|
2074 |
+
.bind('mouseenter mouseover', function () {
|
2075 |
+
if (t.controlsEnabled) {
|
2076 |
+
if (!t.options.alwaysShowControls) {
|
2077 |
+
t.killControlsTimer('enter');
|
2078 |
+
t.showControls();
|
2079 |
+
t.startControlsTimer(2500);
|
2080 |
+
}
|
2081 |
+
}
|
2082 |
+
})
|
2083 |
+
.bind('mousemove', function() {
|
2084 |
+
if (t.controlsEnabled) {
|
2085 |
+
if (!t.controlsAreVisible) {
|
2086 |
+
t.showControls();
|
2087 |
+
}
|
2088 |
+
//t.killControlsTimer('move');
|
2089 |
+
if (!t.options.alwaysShowControls) {
|
2090 |
+
t.startControlsTimer(2500);
|
2091 |
+
}
|
2092 |
+
}
|
2093 |
+
})
|
2094 |
+
.bind('mouseleave', function () {
|
2095 |
+
if (t.controlsEnabled) {
|
2096 |
+
if (!t.media.paused && !t.options.alwaysShowControls) {
|
2097 |
+
t.startControlsTimer(1000);
|
2098 |
+
}
|
2099 |
+
}
|
2100 |
+
});
|
2101 |
+
}
|
2102 |
+
|
2103 |
+
// check for autoplay
|
2104 |
+
if (autoplay && !t.options.alwaysShowControls) {
|
2105 |
+
t.hideControls();
|
2106 |
+
}
|
2107 |
+
|
2108 |
+
// resizer
|
2109 |
+
if (t.options.enableAutosize) {
|
2110 |
+
t.media.addEventListener('loadedmetadata', function(e) {
|
2111 |
+
// if the <video height> was not set and the options.videoHeight was not set
|
2112 |
+
// then resize to the real dimensions
|
2113 |
+
if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) {
|
2114 |
+
t.setPlayerSize(e.target.videoWidth, e.target.videoHeight);
|
2115 |
+
t.setControlsSize();
|
2116 |
+
t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight);
|
2117 |
+
}
|
2118 |
+
}, false);
|
2119 |
+
}
|
2120 |
+
}
|
2121 |
+
|
2122 |
+
// EVENTS
|
2123 |
+
|
2124 |
+
// FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them)
|
2125 |
+
media.addEventListener('play', function() {
|
2126 |
+
|
2127 |
+
// go through all other players
|
2128 |
+
for (var i=0, il=mejs.players.length; i<il; i++) {
|
2129 |
+
var p = mejs.players[i];
|
2130 |
+
if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) {
|
2131 |
+
p.pause();
|
2132 |
+
}
|
2133 |
+
p.hasFocus = false;
|
2134 |
+
}
|
2135 |
+
|
2136 |
+
t.hasFocus = true;
|
2137 |
+
},false);
|
2138 |
+
|
2139 |
+
|
2140 |
+
// ended for all
|
2141 |
+
t.media.addEventListener('ended', function (e) {
|
2142 |
+
try{
|
2143 |
+
t.media.setCurrentTime(0);
|
2144 |
+
} catch (exp) {
|
2145 |
+
|
2146 |
+
}
|
2147 |
+
t.media.pause();
|
2148 |
+
|
2149 |
+
if (t.setProgressRail)
|
2150 |
+
t.setProgressRail();
|
2151 |
+
if (t.setCurrentRail)
|
2152 |
+
t.setCurrentRail();
|
2153 |
+
|
2154 |
+
if (t.options.loop) {
|
2155 |
+
t.media.play();
|
2156 |
+
} else if (!t.options.alwaysShowControls && t.controlsEnabled) {
|
2157 |
+
t.showControls();
|
2158 |
+
}
|
2159 |
+
}, false);
|
2160 |
+
|
2161 |
+
// resize on the first play
|
2162 |
+
t.media.addEventListener('loadedmetadata', function(e) {
|
2163 |
+
if (t.updateDuration) {
|
2164 |
+
t.updateDuration();
|
2165 |
+
}
|
2166 |
+
if (t.updateCurrent) {
|
2167 |
+
t.updateCurrent();
|
2168 |
+
}
|
2169 |
+
|
2170 |
+
if (!t.isFullScreen) {
|
2171 |
+
t.setPlayerSize(t.width, t.height);
|
2172 |
+
t.setControlsSize();
|
2173 |
+
}
|
2174 |
+
}, false);
|
2175 |
+
|
2176 |
+
|
2177 |
+
// webkit has trouble doing this without a delay
|
2178 |
+
setTimeout(function () {
|
2179 |
+
t.setPlayerSize(t.width, t.height);
|
2180 |
+
t.setControlsSize();
|
2181 |
+
}, 50);
|
2182 |
+
|
2183 |
+
// adjust controls whenever window sizes (used to be in fullscreen only)
|
2184 |
+
$(window).resize(function() {
|
2185 |
+
|
2186 |
+
// don't resize for fullscreen mode
|
2187 |
+
if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) {
|
2188 |
+
t.setPlayerSize(t.width, t.height);
|
2189 |
+
}
|
2190 |
+
|
2191 |
+
// always adjust controls
|
2192 |
+
t.setControlsSize();
|
2193 |
+
});
|
2194 |
+
|
2195 |
+
// TEMP: needs to be moved somewhere else
|
2196 |
+
if (t.media.pluginType == 'youtube') {
|
2197 |
+
t.container.find('.mejs-overlay-play').hide();
|
2198 |
+
}
|
2199 |
+
}
|
2200 |
+
|
2201 |
+
// force autoplay for HTML5
|
2202 |
+
if (autoplay && media.pluginType == 'native') {
|
2203 |
+
media.load();
|
2204 |
+
media.play();
|
2205 |
+
}
|
2206 |
+
|
2207 |
+
|
2208 |
+
if (t.options.success) {
|
2209 |
+
|
2210 |
+
if (typeof t.options.success == 'string') {
|
2211 |
+
window[t.options.success](t.media, t.domNode, t);
|
2212 |
+
} else {
|
2213 |
+
t.options.success(t.media, t.domNode, t);
|
2214 |
+
}
|
2215 |
+
}
|
2216 |
+
},
|
2217 |
+
|
2218 |
+
handleError: function(e) {
|
2219 |
+
var t = this;
|
2220 |
+
|
2221 |
+
t.controls.hide();
|
2222 |
+
|
2223 |
+
// Tell user that the file cannot be played
|
2224 |
+
if (t.options.error) {
|
2225 |
+
t.options.error(e);
|
2226 |
+
}
|
2227 |
+
},
|
2228 |
+
|
2229 |
+
setPlayerSize: function(width,height) {
|
2230 |
+
var t = this;
|
2231 |
+
|
2232 |
+
if (typeof width != 'undefined')
|
2233 |
+
t.width = width;
|
2234 |
+
|
2235 |
+
if (typeof height != 'undefined')
|
2236 |
+
t.height = height;
|
2237 |
+
|
2238 |
+
// detect 100% mode
|
2239 |
+
if (t.height.toString().indexOf('%') > 0) {
|
2240 |
+
|
2241 |
+
// do we have the native dimensions yet?
|
2242 |
+
var
|
2243 |
+
nativeWidth = (t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth,
|
2244 |
+
nativeHeight = (t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight,
|
2245 |
+
parentWidth = t.container.parent().width(),
|
2246 |
+
newHeight = parseInt(parentWidth * nativeHeight/nativeWidth, 10);
|
2247 |
+
|
2248 |
+
if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) {
|
2249 |
+
parentWidth = $(window).width();
|
2250 |
+
newHeight = $(window).height();
|
2251 |
+
}
|
2252 |
+
|
2253 |
+
|
2254 |
+
// set outer container size
|
2255 |
+
t.container
|
2256 |
+
.width(parentWidth)
|
2257 |
+
.height(newHeight);
|
2258 |
+
|
2259 |
+
// set native <video>
|
2260 |
+
t.$media
|
2261 |
+
.width('100%')
|
2262 |
+
.height('100%');
|
2263 |
+
|
2264 |
+
// set shims
|
2265 |
+
t.container.find('object, embed, iframe')
|
2266 |
+
.width('100%')
|
2267 |
+
.height('100%');
|
2268 |
+
|
2269 |
+
// if shim is ready, send the size to the embeded plugin
|
2270 |
+
if (t.media.setVideoSize)
|
2271 |
+
t.media.setVideoSize(parentWidth, newHeight);
|
2272 |
+
|
2273 |
+
// set the layers
|
2274 |
+
t.layers.children('.mejs-layer')
|
2275 |
+
.width('100%')
|
2276 |
+
.height('100%');
|
2277 |
+
|
2278 |
+
|
2279 |
+
} else {
|
2280 |
+
|
2281 |
+
t.container
|
2282 |
+
.width(t.width)
|
2283 |
+
.height(t.height);
|
2284 |
+
|
2285 |
+
t.layers.children('.mejs-layer')
|
2286 |
+
.width(t.width)
|
2287 |
+
.height(t.height);
|
2288 |
+
|
2289 |
+
}
|
2290 |
+
},
|
2291 |
+
|
2292 |
+
setControlsSize: function() {
|
2293 |
+
var t = this,
|
2294 |
+
usedWidth = 0,
|
2295 |
+
railWidth = 0,
|
2296 |
+
rail = t.controls.find('.mejs-time-rail'),
|
2297 |
+
total = t.controls.find('.mejs-time-total'),
|
2298 |
+
current = t.controls.find('.mejs-time-current'),
|
2299 |
+
loaded = t.controls.find('.mejs-time-loaded'),
|
2300 |
+
others = rail.siblings();
|
2301 |
+
|
2302 |
+
|
2303 |
+
// allow the size to come from custom CSS
|
2304 |
+
if (t.options && !t.options.autosizeProgress) {
|
2305 |
+
// Also, frontends devs can be more flexible
|
2306 |
+
// due the opportunity of absolute positioning.
|
2307 |
+
railWidth = parseInt(rail.css('width'));
|
2308 |
+
}
|
2309 |
+
|
2310 |
+
// attempt to autosize
|
2311 |
+
if (railWidth === 0 || !railWidth) {
|
2312 |
+
|
2313 |
+
// find the size of all the other controls besides the rail
|
2314 |
+
others.each(function() {
|
2315 |
+
if ($(this).css('position') != 'absolute') {
|
2316 |
+
usedWidth += $(this).outerWidth(true);
|
2317 |
+
}
|
2318 |
+
});
|
2319 |
+
|
2320 |
+
// fit the rail into the remaining space
|
2321 |
+
railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.width());
|
2322 |
+
}
|
2323 |
+
|
2324 |
+
// outer area
|
2325 |
+
rail.width(railWidth);
|
2326 |
+
// dark space
|
2327 |
+
total.width(railWidth - (total.outerWidth(true) - total.width()));
|
2328 |
+
|
2329 |
+
if (t.setProgressRail)
|
2330 |
+
t.setProgressRail();
|
2331 |
+
if (t.setCurrentRail)
|
2332 |
+
t.setCurrentRail();
|
2333 |
+
},
|
2334 |
+
|
2335 |
+
|
2336 |
+
buildposter: function(player, controls, layers, media) {
|
2337 |
+
var t = this,
|
2338 |
+
poster =
|
2339 |
+
$('<div class="mejs-poster mejs-layer">' +
|
2340 |
+
'</div>')
|
2341 |
+
.appendTo(layers),
|
2342 |
+
posterUrl = player.$media.attr('poster');
|
2343 |
+
|
2344 |
+
// prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster)
|
2345 |
+
if (player.options.poster !== '') {
|
2346 |
+
posterUrl = player.options.poster;
|
2347 |
+
}
|
2348 |
+
|
2349 |
+
// second, try the real poster
|
2350 |
+
if (posterUrl !== '' && posterUrl != null) {
|
2351 |
+
t.setPoster(posterUrl);
|
2352 |
+
} else {
|
2353 |
+
poster.hide();
|
2354 |
+
}
|
2355 |
+
|
2356 |
+
media.addEventListener('play',function() {
|
2357 |
+
poster.hide();
|
2358 |
+
}, false);
|
2359 |
+
},
|
2360 |
+
|
2361 |
+
setPoster: function(url) {
|
2362 |
+
var t = this,
|
2363 |
+
posterDiv = t.container.find('.mejs-poster'),
|
2364 |
+
posterImg = posterDiv.find('img');
|
2365 |
+
|
2366 |
+
if (posterImg.length == 0) {
|
2367 |
+
posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv);
|
2368 |
+
}
|
2369 |
+
|
2370 |
+
posterImg.attr('src', url);
|
2371 |
+
},
|
2372 |
+
|
2373 |
+
buildoverlays: function(player, controls, layers, media) {
|
2374 |
+
if (!player.isVideo)
|
2375 |
+
return;
|
2376 |
+
|
2377 |
+
var
|
2378 |
+
loading =
|
2379 |
+
$('<div class="mejs-overlay mejs-layer">'+
|
2380 |
+
'<div class="mejs-overlay-loading"><span></span></div>'+
|
2381 |
+
'</div>')
|
2382 |
+
.hide() // start out hidden
|
2383 |
+
.appendTo(layers),
|
2384 |
+
error =
|
2385 |
+
$('<div class="mejs-overlay mejs-layer">'+
|
2386 |
+
'<div class="mejs-overlay-error"></div>'+
|
2387 |
+
'</div>')
|
2388 |
+
.hide() // start out hidden
|
2389 |
+
.appendTo(layers),
|
2390 |
+
// this needs to come last so it's on top
|
2391 |
+
bigPlay =
|
2392 |
+
$('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+
|
2393 |
+
'<div class="mejs-overlay-button"></div>'+
|
2394 |
+
'</div>')
|
2395 |
+
.appendTo(layers)
|
2396 |
+
.click(function() {
|
2397 |
+
if (media.paused) {
|
2398 |
+
media.play();
|
2399 |
+
} else {
|
2400 |
+
media.pause();
|
2401 |
+
}
|
2402 |
+
});
|
2403 |
+
|
2404 |
+
/*
|
2405 |
+
if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) {
|
2406 |
+
bigPlay.remove();
|
2407 |
+
loading.remove();
|
2408 |
+
}
|
2409 |
+
*/
|
2410 |
+
|
2411 |
+
|
2412 |
+
// show/hide big play button
|
2413 |
+
media.addEventListener('play',function() {
|
2414 |
+
bigPlay.hide();
|
2415 |
+
loading.hide();
|
2416 |
+
controls.find('.mejs-time-buffering').hide();
|
2417 |
+
error.hide();
|
2418 |
+
}, false);
|
2419 |
+
|
2420 |
+
media.addEventListener('playing', function() {
|
2421 |
+
bigPlay.hide();
|
2422 |
+
loading.hide();
|
2423 |
+
controls.find('.mejs-time-buffering').hide();
|
2424 |
+
error.hide();
|
2425 |
+
}, false);
|
2426 |
+
|
2427 |
+
media.addEventListener('seeking', function() {
|
2428 |
+
loading.show();
|
2429 |
+
controls.find('.mejs-time-buffering').show();
|
2430 |
+
}, false);
|
2431 |
+
|
2432 |
+
media.addEventListener('seeked', function() {
|
2433 |
+
loading.hide();
|
2434 |
+
controls.find('.mejs-time-buffering').hide();
|
2435 |
+
}, false);
|
2436 |
+
|
2437 |
+
media.addEventListener('pause',function() {
|
2438 |
+
if (!mejs.MediaFeatures.isiPhone) {
|
2439 |
+
bigPlay.show();
|
2440 |
+
}
|
2441 |
+
}, false);
|
2442 |
+
|
2443 |
+
media.addEventListener('waiting', function() {
|
2444 |
+
loading.show();
|
2445 |
+
controls.find('.mejs-time-buffering').show();
|
2446 |
+
}, false);
|
2447 |
+
|
2448 |
+
|
2449 |
+
// show/hide loading
|
2450 |
+
media.addEventListener('loadeddata',function() {
|
2451 |
+
// for some reason Chrome is firing this event
|
2452 |
+
//if (mejs.MediaFeatures.isChrome && media.getAttribute && media.getAttribute('preload') === 'none')
|
2453 |
+
// return;
|
2454 |
+
|
2455 |
+
loading.show();
|
2456 |
+
controls.find('.mejs-time-buffering').show();
|
2457 |
+
}, false);
|
2458 |
+
media.addEventListener('canplay',function() {
|
2459 |
+
loading.hide();
|
2460 |
+
controls.find('.mejs-time-buffering').hide();
|
2461 |
+
}, false);
|
2462 |
+
|
2463 |
+
// error handling
|
2464 |
+
media.addEventListener('error',function() {
|
2465 |
+
loading.hide();
|
2466 |
+
controls.find('.mejs-time-buffering').hide();
|
2467 |
+
error.show();
|
2468 |
+
error.find('mejs-overlay-error').html("Error loading this resource");
|
2469 |
+
}, false);
|
2470 |
+
},
|
2471 |
+
|
2472 |
+
buildkeyboard: function(player, controls, layers, media) {
|
2473 |
+
|
2474 |
+
var t = this;
|
2475 |
+
|
2476 |
+
// listen for key presses
|
2477 |
+
$(document).keydown(function(e) {
|
2478 |
+
|
2479 |
+
if (player.hasFocus && player.options.enableKeyboard) {
|
2480 |
+
|
2481 |
+
// find a matching key
|
2482 |
+
for (var i=0, il=player.options.keyActions.length; i<il; i++) {
|
2483 |
+
var keyAction = player.options.keyActions[i];
|
2484 |
+
|
2485 |
+
for (var j=0, jl=keyAction.keys.length; j<jl; j++) {
|
2486 |
+
if (e.keyCode == keyAction.keys[j]) {
|
2487 |
+
e.preventDefault();
|
2488 |
+
keyAction.action(player, media);
|
2489 |
+
return false;
|
2490 |
+
}
|
2491 |
+
}
|
2492 |
+
}
|
2493 |
+
}
|
2494 |
+
|
2495 |
+
return true;
|
2496 |
+
});
|
2497 |
+
|
2498 |
+
// check if someone clicked outside a player region, then kill its focus
|
2499 |
+
$(document).click(function(event) {
|
2500 |
+
if ($(event.target).closest('.mejs-container').length == 0) {
|
2501 |
+
player.hasFocus = false;
|
2502 |
+
}
|
2503 |
+
});
|
2504 |
+
|
2505 |
+
},
|
2506 |
+
|
2507 |
+
findTracks: function() {
|
2508 |
+
var t = this,
|
2509 |
+
tracktags = t.$media.find('track');
|
2510 |
+
|
2511 |
+
// store for use by plugins
|
2512 |
+
t.tracks = [];
|
2513 |
+
tracktags.each(function(index, track) {
|
2514 |
+
|
2515 |
+
track = $(track);
|
2516 |
+
|
2517 |
+
t.tracks.push({
|
2518 |
+
srclang: track.attr('srclang').toLowerCase(),
|
2519 |
+
src: track.attr('src'),
|
2520 |
+
kind: track.attr('kind'),
|
2521 |
+
label: track.attr('label') || '',
|
2522 |
+
entries: [],
|
2523 |
+
isLoaded: false
|
2524 |
+
});
|
2525 |
+
});
|
2526 |
+
},
|
2527 |
+
changeSkin: function(className) {
|
2528 |
+
this.container[0].className = 'mejs-container ' + className;
|
2529 |
+
this.setPlayerSize(this.width, this.height);
|
2530 |
+
this.setControlsSize();
|
2531 |
+
},
|
2532 |
+
play: function() {
|
2533 |
+
this.media.play();
|
2534 |
+
},
|
2535 |
+
pause: function() {
|
2536 |
+
this.media.pause();
|
2537 |
+
},
|
2538 |
+
load: function() {
|
2539 |
+
this.media.load();
|
2540 |
+
},
|
2541 |
+
setMuted: function(muted) {
|
2542 |
+
this.media.setMuted(muted);
|
2543 |
+
},
|
2544 |
+
setCurrentTime: function(time) {
|
2545 |
+
this.media.setCurrentTime(time);
|
2546 |
+
},
|
2547 |
+
getCurrentTime: function() {
|
2548 |
+
return this.media.currentTime;
|
2549 |
+
},
|
2550 |
+
setVolume: function(volume) {
|
2551 |
+
this.media.setVolume(volume);
|
2552 |
+
},
|
2553 |
+
getVolume: function() {
|
2554 |
+
return this.media.volume;
|
2555 |
+
},
|
2556 |
+
setSrc: function(src) {
|
2557 |
+
this.media.setSrc(src);
|
2558 |
+
},
|
2559 |
+
remove: function() {
|
2560 |
+
var t = this;
|
2561 |
+
|
2562 |
+
if (t.media.pluginType == 'flash') {
|
2563 |
+
t.media.remove();
|
2564 |
+
} else if (t.media.pluginType == 'native') {
|
2565 |
+
t.media.prop('controls', true);
|
2566 |
+
}
|
2567 |
+
|
2568 |
+
// grab video and put it back in place
|
2569 |
+
if (!t.isDynamic) {
|
2570 |
+
t.$node.insertBefore(t.container)
|
2571 |
+
}
|
2572 |
+
|
2573 |
+
t.container.remove();
|
2574 |
+
}
|
2575 |
+
};
|
2576 |
+
|
2577 |
+
// turn into jQuery plugin
|
2578 |
+
if (typeof jQuery != 'undefined') {
|
2579 |
+
jQuery.fn.mediaelementplayer = function (options) {
|
2580 |
+
return this.each(function () {
|
2581 |
+
new mejs.MediaElementPlayer(this, options);
|
2582 |
+
});
|
2583 |
+
};
|
2584 |
+
}
|
2585 |
+
|
2586 |
+
$(document).ready(function() {
|
2587 |
+
// auto enable using JSON attribute
|
2588 |
+
$('.mejs-player').mediaelementplayer();
|
2589 |
+
});
|
2590 |
+
|
2591 |
+
// push out to window
|
2592 |
+
window.MediaElementPlayer = mejs.MediaElementPlayer;
|
2593 |
+
|
2594 |
+
})(mejs.$);
|
2595 |
+
|
2596 |
+
(function($) {
|
2597 |
+
|
2598 |
+
$.extend(mejs.MepDefaults, {
|
2599 |
+
playpauseText: 'Play/Pause'
|
2600 |
+
});
|
2601 |
+
|
2602 |
+
// PLAY/pause BUTTON
|
2603 |
+
$.extend(MediaElementPlayer.prototype, {
|
2604 |
+
buildplaypause: function(player, controls, layers, media) {
|
2605 |
+
var
|
2606 |
+
t = this,
|
2607 |
+
play =
|
2608 |
+
$('<div class="mejs-button mejs-playpause-button mejs-play" >' +
|
2609 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.playpauseText + '"></button>' +
|
2610 |
+
'</div>')
|
2611 |
+
.appendTo(controls)
|
2612 |
+
.click(function(e) {
|
2613 |
+
e.preventDefault();
|
2614 |
+
|
2615 |
+
if (media.paused) {
|
2616 |
+
media.play();
|
2617 |
+
} else {
|
2618 |
+
media.pause();
|
2619 |
+
}
|
2620 |
+
|
2621 |
+
return false;
|
2622 |
+
});
|
2623 |
+
|
2624 |
+
media.addEventListener('play',function() {
|
2625 |
+
play.removeClass('mejs-play').addClass('mejs-pause');
|
2626 |
+
}, false);
|
2627 |
+
media.addEventListener('playing',function() {
|
2628 |
+
play.removeClass('mejs-play').addClass('mejs-pause');
|
2629 |
+
}, false);
|
2630 |
+
|
2631 |
+
|
2632 |
+
media.addEventListener('pause',function() {
|
2633 |
+
play.removeClass('mejs-pause').addClass('mejs-play');
|
2634 |
+
}, false);
|
2635 |
+
media.addEventListener('paused',function() {
|
2636 |
+
play.removeClass('mejs-pause').addClass('mejs-play');
|
2637 |
+
}, false);
|
2638 |
+
}
|
2639 |
+
});
|
2640 |
+
|
2641 |
+
})(mejs.$);
|
2642 |
+
(function($) {
|
2643 |
+
|
2644 |
+
$.extend(mejs.MepDefaults, {
|
2645 |
+
stopText: 'Stop'
|
2646 |
+
});
|
2647 |
+
|
2648 |
+
// STOP BUTTON
|
2649 |
+
$.extend(MediaElementPlayer.prototype, {
|
2650 |
+
buildstop: function(player, controls, layers, media) {
|
2651 |
+
var t = this,
|
2652 |
+
stop =
|
2653 |
+
$('<div class="mejs-button mejs-stop-button mejs-stop">' +
|
2654 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.stopText + '"></button>' +
|
2655 |
+
'</div>')
|
2656 |
+
.appendTo(controls)
|
2657 |
+
.click(function() {
|
2658 |
+
if (!media.paused) {
|
2659 |
+
media.pause();
|
2660 |
+
}
|
2661 |
+
if (media.currentTime > 0) {
|
2662 |
+
media.setCurrentTime(0);
|
2663 |
+
controls.find('.mejs-time-current').width('0px');
|
2664 |
+
controls.find('.mejs-time-handle').css('left', '0px');
|
2665 |
+
controls.find('.mejs-time-float-current').html( mejs.Utility.secondsToTimeCode(0) );
|
2666 |
+
controls.find('.mejs-currenttime').html( mejs.Utility.secondsToTimeCode(0) );
|
2667 |
+
layers.find('.mejs-poster').show();
|
2668 |
+
}
|
2669 |
+
});
|
2670 |
+
}
|
2671 |
+
});
|
2672 |
+
|
2673 |
+
})(mejs.$);
|
2674 |
+
(function($) {
|
2675 |
+
// progress/loaded bar
|
2676 |
+
$.extend(MediaElementPlayer.prototype, {
|
2677 |
+
buildprogress: function(player, controls, layers, media) {
|
2678 |
+
|
2679 |
+
$('<div class="mejs-time-rail">'+
|
2680 |
+
'<span class="mejs-time-total">'+
|
2681 |
+
'<span class="mejs-time-buffering"></span>'+
|
2682 |
+
'<span class="mejs-time-loaded"></span>'+
|
2683 |
+
'<span class="mejs-time-current"></span>'+
|
2684 |
+
'<span class="mejs-time-handle"></span>'+
|
2685 |
+
'<span class="mejs-time-float">' +
|
2686 |
+
'<span class="mejs-time-float-current">00:00</span>' +
|
2687 |
+
'<span class="mejs-time-float-corner"></span>' +
|
2688 |
+
'</span>'+
|
2689 |
+
'</span>'+
|
2690 |
+
'</div>')
|
2691 |
+
.appendTo(controls);
|
2692 |
+
controls.find('.mejs-time-buffering').hide();
|
2693 |
+
|
2694 |
+
var
|
2695 |
+
t = this,
|
2696 |
+
total = controls.find('.mejs-time-total'),
|
2697 |
+
loaded = controls.find('.mejs-time-loaded'),
|
2698 |
+
current = controls.find('.mejs-time-current'),
|
2699 |
+
handle = controls.find('.mejs-time-handle'),
|
2700 |
+
timefloat = controls.find('.mejs-time-float'),
|
2701 |
+
timefloatcurrent = controls.find('.mejs-time-float-current'),
|
2702 |
+
handleMouseMove = function (e) {
|
2703 |
+
// mouse position relative to the object
|
2704 |
+
var x = e.pageX,
|
2705 |
+
offset = total.offset(),
|
2706 |
+
width = total.outerWidth(),
|
2707 |
+
percentage = 0,
|
2708 |
+
newTime = 0,
|
2709 |
+
pos = x - offset.left;
|
2710 |
+
|
2711 |
+
|
2712 |
+
if (x > offset.left && x <= width + offset.left && media.duration) {
|
2713 |
+
percentage = ((x - offset.left) / width);
|
2714 |
+
newTime = (percentage <= 0.02) ? 0 : percentage * media.duration;
|
2715 |
+
|
2716 |
+
// seek to where the mouse is
|
2717 |
+
if (mouseIsDown) {
|
2718 |
+
media.setCurrentTime(newTime);
|
2719 |
+
}
|
2720 |
+
|
2721 |
+
// position floating time box
|
2722 |
+
if (!mejs.MediaFeatures.hasTouch) {
|
2723 |
+
timefloat.css('left', pos);
|
2724 |
+
timefloatcurrent.html( mejs.Utility.secondsToTimeCode(newTime) );
|
2725 |
+
timefloat.show();
|
2726 |
+
}
|
2727 |
+
}
|
2728 |
+
},
|
2729 |
+
mouseIsDown = false,
|
2730 |
+
mouseIsOver = false;
|
2731 |
+
|
2732 |
+
// handle clicks
|
2733 |
+
//controls.find('.mejs-time-rail').delegate('span', 'click', handleMouseMove);
|
2734 |
+
total
|
2735 |
+
.bind('mousedown', function (e) {
|
2736 |
+
// only handle left clicks
|
2737 |
+
if (e.which === 1) {
|
2738 |
+
mouseIsDown = true;
|
2739 |
+
handleMouseMove(e);
|
2740 |
+
$(document)
|
2741 |
+
.bind('mousemove.dur', function(e) {
|
2742 |
+
handleMouseMove(e);
|
2743 |
+
})
|
2744 |
+
.bind('mouseup.dur', function (e) {
|
2745 |
+
mouseIsDown = false;
|
2746 |
+
timefloat.hide();
|
2747 |
+
$(document).unbind('.dur');
|
2748 |
+
});
|
2749 |
+
return false;
|
2750 |
+
}
|
2751 |
+
})
|
2752 |
+
.bind('mouseenter', function(e) {
|
2753 |
+
mouseIsOver = true;
|
2754 |
+
$(document).bind('mousemove.dur', function(e) {
|
2755 |
+
handleMouseMove(e);
|
2756 |
+
});
|
2757 |
+
if (!mejs.MediaFeatures.hasTouch) {
|
2758 |
+
timefloat.show();
|
2759 |
+
}
|
2760 |
+
})
|
2761 |
+
.bind('mouseleave',function(e) {
|
2762 |
+
mouseIsOver = false;
|
2763 |
+
if (!mouseIsDown) {
|
2764 |
+
$(document).unbind('.dur');
|
2765 |
+
timefloat.hide();
|
2766 |
+
}
|
2767 |
+
});
|
2768 |
+
|
2769 |
+
// loading
|
2770 |
+
media.addEventListener('progress', function (e) {
|
2771 |
+
player.setProgressRail(e);
|
2772 |
+
player.setCurrentRail(e);
|
2773 |
+
}, false);
|
2774 |
+
|
2775 |
+
// current time
|
2776 |
+
media.addEventListener('timeupdate', function(e) {
|
2777 |
+
player.setProgressRail(e);
|
2778 |
+
player.setCurrentRail(e);
|
2779 |
+
}, false);
|
2780 |
+
|
2781 |
+
|
2782 |
+
// store for later use
|
2783 |
+
t.loaded = loaded;
|
2784 |
+
t.total = total;
|
2785 |
+
t.current = current;
|
2786 |
+
t.handle = handle;
|
2787 |
+
},
|
2788 |
+
setProgressRail: function(e) {
|
2789 |
+
|
2790 |
+
var
|
2791 |
+
t = this,
|
2792 |
+
target = (e != undefined) ? e.target : t.media,
|
2793 |
+
percent = null;
|
2794 |
+
|
2795 |
+
// newest HTML5 spec has buffered array (FF4, Webkit)
|
2796 |
+
if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) {
|
2797 |
+
// TODO: account for a real array with multiple values (only Firefox 4 has this so far)
|
2798 |
+
percent = target.buffered.end(0) / target.duration;
|
2799 |
+
}
|
2800 |
+
// Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
|
2801 |
+
// to be anything other than 0. If the byte count is available we use this instead.
|
2802 |
+
// Browsers that support the else if do not seem to have the bufferedBytes value and
|
2803 |
+
// should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8.
|
2804 |
+
else if (target && target.bytesTotal != undefined && target.bytesTotal > 0 && target.bufferedBytes != undefined) {
|
2805 |
+
percent = target.bufferedBytes / target.bytesTotal;
|
2806 |
+
}
|
2807 |
+
// Firefox 3 with an Ogg file seems to go this way
|
2808 |
+
else if (e && e.lengthComputable && e.total != 0) {
|
2809 |
+
percent = e.loaded/e.total;
|
2810 |
+
}
|
2811 |
+
|
2812 |
+
// finally update the progress bar
|
2813 |
+
if (percent !== null) {
|
2814 |
+
percent = Math.min(1, Math.max(0, percent));
|
2815 |
+
// update loaded bar
|
2816 |
+
if (t.loaded && t.total) {
|
2817 |
+
t.loaded.width(t.total.width() * percent);
|
2818 |
+
}
|
2819 |
+
}
|
2820 |
+
},
|
2821 |
+
setCurrentRail: function() {
|
2822 |
+
|
2823 |
+
var t = this;
|
2824 |
+
|
2825 |
+
if (t.media.currentTime != undefined && t.media.duration) {
|
2826 |
+
|
2827 |
+
// update bar and handle
|
2828 |
+
if (t.total && t.handle) {
|
2829 |
+
var
|
2830 |
+
newWidth = t.total.width() * t.media.currentTime / t.media.duration,
|
2831 |
+
handlePos = newWidth - (t.handle.outerWidth(true) / 2);
|
2832 |
+
|
2833 |
+
t.current.width(newWidth);
|
2834 |
+
t.handle.css('left', handlePos);
|
2835 |
+
}
|
2836 |
+
}
|
2837 |
+
|
2838 |
+
}
|
2839 |
+
});
|
2840 |
+
})(mejs.$);
|
2841 |
+
(function($) {
|
2842 |
+
|
2843 |
+
// options
|
2844 |
+
$.extend(mejs.MepDefaults, {
|
2845 |
+
duration: -1,
|
2846 |
+
timeAndDurationSeparator: ' <span> | </span> '
|
2847 |
+
});
|
2848 |
+
|
2849 |
+
|
2850 |
+
// current and duration 00:00 / 00:00
|
2851 |
+
$.extend(MediaElementPlayer.prototype, {
|
2852 |
+
buildcurrent: function(player, controls, layers, media) {
|
2853 |
+
var t = this;
|
2854 |
+
|
2855 |
+
$('<div class="mejs-time">'+
|
2856 |
+
'<span class="mejs-currenttime">' + (player.options.alwaysShowHours ? '00:' : '')
|
2857 |
+
+ (player.options.showTimecodeFrameCount? '00:00:00':'00:00')+ '</span>'+
|
2858 |
+
'</div>')
|
2859 |
+
.appendTo(controls);
|
2860 |
+
|
2861 |
+
t.currenttime = t.controls.find('.mejs-currenttime');
|
2862 |
+
|
2863 |
+
media.addEventListener('timeupdate',function() {
|
2864 |
+
player.updateCurrent();
|
2865 |
+
}, false);
|
2866 |
+
},
|
2867 |
+
|
2868 |
+
|
2869 |
+
buildduration: function(player, controls, layers, media) {
|
2870 |
+
var t = this;
|
2871 |
+
|
2872 |
+
if (controls.children().last().find('.mejs-currenttime').length > 0) {
|
2873 |
+
$(t.options.timeAndDurationSeparator +
|
2874 |
+
'<span class="mejs-duration">' +
|
2875 |
+
(t.options.duration > 0 ?
|
2876 |
+
mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) :
|
2877 |
+
((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00'))
|
2878 |
+
) +
|
2879 |
+
'</span>')
|
2880 |
+
.appendTo(controls.find('.mejs-time'));
|
2881 |
+
} else {
|
2882 |
+
|
2883 |
+
// add class to current time
|
2884 |
+
controls.find('.mejs-currenttime').parent().addClass('mejs-currenttime-container');
|
2885 |
+
|
2886 |
+
$('<div class="mejs-time mejs-duration-container">'+
|
2887 |
+
'<span class="mejs-duration">' +
|
2888 |
+
(t.options.duration > 0 ?
|
2889 |
+
mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) :
|
2890 |
+
((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00'))
|
2891 |
+
) +
|
2892 |
+
'</span>' +
|
2893 |
+
'</div>')
|
2894 |
+
.appendTo(controls);
|
2895 |
+
}
|
2896 |
+
|
2897 |
+
t.durationD = t.controls.find('.mejs-duration');
|
2898 |
+
|
2899 |
+
media.addEventListener('timeupdate',function() {
|
2900 |
+
player.updateDuration();
|
2901 |
+
}, false);
|
2902 |
+
},
|
2903 |
+
|
2904 |
+
updateCurrent: function() {
|
2905 |
+
var t = this;
|
2906 |
+
|
2907 |
+
if (t.currenttime) {
|
2908 |
+
t.currenttime.html(mejs.Utility.secondsToTimeCode(t.media.currentTime, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25));
|
2909 |
+
}
|
2910 |
+
},
|
2911 |
+
|
2912 |
+
updateDuration: function() {
|
2913 |
+
var t = this;
|
2914 |
+
|
2915 |
+
if (t.media.duration && t.durationD) {
|
2916 |
+
t.durationD.html(mejs.Utility.secondsToTimeCode(t.media.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25));
|
2917 |
+
}
|
2918 |
+
}
|
2919 |
+
});
|
2920 |
+
|
2921 |
+
})(mejs.$);
|
2922 |
+
(function($) {
|
2923 |
+
|
2924 |
+
$.extend(mejs.MepDefaults, {
|
2925 |
+
muteText: 'Mute Toggle',
|
2926 |
+
hideVolumeOnTouchDevices: true,
|
2927 |
+
|
2928 |
+
audioVolume: 'horizontal',
|
2929 |
+
videoVolume: 'vertical'
|
2930 |
+
});
|
2931 |
+
|
2932 |
+
$.extend(MediaElementPlayer.prototype, {
|
2933 |
+
buildvolume: function(player, controls, layers, media) {
|
2934 |
+
|
2935 |
+
// Android and iOS don't support volume controls
|
2936 |
+
if (mejs.MediaFeatures.hasTouch && this.options.hideVolumeOnTouchDevices)
|
2937 |
+
return;
|
2938 |
+
|
2939 |
+
var t = this,
|
2940 |
+
mode = (t.isVideo) ? t.options.videoVolume : t.options.audioVolume,
|
2941 |
+
mute = (mode == 'horizontal') ?
|
2942 |
+
|
2943 |
+
// horizontal version
|
2944 |
+
$('<div class="mejs-button mejs-volume-button mejs-mute">'+
|
2945 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
|
2946 |
+
'</div>' +
|
2947 |
+
'<div class="mejs-horizontal-volume-slider">'+ // outer background
|
2948 |
+
'<div class="mejs-horizontal-volume-total"></div>'+ // line background
|
2949 |
+
'<div class="mejs-horizontal-volume-current"></div>'+ // current volume
|
2950 |
+
'<div class="mejs-horizontal-volume-handle"></div>'+ // handle
|
2951 |
+
'</div>'
|
2952 |
+
)
|
2953 |
+
.appendTo(controls) :
|
2954 |
+
|
2955 |
+
// vertical version
|
2956 |
+
$('<div class="mejs-button mejs-volume-button mejs-mute">'+
|
2957 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
|
2958 |
+
'<div class="mejs-volume-slider">'+ // outer background
|
2959 |
+
'<div class="mejs-volume-total"></div>'+ // line background
|
2960 |
+
'<div class="mejs-volume-current"></div>'+ // current volume
|
2961 |
+
'<div class="mejs-volume-handle"></div>'+ // handle
|
2962 |
+
'</div>'+
|
2963 |
+
'</div>')
|
2964 |
+
.appendTo(controls),
|
2965 |
+
volumeSlider = t.container.find('.mejs-volume-slider, .mejs-horizontal-volume-slider'),
|
2966 |
+
volumeTotal = t.container.find('.mejs-volume-total, .mejs-horizontal-volume-total'),
|
2967 |
+
volumeCurrent = t.container.find('.mejs-volume-current, .mejs-horizontal-volume-current'),
|
2968 |
+
volumeHandle = t.container.find('.mejs-volume-handle, .mejs-horizontal-volume-handle'),
|
2969 |
+
|
2970 |
+
positionVolumeHandle = function(volume, secondTry) {
|
2971 |
+
|
2972 |
+
if (!volumeSlider.is(':visible') && typeof secondTry != 'undefined') {
|
2973 |
+
volumeSlider.show();
|
2974 |
+
positionVolumeHandle(volume, true);
|
2975 |
+
volumeSlider.hide()
|
2976 |
+
return;
|
2977 |
+
}
|
2978 |
+
|
2979 |
+
// correct to 0-1
|
2980 |
+
volume = Math.max(0,volume);
|
2981 |
+
volume = Math.min(volume,1);
|
2982 |
+
|
2983 |
+
// ajust mute button style
|
2984 |
+
if (volume == 0) {
|
2985 |
+
mute.removeClass('mejs-mute').addClass('mejs-unmute');
|
2986 |
+
} else {
|
2987 |
+
mute.removeClass('mejs-unmute').addClass('mejs-mute');
|
2988 |
+
}
|
2989 |
+
|
2990 |
+
// position slider
|
2991 |
+
if (mode == 'vertical') {
|
2992 |
+
var
|
2993 |
+
|
2994 |
+
// height of the full size volume slider background
|
2995 |
+
totalHeight = volumeTotal.height(),
|
2996 |
+
|
2997 |
+
// top/left of full size volume slider background
|
2998 |
+
totalPosition = volumeTotal.position(),
|
2999 |
+
|
3000 |
+
// the new top position based on the current volume
|
3001 |
+
// 70% volume on 100px height == top:30px
|
3002 |
+
newTop = totalHeight - (totalHeight * volume);
|
3003 |
+
|
3004 |
+
// handle
|
3005 |
+
volumeHandle.css('top', totalPosition.top + newTop - (volumeHandle.height() / 2));
|
3006 |
+
|
3007 |
+
// show the current visibility
|
3008 |
+
volumeCurrent.height(totalHeight - newTop );
|
3009 |
+
volumeCurrent.css('top', totalPosition.top + newTop);
|
3010 |
+
} else {
|
3011 |
+
var
|
3012 |
+
|
3013 |
+
// height of the full size volume slider background
|
3014 |
+
totalWidth = volumeTotal.width(),
|
3015 |
+
|
3016 |
+
// top/left of full size volume slider background
|
3017 |
+
totalPosition = volumeTotal.position(),
|
3018 |
+
|
3019 |
+
// the new left position based on the current volume
|
3020 |
+
newLeft = totalWidth * volume;
|
3021 |
+
|
3022 |
+
// handle
|
3023 |
+
volumeHandle.css('left', totalPosition.left + newLeft - (volumeHandle.width() / 2));
|
3024 |
+
|
3025 |
+
// rezize the current part of the volume bar
|
3026 |
+
volumeCurrent.width( newLeft );
|
3027 |
+
}
|
3028 |
+
},
|
3029 |
+
handleVolumeMove = function(e) {
|
3030 |
+
|
3031 |
+
var volume = null,
|
3032 |
+
totalOffset = volumeTotal.offset();
|
3033 |
+
|
3034 |
+
// calculate the new volume based on the moust position
|
3035 |
+
if (mode == 'vertical') {
|
3036 |
+
|
3037 |
+
var
|
3038 |
+
railHeight = volumeTotal.height(),
|
3039 |
+
totalTop = parseInt(volumeTotal.css('top').replace(/px/,''),10),
|
3040 |
+
newY = e.pageY - totalOffset.top;
|
3041 |
+
|
3042 |
+
volume = (railHeight - newY) / railHeight;
|
3043 |
+
|
3044 |
+
// the controls just hide themselves (usually when mouse moves too far up)
|
3045 |
+
if (totalOffset.top == 0 || totalOffset.left == 0)
|
3046 |
+
return;
|
3047 |
+
|
3048 |
+
} else {
|
3049 |
+
var
|
3050 |
+
railWidth = volumeTotal.width(),
|
3051 |
+
newX = e.pageX - totalOffset.left;
|
3052 |
+
|
3053 |
+
volume = newX / railWidth;
|
3054 |
+
}
|
3055 |
+
|
3056 |
+
// ensure the volume isn't outside 0-1
|
3057 |
+
volume = Math.max(0,volume);
|
3058 |
+
volume = Math.min(volume,1);
|
3059 |
+
|
3060 |
+
// position the slider and handle
|
3061 |
+
positionVolumeHandle(volume);
|
3062 |
+
|
3063 |
+
// set the media object (this will trigger the volumechanged event)
|
3064 |
+
if (volume == 0) {
|
3065 |
+
media.setMuted(true);
|
3066 |
+
} else {
|
3067 |
+
media.setMuted(false);
|
3068 |
+
}
|
3069 |
+
media.setVolume(volume);
|
3070 |
+
},
|
3071 |
+
mouseIsDown = false,
|
3072 |
+
mouseIsOver = false;
|
3073 |
+
|
3074 |
+
// SLIDER
|
3075 |
+
|
3076 |
+
mute
|
3077 |
+
.hover(function() {
|
3078 |
+
volumeSlider.show();
|
3079 |
+
mouseIsOver = true;
|
3080 |
+
}, function() {
|
3081 |
+
mouseIsOver = false;
|
3082 |
+
|
3083 |
+
if (!mouseIsDown && mode == 'vertical') {
|
3084 |
+
volumeSlider.hide();
|
3085 |
+
}
|
3086 |
+
});
|
3087 |
+
|
3088 |
+
volumeSlider
|
3089 |
+
.bind('mouseover', function() {
|
3090 |
+
mouseIsOver = true;
|
3091 |
+
})
|
3092 |
+
.bind('mousedown', function (e) {
|
3093 |
+
handleVolumeMove(e);
|
3094 |
+
$(document)
|
3095 |
+
.bind('mousemove.vol', function(e) {
|
3096 |
+
handleVolumeMove(e);
|
3097 |
+
})
|
3098 |
+
.bind('mouseup.vol', function () {
|
3099 |
+
mouseIsDown = false;
|
3100 |
+
$(document).unbind('.vol');
|
3101 |
+
|
3102 |
+
if (!mouseIsOver && mode == 'vertical') {
|
3103 |
+
volumeSlider.hide();
|
3104 |
+
}
|
3105 |
+
});
|
3106 |
+
mouseIsDown = true;
|
3107 |
+
|
3108 |
+
return false;
|
3109 |
+
});
|
3110 |
+
|
3111 |
+
|
3112 |
+
// MUTE button
|
3113 |
+
mute.find('button').click(function() {
|
3114 |
+
media.setMuted( !media.muted );
|
3115 |
+
});
|
3116 |
+
|
3117 |
+
// listen for volume change events from other sources
|
3118 |
+
media.addEventListener('volumechange', function(e) {
|
3119 |
+
if (!mouseIsDown) {
|
3120 |
+
if (media.muted) {
|
3121 |
+
positionVolumeHandle(0);
|
3122 |
+
mute.removeClass('mejs-mute').addClass('mejs-unmute');
|
3123 |
+
} else {
|
3124 |
+
positionVolumeHandle(media.volume);
|
3125 |
+
mute.removeClass('mejs-unmute').addClass('mejs-mute');
|
3126 |
+
}
|
3127 |
+
}
|
3128 |
+
}, false);
|
3129 |
+
|
3130 |
+
if (t.container.is(':visible')) {
|
3131 |
+
// set initial volume
|
3132 |
+
positionVolumeHandle(player.options.startVolume);
|
3133 |
+
|
3134 |
+
// shim gets the startvolume as a parameter, but we have to set it on the native <video> and <audio> elements
|
3135 |
+
if (media.pluginType === 'native') {
|
3136 |
+
media.setVolume(player.options.startVolume);
|
3137 |
+
}
|
3138 |
+
}
|
3139 |
+
}
|
3140 |
+
});
|
3141 |
+
|
3142 |
+
})(mejs.$);
|
3143 |
+
|
3144 |
+
(function($) {
|
3145 |
+
|
3146 |
+
$.extend(mejs.MepDefaults, {
|
3147 |
+
usePluginFullScreen: true,
|
3148 |
+
newWindowCallback: function() { return '';},
|
3149 |
+
fullscreenText: 'Fullscreen'
|
3150 |
+
});
|
3151 |
+
|
3152 |
+
$.extend(MediaElementPlayer.prototype, {
|
3153 |
+
|
3154 |
+
isFullScreen: false,
|
3155 |
+
|
3156 |
+
isNativeFullScreen: false,
|
3157 |
+
|
3158 |
+
docStyleOverflow: null,
|
3159 |
+
|
3160 |
+
isInIframe: false,
|
3161 |
+
|
3162 |
+
buildfullscreen: function(player, controls, layers, media) {
|
3163 |
+
|
3164 |
+
if (!player.isVideo)
|
3165 |
+
return;
|
3166 |
+
|
3167 |
+
player.isInIframe = (window.location != window.parent.location);
|
3168 |
+
|
3169 |
+
// native events
|
3170 |
+
if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
3171 |
+
|
3172 |
+
// chrome doesn't alays fire this in an iframe
|
3173 |
+
var target = null;
|
3174 |
+
|
3175 |
+
if (mejs.MediaFeatures.hasMozNativeFullScreen) {
|
3176 |
+
target = $(document);
|
3177 |
+
} else {
|
3178 |
+
target = player.container;
|
3179 |
+
}
|
3180 |
+
|
3181 |
+
target.bind(mejs.MediaFeatures.fullScreenEventName, function(e) {
|
3182 |
+
//player.container.bind('webkitfullscreenchange', function(e) {
|
3183 |
+
|
3184 |
+
|
3185 |
+
if (mejs.MediaFeatures.isFullScreen()) {
|
3186 |
+
player.isNativeFullScreen = true;
|
3187 |
+
// reset the controls once we are fully in full screen
|
3188 |
+
player.setControlsSize();
|
3189 |
+
} else {
|
3190 |
+
player.isNativeFullScreen = false;
|
3191 |
+
// when a user presses ESC
|
3192 |
+
// make sure to put the player back into place
|
3193 |
+
player.exitFullScreen();
|
3194 |
+
}
|
3195 |
+
});
|
3196 |
+
}
|
3197 |
+
|
3198 |
+
var t = this,
|
3199 |
+
normalHeight = 0,
|
3200 |
+
normalWidth = 0,
|
3201 |
+
container = player.container,
|
3202 |
+
fullscreenBtn =
|
3203 |
+
$('<div class="mejs-button mejs-fullscreen-button">' +
|
3204 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.fullscreenText + '"></button>' +
|
3205 |
+
'</div>')
|
3206 |
+
.appendTo(controls);
|
3207 |
+
|
3208 |
+
if (t.media.pluginType === 'native' || (!t.options.usePluginFullScreen && !mejs.MediaFeatures.isFirefox)) {
|
3209 |
+
|
3210 |
+
fullscreenBtn.click(function() {
|
3211 |
+
var isFullScreen = (mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || player.isFullScreen;
|
3212 |
+
|
3213 |
+
if (isFullScreen) {
|
3214 |
+
player.exitFullScreen();
|
3215 |
+
} else {
|
3216 |
+
player.enterFullScreen();
|
3217 |
+
}
|
3218 |
+
});
|
3219 |
+
|
3220 |
+
} else {
|
3221 |
+
|
3222 |
+
var hideTimeout = null,
|
3223 |
+
supportsPointerEvents = (function() {
|
3224 |
+
// TAKEN FROM MODERNIZR
|
3225 |
+
var element = document.createElement('x'),
|
3226 |
+
documentElement = document.documentElement,
|
3227 |
+
getComputedStyle = window.getComputedStyle,
|
3228 |
+
supports;
|
3229 |
+
if(!('pointerEvents' in element.style)){
|
3230 |
+
return false;
|
3231 |
+
}
|
3232 |
+
element.style.pointerEvents = 'auto';
|
3233 |
+
element.style.pointerEvents = 'x';
|
3234 |
+
documentElement.appendChild(element);
|
3235 |
+
supports = getComputedStyle &&
|
3236 |
+
getComputedStyle(element, '').pointerEvents === 'auto';
|
3237 |
+
documentElement.removeChild(element);
|
3238 |
+
return !!supports;
|
3239 |
+
})();
|
3240 |
+
|
3241 |
+
console.log('supportsPointerEvents', supportsPointerEvents);
|
3242 |
+
|
3243 |
+
if (supportsPointerEvents && !mejs.MediaFeatures.isOpera) { // opera doesn't allow this :(
|
3244 |
+
|
3245 |
+
// allows clicking through the fullscreen button and controls down directly to Flash
|
3246 |
+
|
3247 |
+
/*
|
3248 |
+
When a user puts his mouse over the fullscreen button, the controls are disabled
|
3249 |
+
So we put a div over the video and another one on iether side of the fullscreen button
|
3250 |
+
that caputre mouse movement
|
3251 |
+
and restore the controls once the mouse moves outside of the fullscreen button
|
3252 |
+
*/
|
3253 |
+
|
3254 |
+
var fullscreenIsDisabled = false,
|
3255 |
+
restoreControls = function() {
|
3256 |
+
if (fullscreenIsDisabled) {
|
3257 |
+
// hide the hovers
|
3258 |
+
videoHoverDiv.hide();
|
3259 |
+
controlsLeftHoverDiv.hide();
|
3260 |
+
controlsRightHoverDiv.hide();
|
3261 |
+
|
3262 |
+
// restore the control bar
|
3263 |
+
fullscreenBtn.css('pointer-events', '');
|
3264 |
+
t.controls.css('pointer-events', '');
|
3265 |
+
|
3266 |
+
// store for later
|
3267 |
+
fullscreenIsDisabled = false;
|
3268 |
+
}
|
3269 |
+
},
|
3270 |
+
videoHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
|
3271 |
+
controlsLeftHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
|
3272 |
+
controlsRightHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
|
3273 |
+
positionHoverDivs = function() {
|
3274 |
+
var style = {position: 'absolute', top: 0, left: 0}; //, backgroundColor: '#f00'};
|
3275 |
+
videoHoverDiv.css(style);
|
3276 |
+
controlsLeftHoverDiv.css(style);
|
3277 |
+
controlsRightHoverDiv.css(style);
|
3278 |
+
|
3279 |
+
// over video, but not controls
|
3280 |
+
videoHoverDiv
|
3281 |
+
.width( t.container.width() )
|
3282 |
+
.height( t.container.height() - t.controls.height() );
|
3283 |
+
|
3284 |
+
// over controls, but not the fullscreen button
|
3285 |
+
var fullScreenBtnOffset = fullscreenBtn.offset().left - t.container.offset().left;
|
3286 |
+
fullScreenBtnWidth = fullscreenBtn.outerWidth(true);
|
3287 |
+
|
3288 |
+
controlsLeftHoverDiv
|
3289 |
+
.width( fullScreenBtnOffset )
|
3290 |
+
.height( t.controls.height() )
|
3291 |
+
.css({top: t.container.height() - t.controls.height()});
|
3292 |
+
|
3293 |
+
// after the fullscreen button
|
3294 |
+
controlsRightHoverDiv
|
3295 |
+
.width( t.container.width() - fullScreenBtnOffset - fullScreenBtnWidth )
|
3296 |
+
.height( t.controls.height() )
|
3297 |
+
.css({top: t.container.height() - t.controls.height(),
|
3298 |
+
left: fullScreenBtnOffset + fullScreenBtnWidth});
|
3299 |
+
};
|
3300 |
+
|
3301 |
+
$(document).resize(function() {
|
3302 |
+
positionHoverDivs();
|
3303 |
+
});
|
3304 |
+
|
3305 |
+
// on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash
|
3306 |
+
fullscreenBtn
|
3307 |
+
.mouseover(function() {
|
3308 |
+
|
3309 |
+
if (!t.isFullScreen) {
|
3310 |
+
|
3311 |
+
var buttonPos = fullscreenBtn.offset(),
|
3312 |
+
containerPos = player.container.offset();
|
3313 |
+
|
3314 |
+
// move the button in Flash into place
|
3315 |
+
media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, false);
|
3316 |
+
|
3317 |
+
// allows click through
|
3318 |
+
fullscreenBtn.css('pointer-events', 'none');
|
3319 |
+
t.controls.css('pointer-events', 'none');
|
3320 |
+
|
3321 |
+
// show the divs that will restore things
|
3322 |
+
videoHoverDiv.show();
|
3323 |
+
controlsRightHoverDiv.show();
|
3324 |
+
controlsLeftHoverDiv.show();
|
3325 |
+
positionHoverDivs();
|
3326 |
+
|
3327 |
+
fullscreenIsDisabled = true;
|
3328 |
+
}
|
3329 |
+
|
3330 |
+
});
|
3331 |
+
|
3332 |
+
// restore controls anytime the user enters or leaves fullscreen
|
3333 |
+
media.addEventListener('fullscreenchange', function(e) {
|
3334 |
+
restoreControls();
|
3335 |
+
});
|
3336 |
+
|
3337 |
+
|
3338 |
+
// the mouseout event doesn't work on the fullscren button, because we already killed the pointer-events
|
3339 |
+
// so we use the document.mousemove event to restore controls when the mouse moves outside the fullscreen button
|
3340 |
+
/*
|
3341 |
+
$(document).mousemove(function(e) {
|
3342 |
+
|
3343 |
+
// if the mouse is anywhere but the fullsceen button, then restore it all
|
3344 |
+
if (fullscreenIsDisabled) {
|
3345 |
+
|
3346 |
+
var fullscreenBtnPos = fullscreenBtn.offset();
|
3347 |
+
|
3348 |
+
|
3349 |
+
if (e.pageY < fullscreenBtnPos.top || e.pageY > fullscreenBtnPos.top + fullscreenBtn.outerHeight(true) ||
|
3350 |
+
e.pageX < fullscreenBtnPos.left || e.pageX > fullscreenBtnPos.left + fullscreenBtn.outerWidth(true)
|
3351 |
+
) {
|
3352 |
+
|
3353 |
+
fullscreenBtn.css('pointer-events', '');
|
3354 |
+
t.controls.css('pointer-events', '');
|
3355 |
+
|
3356 |
+
fullscreenIsDisabled = false;
|
3357 |
+
}
|
3358 |
+
}
|
3359 |
+
});
|
3360 |
+
*/
|
3361 |
+
|
3362 |
+
|
3363 |
+
} else {
|
3364 |
+
|
3365 |
+
// the hover state will show the fullscreen button in Flash to hover up and click
|
3366 |
+
|
3367 |
+
fullscreenBtn
|
3368 |
+
.mouseover(function() {
|
3369 |
+
|
3370 |
+
if (hideTimeout !== null) {
|
3371 |
+
clearTimeout(hideTimeout);
|
3372 |
+
delete hideTimeout;
|
3373 |
+
}
|
3374 |
+
|
3375 |
+
var buttonPos = fullscreenBtn.offset(),
|
3376 |
+
containerPos = player.container.offset();
|
3377 |
+
|
3378 |
+
media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, true);
|
3379 |
+
|
3380 |
+
})
|
3381 |
+
.mouseout(function() {
|
3382 |
+
|
3383 |
+
if (hideTimeout !== null) {
|
3384 |
+
clearTimeout(hideTimeout);
|
3385 |
+
delete hideTimeout;
|
3386 |
+
}
|
3387 |
+
|
3388 |
+
hideTimeout = setTimeout(function() {
|
3389 |
+
media.hideFullscreenButton();
|
3390 |
+
}, 1500);
|
3391 |
+
|
3392 |
+
|
3393 |
+
});
|
3394 |
+
}
|
3395 |
+
}
|
3396 |
+
|
3397 |
+
player.fullscreenBtn = fullscreenBtn;
|
3398 |
+
|
3399 |
+
$(document).bind('keydown',function (e) {
|
3400 |
+
if (((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen) && e.keyCode == 27) {
|
3401 |
+
player.exitFullScreen();
|
3402 |
+
}
|
3403 |
+
});
|
3404 |
+
|
3405 |
+
},
|
3406 |
+
enterFullScreen: function() {
|
3407 |
+
|
3408 |
+
var t = this;
|
3409 |
+
|
3410 |
+
// firefox+flash can't adjust plugin sizes without resetting :(
|
3411 |
+
if (t.media.pluginType !== 'native' && (mejs.MediaFeatures.isFirefox || t.options.usePluginFullScreen)) {
|
3412 |
+
//t.media.setFullscreen(true);
|
3413 |
+
//player.isFullScreen = true;
|
3414 |
+
return;
|
3415 |
+
}
|
3416 |
+
|
3417 |
+
// store overflow
|
3418 |
+
docStyleOverflow = document.documentElement.style.overflow;
|
3419 |
+
// set it to not show scroll bars so 100% will work
|
3420 |
+
document.documentElement.style.overflow = 'hidden';
|
3421 |
+
|
3422 |
+
// store sizing
|
3423 |
+
normalHeight = t.container.height();
|
3424 |
+
normalWidth = t.container.width();
|
3425 |
+
|
3426 |
+
// attempt to do true fullscreen (Safari 5.1 and Firefox Nightly only for now)
|
3427 |
+
if (t.media.pluginType === 'native') {
|
3428 |
+
if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
3429 |
+
|
3430 |
+
mejs.MediaFeatures.requestFullScreen(t.container[0]);
|
3431 |
+
//return;
|
3432 |
+
|
3433 |
+
if (t.isInIframe) {
|
3434 |
+
// sometimes exiting from fullscreen doesn't work
|
3435 |
+
// notably in Chrome <iframe>. Fixed in version 17
|
3436 |
+
setTimeout(function checkFullscreen() {
|
3437 |
+
|
3438 |
+
if (t.isNativeFullScreen) {
|
3439 |
+
|
3440 |
+
// check if the video is suddenly not really fullscreen
|
3441 |
+
if ($(window).width() !== screen.width) {
|
3442 |
+
// manually exit
|
3443 |
+
t.exitFullScreen();
|
3444 |
+
} else {
|
3445 |
+
// test again
|
3446 |
+
setTimeout(checkFullscreen, 500);
|
3447 |
+
}
|
3448 |
+
}
|
3449 |
+
|
3450 |
+
|
3451 |
+
}, 500);
|
3452 |
+
}
|
3453 |
+
|
3454 |
+
} else if (mejs.MediaFeatures.hasSemiNativeFullScreen) {
|
3455 |
+
t.media.webkitEnterFullscreen();
|
3456 |
+
return;
|
3457 |
+
}
|
3458 |
+
}
|
3459 |
+
|
3460 |
+
// check for iframe launch
|
3461 |
+
if (t.isInIframe) {
|
3462 |
+
var url = t.options.newWindowCallback(this);
|
3463 |
+
|
3464 |
+
|
3465 |
+
if (url !== '') {
|
3466 |
+
|
3467 |
+
// launch immediately
|
3468 |
+
if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
3469 |
+
t.pause();
|
3470 |
+
window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');
|
3471 |
+
return;
|
3472 |
+
} else {
|
3473 |
+
setTimeout(function() {
|
3474 |
+
if (!t.isNativeFullScreen) {
|
3475 |
+
t.pause();
|
3476 |
+
window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');
|
3477 |
+
}
|
3478 |
+
}, 250);
|
3479 |
+
}
|
3480 |
+
}
|
3481 |
+
|
3482 |
+
}
|
3483 |
+
|
3484 |
+
// full window code
|
3485 |
+
|
3486 |
+
|
3487 |
+
|
3488 |
+
// make full size
|
3489 |
+
t.container
|
3490 |
+
.addClass('mejs-container-fullscreen')
|
3491 |
+
.width('100%')
|
3492 |
+
.height('100%');
|
3493 |
+
//.css({position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, overflow: 'hidden', width: '100%', height: '100%', 'z-index': 1000});
|
3494 |
+
|
3495 |
+
// Only needed for safari 5.1 native full screen, can cause display issues elsewhere
|
3496 |
+
// Actually, it seems to be needed for IE8, too
|
3497 |
+
//if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
3498 |
+
setTimeout(function() {
|
3499 |
+
t.container.css({width: '100%', height: '100%'});
|
3500 |
+
t.setControlsSize();
|
3501 |
+
}, 500);
|
3502 |
+
//}
|
3503 |
+
|
3504 |
+
if (t.pluginType === 'native') {
|
3505 |
+
t.$media
|
3506 |
+
.width('100%')
|
3507 |
+
.height('100%');
|
3508 |
+
} else {
|
3509 |
+
t.container.find('object, embed, iframe')
|
3510 |
+
.width('100%')
|
3511 |
+
.height('100%');
|
3512 |
+
|
3513 |
+
//if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
3514 |
+
t.media.setVideoSize($(window).width(),$(window).height());
|
3515 |
+
//}
|
3516 |
+
}
|
3517 |
+
|
3518 |
+
t.layers.children('div')
|
3519 |
+
.width('100%')
|
3520 |
+
.height('100%');
|
3521 |
+
|
3522 |
+
if (t.fullscreenBtn) {
|
3523 |
+
t.fullscreenBtn
|
3524 |
+
.removeClass('mejs-fullscreen')
|
3525 |
+
.addClass('mejs-unfullscreen');
|
3526 |
+
}
|
3527 |
+
|
3528 |
+
t.setControlsSize();
|
3529 |
+
t.isFullScreen = true;
|
3530 |
+
},
|
3531 |
+
|
3532 |
+
exitFullScreen: function() {
|
3533 |
+
|
3534 |
+
var t = this;
|
3535 |
+
|
3536 |
+
// firefox can't adjust plugins
|
3537 |
+
if (t.media.pluginType !== 'native' && mejs.MediaFeatures.isFirefox) {
|
3538 |
+
t.media.setFullscreen(false);
|
3539 |
+
//player.isFullScreen = false;
|
3540 |
+
return;
|
3541 |
+
}
|
3542 |
+
|
3543 |
+
// come outo of native fullscreen
|
3544 |
+
if (mejs.MediaFeatures.hasTrueNativeFullScreen && (mejs.MediaFeatures.isFullScreen() || t.isFullScreen)) {
|
3545 |
+
mejs.MediaFeatures.cancelFullScreen();
|
3546 |
+
}
|
3547 |
+
|
3548 |
+
// restore scroll bars to document
|
3549 |
+
document.documentElement.style.overflow = docStyleOverflow;
|
3550 |
+
|
3551 |
+
t.container
|
3552 |
+
.removeClass('mejs-container-fullscreen')
|
3553 |
+
.width(normalWidth)
|
3554 |
+
.height(normalHeight);
|
3555 |
+
//.css({position: '', left: '', top: '', right: '', bottom: '', overflow: 'inherit', width: normalWidth + 'px', height: normalHeight + 'px', 'z-index': 1});
|
3556 |
+
|
3557 |
+
if (t.pluginType === 'native') {
|
3558 |
+
t.$media
|
3559 |
+
.width(normalWidth)
|
3560 |
+
.height(normalHeight);
|
3561 |
+
} else {
|
3562 |
+
t.container.find('object embed')
|
3563 |
+
.width(normalWidth)
|
3564 |
+
.height(normalHeight);
|
3565 |
+
|
3566 |
+
t.media.setVideoSize(normalWidth, normalHeight);
|
3567 |
+
}
|
3568 |
+
|
3569 |
+
t.layers.children('div')
|
3570 |
+
.width(normalWidth)
|
3571 |
+
.height(normalHeight);
|
3572 |
+
|
3573 |
+
t.fullscreenBtn
|
3574 |
+
.removeClass('mejs-unfullscreen')
|
3575 |
+
.addClass('mejs-fullscreen');
|
3576 |
+
|
3577 |
+
t.setControlsSize();
|
3578 |
+
t.isFullScreen = false;
|
3579 |
+
}
|
3580 |
+
});
|
3581 |
+
|
3582 |
+
})(mejs.$);
|
3583 |
+
|
3584 |
+
(function($) {
|
3585 |
+
|
3586 |
+
// add extra default options
|
3587 |
+
$.extend(mejs.MepDefaults, {
|
3588 |
+
// this will automatically turn on a <track>
|
3589 |
+
startLanguage: '',
|
3590 |
+
|
3591 |
+
tracksText: 'Captions/Subtitles'
|
3592 |
+
});
|
3593 |
+
|
3594 |
+
$.extend(MediaElementPlayer.prototype, {
|
3595 |
+
|
3596 |
+
hasChapters: false,
|
3597 |
+
|
3598 |
+
buildtracks: function(player, controls, layers, media) {
|
3599 |
+
if (!player.isVideo)
|
3600 |
+
return;
|
3601 |
+
|
3602 |
+
if (player.tracks.length == 0)
|
3603 |
+
return;
|
3604 |
+
|
3605 |
+
var t= this, i, options = '';
|
3606 |
+
|
3607 |
+
player.chapters =
|
3608 |
+
$('<div class="mejs-chapters mejs-layer"></div>')
|
3609 |
+
.prependTo(layers).hide();
|
3610 |
+
player.captions =
|
3611 |
+
$('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position"><span class="mejs-captions-text"></span></div></div>')
|
3612 |
+
.prependTo(layers).hide();
|
3613 |
+
player.captionsText = player.captions.find('.mejs-captions-text');
|
3614 |
+
player.captionsButton =
|
3615 |
+
$('<div class="mejs-button mejs-captions-button">'+
|
3616 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.tracksText + '"></button>'+
|
3617 |
+
'<div class="mejs-captions-selector">'+
|
3618 |
+
'<ul>'+
|
3619 |
+
'<li>'+
|
3620 |
+
'<input type="radio" name="' + player.id + '_captions" id="' + player.id + '_captions_none" value="none" checked="checked" />' +
|
3621 |
+
'<label for="' + player.id + '_captions_none">None</label>'+
|
3622 |
+
'</li>' +
|
3623 |
+
'</ul>'+
|
3624 |
+
'</div>'+
|
3625 |
+
'</div>')
|
3626 |
+
.appendTo(controls)
|
3627 |
+
|
3628 |
+
// hover
|
3629 |
+
.hover(function() {
|
3630 |
+
$(this).find('.mejs-captions-selector').css('visibility','visible');
|
3631 |
+
}, function() {
|
3632 |
+
$(this).find('.mejs-captions-selector').css('visibility','hidden');
|
3633 |
+
})
|
3634 |
+
|
3635 |
+
// handle clicks to the language radio buttons
|
3636 |
+
.delegate('input[type=radio]','click',function() {
|
3637 |
+
lang = this.value;
|
3638 |
+
|
3639 |
+
if (lang == 'none') {
|
3640 |
+
player.selectedTrack = null;
|
3641 |
+
} else {
|
3642 |
+
for (i=0; i<player.tracks.length; i++) {
|
3643 |
+
if (player.tracks[i].srclang == lang) {
|
3644 |
+
player.selectedTrack = player.tracks[i];
|
3645 |
+
player.captions.attr('lang', player.selectedTrack.srclang);
|
3646 |
+
player.displayCaptions();
|
3647 |
+
break;
|
3648 |
+
}
|
3649 |
+
}
|
3650 |
+
}
|
3651 |
+
});
|
3652 |
+
//.bind('mouseenter', function() {
|
3653 |
+
// player.captionsButton.find('.mejs-captions-selector').css('visibility','visible')
|
3654 |
+
//});
|
3655 |
+
|
3656 |
+
if (!player.options.alwaysShowControls) {
|
3657 |
+
// move with controls
|
3658 |
+
player.container
|
3659 |
+
.bind('mouseenter', function () {
|
3660 |
+
// push captions above controls
|
3661 |
+
player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
|
3662 |
+
|
3663 |
+
})
|
3664 |
+
.bind('mouseleave', function () {
|
3665 |
+
if (!media.paused) {
|
3666 |
+
// move back to normal place
|
3667 |
+
player.container.find('.mejs-captions-position').removeClass('mejs-captions-position-hover');
|
3668 |
+
}
|
3669 |
+
});
|
3670 |
+
} else {
|
3671 |
+
player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
|
3672 |
+
}
|
3673 |
+
|
3674 |
+
player.trackToLoad = -1;
|
3675 |
+
player.selectedTrack = null;
|
3676 |
+
player.isLoadingTrack = false;
|
3677 |
+
|
3678 |
+
|
3679 |
+
|
3680 |
+
// add to list
|
3681 |
+
for (i=0; i<player.tracks.length; i++) {
|
3682 |
+
if (player.tracks[i].kind == 'subtitles') {
|
3683 |
+
player.addTrackButton(player.tracks[i].srclang, player.tracks[i].label);
|
3684 |
+
}
|
3685 |
+
}
|
3686 |
+
|
3687 |
+
player.loadNextTrack();
|
3688 |
+
|
3689 |
+
|
3690 |
+
media.addEventListener('timeupdate',function(e) {
|
3691 |
+
player.displayCaptions();
|
3692 |
+
}, false);
|
3693 |
+
|
3694 |
+
media.addEventListener('loadedmetadata', function(e) {
|
3695 |
+
player.displayChapters();
|
3696 |
+
}, false);
|
3697 |
+
|
3698 |
+
player.container.hover(
|
3699 |
+
function () {
|
3700 |
+
// chapters
|
3701 |
+
if (player.hasChapters) {
|
3702 |
+
player.chapters.css('visibility','visible');
|
3703 |
+
player.chapters.fadeIn(200).height(player.chapters.find('.mejs-chapter').outerHeight());
|
3704 |
+
}
|
3705 |
+
},
|
3706 |
+
function () {
|
3707 |
+
if (player.hasChapters && !media.paused) {
|
3708 |
+
player.chapters.fadeOut(200, function() {
|
3709 |
+
$(this).css('visibility','hidden');
|
3710 |
+
$(this).css('display','block');
|
3711 |
+
});
|
3712 |
+
}
|
3713 |
+
});
|
3714 |
+
|
3715 |
+
// check for autoplay
|
3716 |
+
if (player.node.getAttribute('autoplay') !== null) {
|
3717 |
+
player.chapters.css('visibility','hidden');
|
3718 |
+
}
|
3719 |
+
},
|
3720 |
+
|
3721 |
+
loadNextTrack: function() {
|
3722 |
+
var t = this;
|
3723 |
+
|
3724 |
+
t.trackToLoad++;
|
3725 |
+
if (t.trackToLoad < t.tracks.length) {
|
3726 |
+
t.isLoadingTrack = true;
|
3727 |
+
t.loadTrack(t.trackToLoad);
|
3728 |
+
} else {
|
3729 |
+
// add done?
|
3730 |
+
t.isLoadingTrack = false;
|
3731 |
+
}
|
3732 |
+
},
|
3733 |
+
|
3734 |
+
loadTrack: function(index){
|
3735 |
+
var
|
3736 |
+
t = this,
|
3737 |
+
track = t.tracks[index],
|
3738 |
+
after = function() {
|
3739 |
+
|
3740 |
+
track.isLoaded = true;
|
3741 |
+
|
3742 |
+
// create button
|
3743 |
+
//t.addTrackButton(track.srclang);
|
3744 |
+
t.enableTrackButton(track.srclang, track.label);
|
3745 |
+
|
3746 |
+
t.loadNextTrack();
|
3747 |
+
|
3748 |
+
};
|
3749 |
+
|
3750 |
+
if (track.isTranslation) {
|
3751 |
+
|
3752 |
+
// translate the first track
|
3753 |
+
mejs.TrackFormatParser.translateTrackText(t.tracks[0].entries, t.tracks[0].srclang, track.srclang, t.options.googleApiKey, function(newOne) {
|
3754 |
+
|
3755 |
+
// store the new translation
|
3756 |
+
track.entries = newOne;
|
3757 |
+
|
3758 |
+
after();
|
3759 |
+
});
|
3760 |
+
|
3761 |
+
} else {
|
3762 |
+
$.ajax({
|
3763 |
+
url: track.src,
|
3764 |
+
success: function(d) {
|
3765 |
+
|
3766 |
+
// parse the loaded file
|
3767 |
+
track.entries = mejs.TrackFormatParser.parse(d);
|
3768 |
+
after();
|
3769 |
+
|
3770 |
+
if (track.kind == 'chapters' && t.media.duration > 0) {
|
3771 |
+
t.drawChapters(track);
|
3772 |
+
}
|
3773 |
+
},
|
3774 |
+
error: function() {
|
3775 |
+
t.loadNextTrack();
|
3776 |
+
}
|
3777 |
+
});
|
3778 |
+
}
|
3779 |
+
},
|
3780 |
+
|
3781 |
+
enableTrackButton: function(lang, label) {
|
3782 |
+
var t = this;
|
3783 |
+
|
3784 |
+
if (label === '') {
|
3785 |
+
label = mejs.language.codes[lang] || lang;
|
3786 |
+
}
|
3787 |
+
|
3788 |
+
t.captionsButton
|
3789 |
+
.find('input[value=' + lang + ']')
|
3790 |
+
.prop('disabled',false)
|
3791 |
+
.siblings('label')
|
3792 |
+
.html( label );
|
3793 |
+
|
3794 |
+
// auto select
|
3795 |
+
if (t.options.startLanguage == lang) {
|
3796 |
+
$('#' + t.id + '_captions_' + lang).click();
|
3797 |
+
}
|
3798 |
+
|
3799 |
+
t.adjustLanguageBox();
|
3800 |
+
},
|
3801 |
+
|
3802 |
+
addTrackButton: function(lang, label) {
|
3803 |
+
var t = this;
|
3804 |
+
if (label === '') {
|
3805 |
+
label = mejs.language.codes[lang] || lang;
|
3806 |
+
}
|
3807 |
+
|
3808 |
+
t.captionsButton.find('ul').append(
|
3809 |
+
$('<li>'+
|
3810 |
+
'<input type="radio" name="' + t.id + '_captions" id="' + t.id + '_captions_' + lang + '" value="' + lang + '" disabled="disabled" />' +
|
3811 |
+
'<label for="' + t.id + '_captions_' + lang + '">' + label + ' (loading)' + '</label>'+
|
3812 |
+
'</li>')
|
3813 |
+
);
|
3814 |
+
|
3815 |
+
t.adjustLanguageBox();
|
3816 |
+
|
3817 |
+
// remove this from the dropdownlist (if it exists)
|
3818 |
+
t.container.find('.mejs-captions-translations option[value=' + lang + ']').remove();
|
3819 |
+
},
|
3820 |
+
|
3821 |
+
adjustLanguageBox:function() {
|
3822 |
+
var t = this;
|
3823 |
+
// adjust the size of the outer box
|
3824 |
+
t.captionsButton.find('.mejs-captions-selector').height(
|
3825 |
+
t.captionsButton.find('.mejs-captions-selector ul').outerHeight(true) +
|
3826 |
+
t.captionsButton.find('.mejs-captions-translations').outerHeight(true)
|
3827 |
+
);
|
3828 |
+
},
|
3829 |
+
|
3830 |
+
displayCaptions: function() {
|
3831 |
+
|
3832 |
+
if (typeof this.tracks == 'undefined')
|
3833 |
+
return;
|
3834 |
+
|
3835 |
+
var
|
3836 |
+
t = this,
|
3837 |
+
i,
|
3838 |
+
track = t.selectedTrack;
|
3839 |
+
|
3840 |
+
if (track != null && track.isLoaded) {
|
3841 |
+
for (i=0; i<track.entries.times.length; i++) {
|
3842 |
+
if (t.media.currentTime >= track.entries.times[i].start && t.media.currentTime <= track.entries.times[i].stop){
|
3843 |
+
t.captionsText.html(track.entries.text[i]);
|
3844 |
+
t.captions.show().height(0);
|
3845 |
+
return; // exit out if one is visible;
|
3846 |
+
}
|
3847 |
+
}
|
3848 |
+
t.captions.hide();
|
3849 |
+
} else {
|
3850 |
+
t.captions.hide();
|
3851 |
+
}
|
3852 |
+
},
|
3853 |
+
|
3854 |
+
displayChapters: function() {
|
3855 |
+
var
|
3856 |
+
t = this,
|
3857 |
+
i;
|
3858 |
+
|
3859 |
+
for (i=0; i<t.tracks.length; i++) {
|
3860 |
+
if (t.tracks[i].kind == 'chapters' && t.tracks[i].isLoaded) {
|
3861 |
+
t.drawChapters(t.tracks[i]);
|
3862 |
+
t.hasChapters = true;
|
3863 |
+
break;
|
3864 |
+
}
|
3865 |
+
}
|
3866 |
+
},
|
3867 |
+
|
3868 |
+
drawChapters: function(chapters) {
|
3869 |
+
var
|
3870 |
+
t = this,
|
3871 |
+
i,
|
3872 |
+
dur,
|
3873 |
+
//width,
|
3874 |
+
//left,
|
3875 |
+
percent = 0,
|
3876 |
+
usedPercent = 0;
|
3877 |
+
|
3878 |
+
t.chapters.empty();
|
3879 |
+
|
3880 |
+
for (i=0; i<chapters.entries.times.length; i++) {
|
3881 |
+
dur = chapters.entries.times[i].stop - chapters.entries.times[i].start;
|
3882 |
+
percent = Math.floor(dur / t.media.duration * 100);
|
3883 |
+
if (percent + usedPercent > 100 || // too large
|
3884 |
+
i == chapters.entries.times.length-1 && percent + usedPercent < 100) // not going to fill it in
|
3885 |
+
{
|
3886 |
+
percent = 100 - usedPercent;
|
3887 |
+
}
|
3888 |
+
//width = Math.floor(t.width * dur / t.media.duration);
|
3889 |
+
//left = Math.floor(t.width * chapters.entries.times[i].start / t.media.duration);
|
3890 |
+
//if (left + width > t.width) {
|
3891 |
+
// width = t.width - left;
|
3892 |
+
//}
|
3893 |
+
|
3894 |
+
t.chapters.append( $(
|
3895 |
+
'<div class="mejs-chapter" rel="' + chapters.entries.times[i].start + '" style="left: ' + usedPercent.toString() + '%;width: ' + percent.toString() + '%;">' +
|
3896 |
+
'<div class="mejs-chapter-block' + ((i==chapters.entries.times.length-1) ? ' mejs-chapter-block-last' : '') + '">' +
|
3897 |
+
'<span class="ch-title">' + chapters.entries.text[i] + '</span>' +
|
3898 |
+
'<span class="ch-time">' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].start) + '–' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' +
|
3899 |
+
'</div>' +
|
3900 |
+
'</div>'));
|
3901 |
+
usedPercent += percent;
|
3902 |
+
}
|
3903 |
+
|
3904 |
+
t.chapters.find('div.mejs-chapter').click(function() {
|
3905 |
+
t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) );
|
3906 |
+
if (t.media.paused) {
|
3907 |
+
t.media.play();
|
3908 |
+
}
|
3909 |
+
});
|
3910 |
+
|
3911 |
+
t.chapters.show();
|
3912 |
+
}
|
3913 |
+
});
|
3914 |
+
|
3915 |
+
|
3916 |
+
|
3917 |
+
mejs.language = {
|
3918 |
+
codes: {
|
3919 |
+
af:'Afrikaans',
|
3920 |
+
sq:'Albanian',
|
3921 |
+
ar:'Arabic',
|
3922 |
+
be:'Belarusian',
|
3923 |
+
bg:'Bulgarian',
|
3924 |
+
ca:'Catalan',
|
3925 |
+
zh:'Chinese',
|
3926 |
+
'zh-cn':'Chinese Simplified',
|
3927 |
+
'zh-tw':'Chinese Traditional',
|
3928 |
+
hr:'Croatian',
|
3929 |
+
cs:'Czech',
|
3930 |
+
da:'Danish',
|
3931 |
+
nl:'Dutch',
|
3932 |
+
en:'English',
|
3933 |
+
et:'Estonian',
|
3934 |
+
tl:'Filipino',
|
3935 |
+
fi:'Finnish',
|
3936 |
+
fr:'French',
|
3937 |
+
gl:'Galician',
|
3938 |
+
de:'German',
|
3939 |
+
el:'Greek',
|
3940 |
+
ht:'Haitian Creole',
|
3941 |
+
iw:'Hebrew',
|
3942 |
+
hi:'Hindi',
|
3943 |
+
hu:'Hungarian',
|
3944 |
+
is:'Icelandic',
|
3945 |
+
id:'Indonesian',
|
3946 |
+
ga:'Irish',
|
3947 |
+
it:'Italian',
|
3948 |
+
ja:'Japanese',
|
3949 |
+
ko:'Korean',
|
3950 |
+
lv:'Latvian',
|
3951 |
+
lt:'Lithuanian',
|
3952 |
+
mk:'Macedonian',
|
3953 |
+
ms:'Malay',
|
3954 |
+
mt:'Maltese',
|
3955 |
+
no:'Norwegian',
|
3956 |
+
fa:'Persian',
|
3957 |
+
pl:'Polish',
|
3958 |
+
pt:'Portuguese',
|
3959 |
+
//'pt-pt':'Portuguese (Portugal)',
|
3960 |
+
ro:'Romanian',
|
3961 |
+
ru:'Russian',
|
3962 |
+
sr:'Serbian',
|
3963 |
+
sk:'Slovak',
|
3964 |
+
sl:'Slovenian',
|
3965 |
+
es:'Spanish',
|
3966 |
+
sw:'Swahili',
|
3967 |
+
sv:'Swedish',
|
3968 |
+
tl:'Tagalog',
|
3969 |
+
th:'Thai',
|
3970 |
+
tr:'Turkish',
|
3971 |
+
uk:'Ukrainian',
|
3972 |
+
vi:'Vietnamese',
|
3973 |
+
cy:'Welsh',
|
3974 |
+
yi:'Yiddish'
|
3975 |
+
}
|
3976 |
+
};
|
3977 |
+
|
3978 |
+
/*
|
3979 |
+
Parses WebVVT format which should be formatted as
|
3980 |
+
================================
|
3981 |
+
WEBVTT
|
3982 |
+
|
3983 |
+
1
|
3984 |
+
00:00:01,1 --> 00:00:05,000
|
3985 |
+
A line of text
|
3986 |
+
|
3987 |
+
2
|
3988 |
+
00:01:15,1 --> 00:02:05,000
|
3989 |
+
A second line of text
|
3990 |
+
|
3991 |
+
===============================
|
3992 |
+
|
3993 |
+
Adapted from: http://www.delphiki.com/html5/playr
|
3994 |
+
*/
|
3995 |
+
mejs.TrackFormatParser = {
|
3996 |
+
// match start "chapter-" (or anythingelse)
|
3997 |
+
pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/,
|
3998 |
+
pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/,
|
3999 |
+
|
4000 |
+
split2: function (text, regex) {
|
4001 |
+
// normal version for compliant browsers
|
4002 |
+
// see below for IE fix
|
4003 |
+
return text.split(regex);
|
4004 |
+
},
|
4005 |
+
parse: function(trackText) {
|
4006 |
+
var
|
4007 |
+
i = 0,
|
4008 |
+
lines = this.split2(trackText, /\r?\n/),
|
4009 |
+
entries = {text:[], times:[]},
|
4010 |
+
timecode,
|
4011 |
+
text;
|
4012 |
+
|
4013 |
+
for(; i<lines.length; i++) {
|
4014 |
+
// check for the line number
|
4015 |
+
if (this.pattern_identifier.exec(lines[i])){
|
4016 |
+
// skip to the next line where the start --> end time code should be
|
4017 |
+
i++;
|
4018 |
+
timecode = this.pattern_timecode.exec(lines[i]);
|
4019 |
+
|
4020 |
+
if (timecode && i<lines.length){
|
4021 |
+
i++;
|
4022 |
+
// grab all the (possibly multi-line) text that follows
|
4023 |
+
text = lines[i];
|
4024 |
+
i++;
|
4025 |
+
while(lines[i] !== '' && i<lines.length){
|
4026 |
+
text = text + '\n' + lines[i];
|
4027 |
+
i++;
|
4028 |
+
}
|
4029 |
+
|
4030 |
+
// Text is in a different array so I can use .join
|
4031 |
+
entries.text.push(text);
|
4032 |
+
entries.times.push(
|
4033 |
+
{
|
4034 |
+
start: mejs.Utility.timeCodeToSeconds(timecode[1]),
|
4035 |
+
stop: mejs.Utility.timeCodeToSeconds(timecode[3]),
|
4036 |
+
settings: timecode[5]
|
4037 |
+
});
|
4038 |
+
}
|
4039 |
+
}
|
4040 |
+
}
|
4041 |
+
|
4042 |
+
return entries;
|
4043 |
+
}
|
4044 |
+
};
|
4045 |
+
|
4046 |
+
// test for browsers with bad String.split method.
|
4047 |
+
if ('x\n\ny'.split(/\n/gi).length != 3) {
|
4048 |
+
// add super slow IE8 and below version
|
4049 |
+
mejs.TrackFormatParser.split2 = function(text, regex) {
|
4050 |
+
var
|
4051 |
+
parts = [],
|
4052 |
+
chunk = '',
|
4053 |
+
i;
|
4054 |
+
|
4055 |
+
for (i=0; i<text.length; i++) {
|
4056 |
+
chunk += text.substring(i,i+1);
|
4057 |
+
if (regex.test(chunk)) {
|
4058 |
+
parts.push(chunk.replace(regex, ''));
|
4059 |
+
chunk = '';
|
4060 |
+
}
|
4061 |
+
}
|
4062 |
+
parts.push(chunk);
|
4063 |
+
return parts;
|
4064 |
+
}
|
4065 |
+
}
|
4066 |
+
|
4067 |
+
})(mejs.$);
|
4068 |
+
|
4069 |
+
/*
|
4070 |
+
* ContextMenu Plugin
|
4071 |
+
*
|
4072 |
+
*
|
4073 |
+
*/
|
4074 |
+
|
4075 |
+
(function($) {
|
4076 |
+
|
4077 |
+
$.extend(mejs.MepDefaults,
|
4078 |
+
{ 'contextMenuItems': [
|
4079 |
+
// demo of a fullscreen option
|
4080 |
+
{
|
4081 |
+
render: function(player) {
|
4082 |
+
|
4083 |
+
// check for fullscreen plugin
|
4084 |
+
if (typeof player.enterFullScreen == 'undefined')
|
4085 |
+
return null;
|
4086 |
+
|
4087 |
+
if (player.isFullScreen) {
|
4088 |
+
return "Turn off Fullscreen";
|
4089 |
+
} else {
|
4090 |
+
return "Go Fullscreen";
|
4091 |
+
}
|
4092 |
+
},
|
4093 |
+
click: function(player) {
|
4094 |
+
if (player.isFullScreen) {
|
4095 |
+
player.exitFullScreen();
|
4096 |
+
} else {
|
4097 |
+
player.enterFullScreen();
|
4098 |
+
}
|
4099 |
+
}
|
4100 |
+
}
|
4101 |
+
,
|
4102 |
+
// demo of a mute/unmute button
|
4103 |
+
{
|
4104 |
+
render: function(player) {
|
4105 |
+
if (player.media.muted) {
|
4106 |
+
return "Unmute";
|
4107 |
+
} else {
|
4108 |
+
return "Mute";
|
4109 |
+
}
|
4110 |
+
},
|
4111 |
+
click: function(player) {
|
4112 |
+
if (player.media.muted) {
|
4113 |
+
player.setMuted(false);
|
4114 |
+
} else {
|
4115 |
+
player.setMuted(true);
|
4116 |
+
}
|
4117 |
+
}
|
4118 |
+
},
|
4119 |
+
// separator
|
4120 |
+
{
|
4121 |
+
isSeparator: true
|
4122 |
+
}
|
4123 |
+
,
|
4124 |
+
// demo of simple download video
|
4125 |
+
{
|
4126 |
+
render: function(player) {
|
4127 |
+
return "Download Video";
|
4128 |
+
},
|
4129 |
+
click: function(player) {
|
4130 |
+
window.location.href = player.media.currentSrc;
|
4131 |
+
}
|
4132 |
+
}
|
4133 |
+
]}
|
4134 |
+
);
|
4135 |
+
|
4136 |
+
|
4137 |
+
$.extend(MediaElementPlayer.prototype, {
|
4138 |
+
buildcontextmenu: function(player, controls, layers, media) {
|
4139 |
+
|
4140 |
+
// create context menu
|
4141 |
+
player.contextMenu = $('<div class="mejs-contextmenu"></div>')
|
4142 |
+
.appendTo($('body'))
|
4143 |
+
.hide();
|
4144 |
+
|
4145 |
+
// create events for showing context menu
|
4146 |
+
player.container.bind('contextmenu', function(e) {
|
4147 |
+
if (player.isContextMenuEnabled) {
|
4148 |
+
e.preventDefault();
|
4149 |
+
player.renderContextMenu(e.clientX-1, e.clientY-1);
|
4150 |
+
return false;
|
4151 |
+
}
|
4152 |
+
});
|
4153 |
+
player.container.bind('click', function() {
|
4154 |
+
player.contextMenu.hide();
|
4155 |
+
});
|
4156 |
+
player.contextMenu.bind('mouseleave', function() {
|
4157 |
+
|
4158 |
+
//console.log('context hover out');
|
4159 |
+
player.startContextMenuTimer();
|
4160 |
+
|
4161 |
+
});
|
4162 |
+
},
|
4163 |
+
|
4164 |
+
isContextMenuEnabled: true,
|
4165 |
+
enableContextMenu: function() {
|
4166 |
+
this.isContextMenuEnabled = true;
|
4167 |
+
},
|
4168 |
+
disableContextMenu: function() {
|
4169 |
+
this.isContextMenuEnabled = false;
|
4170 |
+
},
|
4171 |
+
|
4172 |
+
contextMenuTimeout: null,
|
4173 |
+
startContextMenuTimer: function() {
|
4174 |
+
//console.log('startContextMenuTimer');
|
4175 |
+
|
4176 |
+
var t = this;
|
4177 |
+
|
4178 |
+
t.killContextMenuTimer();
|
4179 |
+
|
4180 |
+
t.contextMenuTimer = setTimeout(function() {
|
4181 |
+
t.hideContextMenu();
|
4182 |
+
t.killContextMenuTimer();
|
4183 |
+
}, 750);
|
4184 |
+
},
|
4185 |
+
killContextMenuTimer: function() {
|
4186 |
+
var timer = this.contextMenuTimer;
|
4187 |
+
|
4188 |
+
//console.log('killContextMenuTimer', timer);
|
4189 |
+
|
4190 |
+
if (timer != null) {
|
4191 |
+
clearTimeout(timer);
|
4192 |
+
delete timer;
|
4193 |
+
timer = null;
|
4194 |
+
}
|
4195 |
+
},
|
4196 |
+
|
4197 |
+
hideContextMenu: function() {
|
4198 |
+
this.contextMenu.hide();
|
4199 |
+
},
|
4200 |
+
|
4201 |
+
renderContextMenu: function(x,y) {
|
4202 |
+
|
4203 |
+
// alway re-render the items so that things like "turn fullscreen on" and "turn fullscreen off" are always written correctly
|
4204 |
+
var t = this,
|
4205 |
+
html = '',
|
4206 |
+
items = t.options.contextMenuItems;
|
4207 |
+
|
4208 |
+
for (var i=0, il=items.length; i<il; i++) {
|
4209 |
+
|
4210 |
+
if (items[i].isSeparator) {
|
4211 |
+
html += '<div class="mejs-contextmenu-separator"></div>';
|
4212 |
+
} else {
|
4213 |
+
|
4214 |
+
var rendered = items[i].render(t);
|
4215 |
+
|
4216 |
+
// render can return null if the item doesn't need to be used at the moment
|
4217 |
+
if (rendered != null) {
|
4218 |
+
html += '<div class="mejs-contextmenu-item" data-itemindex="' + i + '" id="element-' + (Math.random()*1000000) + '">' + rendered + '</div>';
|
4219 |
+
}
|
4220 |
+
}
|
4221 |
+
}
|
4222 |
+
|
4223 |
+
// position and show the context menu
|
4224 |
+
t.contextMenu
|
4225 |
+
.empty()
|
4226 |
+
.append($(html))
|
4227 |
+
.css({top:y, left:x})
|
4228 |
+
.show();
|
4229 |
+
|
4230 |
+
// bind events
|
4231 |
+
t.contextMenu.find('.mejs-contextmenu-item').each(function() {
|
4232 |
+
|
4233 |
+
// which one is this?
|
4234 |
+
var $dom = $(this),
|
4235 |
+
itemIndex = parseInt( $dom.data('itemindex'), 10 ),
|
4236 |
+
item = t.options.contextMenuItems[itemIndex];
|
4237 |
+
|
4238 |
+
// bind extra functionality?
|
4239 |
+
if (typeof item.show != 'undefined')
|
4240 |
+
item.show( $dom , t);
|
4241 |
+
|
4242 |
+
// bind click action
|
4243 |
+
$dom.click(function() {
|
4244 |
+
// perform click action
|
4245 |
+
if (typeof item.click != 'undefined')
|
4246 |
+
item.click(t);
|
4247 |
+
|
4248 |
+
// close
|
4249 |
+
t.contextMenu.hide();
|
4250 |
+
});
|
4251 |
+
});
|
4252 |
+
|
4253 |
+
// stop the controls from hiding
|
4254 |
+
setTimeout(function() {
|
4255 |
+
t.killControlsTimer('rev3');
|
4256 |
+
}, 100);
|
4257 |
+
|
4258 |
+
}
|
4259 |
+
});
|
4260 |
+
|
4261 |
+
})(mejs.$);
|
4262 |
+
|
includes/media-element/mediaelement-and-player.min.js
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* MediaElement.js
|
3 |
+
* HTML5 <video> and <audio> shim and player
|
4 |
+
* http://mediaelementjs.com/
|
5 |
+
*
|
6 |
+
* Creates a JavaScript object that mimics HTML5 MediaElement API
|
7 |
+
* for browsers that don't understand HTML5 or can't play the provided codec
|
8 |
+
* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
|
9 |
+
*
|
10 |
+
* Copyright 2010-2012, John Dyer (http://j.hn)
|
11 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
12 |
+
*
|
13 |
+
*/var mejs=mejs||{};mejs.version="2.9.1";mejs.meIndex=0;mejs.plugins={silverlight:[{version:[3,0],types:["video/mp4","video/m4v","video/mov","video/wmv","audio/wma","audio/m4a","audio/mp3","audio/wav","audio/mpeg"]}],flash:[{version:[9,0,124],types:["video/mp4","video/m4v","video/mov","video/flv","video/x-flv","audio/flv","audio/x-flv","audio/mp3","audio/m4a","audio/mpeg","video/youtube","video/x-youtube"]}],youtube:[{version:null,types:["video/youtube","video/x-youtube"]}],vimeo:[{version:null,types:["video/vimeo"]}]};
|
14 |
+
mejs.Utility={encodeUrl:function(a){return encodeURIComponent(a)},escapeHTML:function(a){return a.toString().split("&").join("&").split("<").join("<").split('"').join(""")},absolutizeUrl:function(a){var b=document.createElement("div");b.innerHTML='<a href="'+this.escapeHTML(a)+'">x</a>';return b.firstChild.href},getScriptPath:function(a){for(var b=0,c,d="",e="",g,f=document.getElementsByTagName("script"),j=f.length,h=a.length;b<j;b++){g=f[b].src;for(c=0;c<h;c++){e=a[c];if(g.indexOf(e)>
|
15 |
+
-1){d=g.substring(0,g.indexOf(e));break}}if(d!=="")break}return d},secondsToTimeCode:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;var e=Math.floor(a/3600)%24,g=Math.floor(a/60)%60,f=Math.floor(a%60);a=Math.floor((a%1*d).toFixed(3));return(b||e>0?(e<10?"0"+e:e)+":":"")+(g<10?"0"+g:g)+":"+(f<10?"0"+f:f)+(c?":"+(a<10?"0"+a:a):"")},timeCodeToSeconds:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;a=a.split(":");b=parseInt(a[0],
|
16 |
+
10);var e=parseInt(a[1],10),g=parseInt(a[2],10),f=0,j=0;if(c)f=parseInt(a[3])/d;return j=b*3600+e*60+g+f},removeSwf:function(a){var b=document.getElementById(a);if(b&&b.nodeName=="OBJECT")if(mejs.MediaFeatures.isIE){b.style.display="none";(function(){b.readyState==4?mejs.Utility.removeObjectInIE(a):setTimeout(arguments.callee,10)})()}else b.parentNode.removeChild(b)},removeObjectInIE:function(a){if(a=document.getElementById(a)){for(var b in a)if(typeof a[b]=="function")a[b]=null;a.parentNode.removeChild(a)}}};
|
17 |
+
mejs.PluginDetector={hasPluginVersion:function(a,b){var c=this.plugins[a];b[1]=b[1]||0;b[2]=b[2]||0;return c[0]>b[0]||c[0]==b[0]&&c[1]>b[1]||c[0]==b[0]&&c[1]==b[1]&&c[2]>=b[2]?true:false},nav:window.navigator,ua:window.navigator.userAgent.toLowerCase(),plugins:[],addPlugin:function(a,b,c,d,e){this.plugins[a]=this.detectPlugin(b,c,d,e)},detectPlugin:function(a,b,c,d){var e=[0,0,0],g;if(typeof this.nav.plugins!="undefined"&&typeof this.nav.plugins[a]=="object"){if((c=this.nav.plugins[a].description)&&
|
18 |
+
!(typeof this.nav.mimeTypes!="undefined"&&this.nav.mimeTypes[b]&&!this.nav.mimeTypes[b].enabledPlugin)){e=c.replace(a,"").replace(/^\s+/,"").replace(/\sr/gi,".").split(".");for(a=0;a<e.length;a++)e[a]=parseInt(e[a].match(/\d+/),10)}}else if(typeof window.ActiveXObject!="undefined")try{if(g=new ActiveXObject(c))e=d(g)}catch(f){}return e}};
|
19 |
+
mejs.PluginDetector.addPlugin("flash","Shockwave Flash","application/x-shockwave-flash","ShockwaveFlash.ShockwaveFlash",function(a){var b=[];if(a=a.GetVariable("$version")){a=a.split(" ")[1].split(",");b=[parseInt(a[0],10),parseInt(a[1],10),parseInt(a[2],10)]}return b});
|
20 |
+
mejs.PluginDetector.addPlugin("silverlight","Silverlight Plug-In","application/x-silverlight-2","AgControl.AgControl",function(a){var b=[0,0,0,0],c=function(d,e,g,f){for(;d.isVersionSupported(e[0]+"."+e[1]+"."+e[2]+"."+e[3]);)e[g]+=f;e[g]-=f};c(a,b,0,1);c(a,b,1,1);c(a,b,2,1E4);c(a,b,2,1E3);c(a,b,2,100);c(a,b,2,10);c(a,b,2,1);c(a,b,3,1);return b});
|
21 |
+
mejs.MediaFeatures={init:function(){var a=this,b=document,c=mejs.PluginDetector.nav,d=mejs.PluginDetector.ua.toLowerCase(),e,g=["source","track","audio","video"];a.isiPad=d.match(/ipad/i)!==null;a.isiPhone=d.match(/iphone/i)!==null;a.isiOS=a.isiPhone||a.isiPad;a.isAndroid=d.match(/android/i)!==null;a.isBustedAndroid=d.match(/android 2\.[12]/)!==null;a.isIE=c.appName.toLowerCase().indexOf("microsoft")!=-1;a.isChrome=d.match(/chrome/gi)!==null;a.isFirefox=d.match(/firefox/gi)!==null;a.isWebkit=d.match(/webkit/gi)!==
|
22 |
+
null;a.isGecko=d.match(/gecko/gi)!==null&&!a.isWebkit;a.isOpera=d.match(/opera/gi)!==null;a.hasTouch="ontouchstart"in window;for(c=0;c<g.length;c++)e=document.createElement(g[c]);a.supportsMediaTag=typeof e.canPlayType!=="undefined"||a.isBustedAndroid;a.hasSemiNativeFullScreen=typeof e.webkitEnterFullscreen!=="undefined";a.hasWebkitNativeFullScreen=typeof e.webkitRequestFullScreen!=="undefined";a.hasMozNativeFullScreen=typeof e.mozRequestFullScreen!=="undefined";a.hasTrueNativeFullScreen=a.hasWebkitNativeFullScreen||
|
23 |
+
a.hasMozNativeFullScreen;a.nativeFullScreenEnabled=a.hasTrueNativeFullScreen;if(a.hasMozNativeFullScreen)a.nativeFullScreenEnabled=e.mozFullScreenEnabled;if(this.isChrome)a.hasSemiNativeFullScreen=false;if(a.hasTrueNativeFullScreen){a.fullScreenEventName=a.hasWebkitNativeFullScreen?"webkitfullscreenchange":"mozfullscreenchange";a.isFullScreen=function(){if(e.mozRequestFullScreen)return b.mozFullScreen;else if(e.webkitRequestFullScreen)return b.webkitIsFullScreen};a.requestFullScreen=function(f){if(a.hasWebkitNativeFullScreen)f.webkitRequestFullScreen();
|
24 |
+
else a.hasMozNativeFullScreen&&f.mozRequestFullScreen()};a.cancelFullScreen=function(){if(a.hasWebkitNativeFullScreen)document.webkitCancelFullScreen();else a.hasMozNativeFullScreen&&document.mozCancelFullScreen()}}if(a.hasSemiNativeFullScreen&&d.match(/mac os x 10_5/i)){a.hasNativeFullScreen=false;a.hasSemiNativeFullScreen=false}}};mejs.MediaFeatures.init();
|
25 |
+
mejs.HtmlMediaElement={pluginType:"native",isFullScreen:false,setCurrentTime:function(a){this.currentTime=a},setMuted:function(a){this.muted=a},setVolume:function(a){this.volume=a},stop:function(){this.pause()},setSrc:function(a){for(var b=this.getElementsByTagName("source");b.length>0;)this.removeChild(b[0]);if(typeof a=="string")this.src=a;else{var c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type))this.src=c.src}}},setVideoSize:function(a,b){this.width=a;this.height=b}};
|
26 |
+
mejs.PluginMediaElement=function(a,b,c){this.id=a;this.pluginType=b;this.src=c;this.events={}};
|
27 |
+
mejs.PluginMediaElement.prototype={pluginElement:null,pluginType:"",isFullScreen:false,playbackRate:-1,defaultPlaybackRate:-1,seekable:[],played:[],paused:true,ended:false,seeking:false,duration:0,error:null,tagName:"",muted:false,volume:1,currentTime:0,play:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.playVideo():this.pluginApi.playMedia();this.paused=false}},load:function(){if(this.pluginApi!=null){this.pluginType!="youtube"&&this.pluginApi.loadMedia();this.paused=
|
28 |
+
false}},pause:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.pauseVideo():this.pluginApi.pauseMedia();this.paused=true}},stop:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.stopVideo():this.pluginApi.stopMedia();this.paused=true}},canPlayType:function(a){var b,c,d,e=mejs.plugins[this.pluginType];for(b=0;b<e.length;b++){d=e[b];if(mejs.PluginDetector.hasPluginVersion(this.pluginType,d.version))for(c=0;c<d.types.length;c++)if(a==d.types[c])return true}return false},
|
29 |
+
positionFullscreenButton:function(a,b,c){this.pluginApi!=null&&this.pluginApi.positionFullscreenButton&&this.pluginApi.positionFullscreenButton(a,b,c)},hideFullscreenButton:function(){this.pluginApi!=null&&this.pluginApi.hideFullscreenButton&&this.pluginApi.hideFullscreenButton()},setSrc:function(a){if(typeof a=="string"){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(a));this.src=mejs.Utility.absolutizeUrl(a)}else{var b,c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(c.src));
|
30 |
+
this.src=mejs.Utility.absolutizeUrl(a)}}}},setCurrentTime:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.seekTo(a):this.pluginApi.setCurrentTime(a);this.currentTime=a}},setVolume:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.setVolume(a*100):this.pluginApi.setVolume(a);this.volume=a}},setMuted:function(a){if(this.pluginApi!=null){if(this.pluginType=="youtube"){a?this.pluginApi.mute():this.pluginApi.unMute();this.muted=a;this.dispatchEvent("volumechange")}else this.pluginApi.setMuted(a);
|
31 |
+
this.muted=a}},setVideoSize:function(a,b){if(this.pluginElement.style){this.pluginElement.style.width=a+"px";this.pluginElement.style.height=b+"px"}this.pluginApi!=null&&this.pluginApi.setVideoSize&&this.pluginApi.setVideoSize(a,b)},setFullscreen:function(a){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.pluginApi.setFullscreen(a)},enterFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.setFullscreen(true)},exitFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&
|
32 |
+
this.setFullscreen(false)},addEventListener:function(a,b){this.events[a]=this.events[a]||[];this.events[a].push(b)},removeEventListener:function(a,b){if(!a){this.events={};return true}var c=this.events[a];if(!c)return true;if(!b){this.events[a]=[];return true}for(i=0;i<c.length;i++)if(c[i]===b){this.events[a].splice(i,1);return true}return false},dispatchEvent:function(a){var b,c,d=this.events[a];if(d){c=Array.prototype.slice.call(arguments,1);for(b=0;b<d.length;b++)d[b].apply(null,c)}},attributes:{},
|
33 |
+
hasAttribute:function(a){return a in this.attributes},removeAttribute:function(a){delete this.attributes[a]},getAttribute:function(a){if(this.hasAttribute(a))return this.attributes[a];return""},setAttribute:function(a,b){this.attributes[a]=b},remove:function(){mejs.Utility.removeSwf(this.pluginElement.id)}};
|
34 |
+
mejs.MediaPluginBridge={pluginMediaElements:{},htmlMediaElements:{},registerPluginElement:function(a,b,c){this.pluginMediaElements[a]=b;this.htmlMediaElements[a]=c},initPlugin:function(a){var b=this.pluginMediaElements[a],c=this.htmlMediaElements[a];if(b){switch(b.pluginType){case "flash":b.pluginElement=b.pluginApi=document.getElementById(a);break;case "silverlight":b.pluginElement=document.getElementById(b.id);b.pluginApi=b.pluginElement.Content.MediaElementJS}b.pluginApi!=null&&b.success&&b.success(b,
|
35 |
+
c)}},fireEvent:function(a,b,c){var d,e;a=this.pluginMediaElements[a];a.ended=false;a.paused=true;b={type:b,target:a};for(d in c){a[d]=c[d];b[d]=c[d]}e=c.bufferedTime||0;b.target.buffered=b.buffered={start:function(){return 0},end:function(){return e},length:1};a.dispatchEvent(b.type,b)}};
|
36 |
+
mejs.MediaElementDefaults={mode:"auto",plugins:["flash","silverlight","youtube","vimeo"],enablePluginDebug:false,type:"",pluginPath:mejs.Utility.getScriptPath(["mediaelement.js","mediaelement.min.js","mediaelement-and-player.js","mediaelement-and-player.min.js"]),flashName:"flashmediaelement.swf",enablePluginSmoothing:false,silverlightName:"silverlightmediaelement.xap",defaultVideoWidth:480,defaultVideoHeight:270,pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:0.8,success:function(){},
|
37 |
+
error:function(){}};mejs.MediaElement=function(a,b){return mejs.HtmlMediaElementShim.create(a,b)};
|
38 |
+
mejs.HtmlMediaElementShim={create:function(a,b){var c=mejs.MediaElementDefaults,d=typeof a=="string"?document.getElementById(a):a,e=d.tagName.toLowerCase(),g=e==="audio"||e==="video",f=g?d.getAttribute("src"):d.getAttribute("href");e=d.getAttribute("poster");var j=d.getAttribute("autoplay"),h=d.getAttribute("preload"),l=d.getAttribute("controls"),k;for(k in b)c[k]=b[k];f=typeof f=="undefined"||f===null||f==""?null:f;e=typeof e=="undefined"||e===null?"":e;h=typeof h=="undefined"||h===null||h==="false"?
|
39 |
+
"none":h;j=!(typeof j=="undefined"||j===null||j==="false");l=!(typeof l=="undefined"||l===null||l==="false");k=this.determinePlayback(d,c,mejs.MediaFeatures.supportsMediaTag,g,f);k.url=k.url!==null?mejs.Utility.absolutizeUrl(k.url):"";if(k.method=="native"){if(mejs.MediaFeatures.isBustedAndroid){d.src=k.url;d.addEventListener("click",function(){d.play()},false)}return this.updateNative(k,c,j,h)}else if(k.method!=="")return this.createPlugin(k,c,e,j,h,l);else{this.createErrorMessage(k,c,e);return this}},
|
40 |
+
determinePlayback:function(a,b,c,d,e){var g=[],f,j,h={method:"",url:"",htmlMediaElement:a,isVideo:a.tagName.toLowerCase()!="audio"},l,k;if(typeof b.type!="undefined"&&b.type!=="")if(typeof b.type=="string")g.push({type:b.type,url:e});else for(f=0;f<b.type.length;f++)g.push({type:b.type[f],url:e});else if(e!==null){j=this.formatType(e,a.getAttribute("type"));g.push({type:j,url:e})}else for(f=0;f<a.childNodes.length;f++){j=a.childNodes[f];if(j.nodeType==1&&j.tagName.toLowerCase()=="source"){e=j.getAttribute("src");
|
41 |
+
j=this.formatType(e,j.getAttribute("type"));g.push({type:j,url:e})}}if(!d&&g.length>0&&g[0].url!==null&&this.getTypeFromFile(g[0].url).indexOf("audio")>-1)h.isVideo=false;if(mejs.MediaFeatures.isBustedAndroid)a.canPlayType=function(m){return m.match(/video\/(mp4|m4v)/gi)!==null?"maybe":""};if(c&&(b.mode==="auto"||b.mode==="native")){if(!d){f=document.createElement(h.isVideo?"video":"audio");a.parentNode.insertBefore(f,a);a.style.display="none";h.htmlMediaElement=a=f}for(f=0;f<g.length;f++)if(a.canPlayType(g[f].type).replace(/no/,
|
42 |
+
"")!==""||a.canPlayType(g[f].type.replace(/mp3/,"mpeg")).replace(/no/,"")!==""){h.method="native";h.url=g[f].url;break}if(h.method==="native"){if(h.url!==null)a.src=h.url;return h}}if(b.mode==="auto"||b.mode==="shim")for(f=0;f<g.length;f++){j=g[f].type;for(a=0;a<b.plugins.length;a++){e=b.plugins[a];l=mejs.plugins[e];for(c=0;c<l.length;c++){k=l[c];if(k.version==null||mejs.PluginDetector.hasPluginVersion(e,k.version))for(d=0;d<k.types.length;d++)if(j==k.types[d]){h.method=e;h.url=g[f].url;return h}}}}if(h.method===
|
43 |
+
""&&g.length>0)h.url=g[0].url;return h},formatType:function(a,b){return a&&!b?this.getTypeFromFile(a):b&&~b.indexOf(";")?b.substr(0,b.indexOf(";")):b},getTypeFromFile:function(a){a=a.substring(a.lastIndexOf(".")+1);return(/(mp4|m4v|ogg|ogv|webm|flv|wmv|mpeg|mov)/gi.test(a)?"video":"audio")+"/"+a},createErrorMessage:function(a,b,c){var d=a.htmlMediaElement,e=document.createElement("div");e.className="me-cannotplay";try{e.style.width=d.width+"px";e.style.height=d.height+"px"}catch(g){}e.innerHTML=c!==
|
44 |
+
""?'<a href="'+a.url+'"><img src="'+c+'" width="100%" height="100%" /></a>':'<a href="'+a.url+'"><span>Download File</span></a>';d.parentNode.insertBefore(e,d);d.style.display="none";b.error(d)},createPlugin:function(a,b,c,d,e,g){c=a.htmlMediaElement;var f=1,j=1,h="me_"+a.method+"_"+mejs.meIndex++,l=new mejs.PluginMediaElement(h,a.method,a.url),k=document.createElement("div"),m;l.tagName=c.tagName;for(m=0;m<c.attributes.length;m++){var n=c.attributes[m];n.specified==true&&l.setAttribute(n.name,n.value)}for(m=
|
45 |
+
c.parentNode;m!==null&&m.tagName.toLowerCase()!="body";){if(m.parentNode.tagName.toLowerCase()=="p"){m.parentNode.parentNode.insertBefore(m,m.parentNode);break}m=m.parentNode}if(a.isVideo){f=b.videoWidth>0?b.videoWidth:c.getAttribute("width")!==null?c.getAttribute("width"):b.defaultVideoWidth;j=b.videoHeight>0?b.videoHeight:c.getAttribute("height")!==null?c.getAttribute("height"):b.defaultVideoHeight;f=mejs.Utility.encodeUrl(f);j=mejs.Utility.encodeUrl(j)}else if(b.enablePluginDebug){f=320;j=240}l.success=
|
46 |
+
b.success;mejs.MediaPluginBridge.registerPluginElement(h,l,c);k.className="me-plugin";k.id=h+"_container";a.isVideo?c.parentNode.insertBefore(k,c):document.body.insertBefore(k,document.body.childNodes[0]);d=["id="+h,"isvideo="+(a.isVideo?"true":"false"),"autoplay="+(d?"true":"false"),"preload="+e,"width="+f,"startvolume="+b.startVolume,"timerrate="+b.timerRate,"height="+j];if(a.url!==null)a.method=="flash"?d.push("file="+mejs.Utility.encodeUrl(a.url)):d.push("file="+a.url);b.enablePluginDebug&&d.push("debug=true");
|
47 |
+
b.enablePluginSmoothing&&d.push("smoothing=true");g&&d.push("controls=true");if(b.pluginVars)d=d.concat(b.pluginVars);switch(a.method){case "silverlight":k.innerHTML='<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="'+h+'" name="'+h+'" width="'+f+'" height="'+j+'"><param name="initParams" value="'+d.join(",")+'" /><param name="windowless" value="true" /><param name="background" value="black" /><param name="minRuntimeVersion" value="3.0.0.0" /><param name="autoUpgrade" value="true" /><param name="source" value="'+
|
48 |
+
b.pluginPath+b.silverlightName+'" /></object>';break;case "flash":if(mejs.MediaFeatures.isIE){a=document.createElement("div");k.appendChild(a);a.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+h+'" width="'+f+'" height="'+j+'"><param name="movie" value="'+b.pluginPath+b.flashName+"?x="+new Date+'" /><param name="flashvars" value="'+d.join("&")+'" /><param name="quality" value="high" /><param name="bgcolor" value="#000000" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else k.innerHTML=
|
49 |
+
'<embed id="'+h+'" name="'+h+'" play="true" loop="false" quality="high" bgcolor="#000000" wmode="transparent" allowScriptAccess="always" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" src="'+b.pluginPath+b.flashName+'" flashvars="'+d.join("&")+'" width="'+f+'" height="'+j+'"></embed>';break;case "youtube":b=a.url.substr(a.url.lastIndexOf("=")+1);youtubeSettings={container:k,containerId:k.id,pluginMediaElement:l,pluginId:h,videoId:b,
|
50 |
+
height:j,width:f};mejs.PluginDetector.hasPluginVersion("flash",[10,0,0])?mejs.YouTubeApi.createFlash(youtubeSettings):mejs.YouTubeApi.enqueueIframe(youtubeSettings);break;case "vimeo":console.log("vimeoid");l.vimeoid=a.url.substr(a.url.lastIndexOf("/")+1);k.innerHTML='<object width="'+f+'" height="'+j+'"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="flashvars" value="api=1" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id='+
|
51 |
+
l.vimeoid+'&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" /><embed src="//vimeo.com/moogaloop.swf?api=1&clip_id='+l.vimeoid+'&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="'+f+'" height="'+j+'"></embed></object>'}c.style.display=
|
52 |
+
"none";return l},updateNative:function(a,b){var c=a.htmlMediaElement,d;for(d in mejs.HtmlMediaElement)c[d]=mejs.HtmlMediaElement[d];b.success(c,c);return c}};
|
53 |
+
mejs.YouTubeApi={isIframeStarted:false,isIframeLoaded:false,loadIframeApi:function(){if(!this.isIframeStarted){var a=document.createElement("script");a.src="http://www.youtube.com/player_api";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b);this.isIframeStarted=true}},iframeQueue:[],enqueueIframe:function(a){if(this.isLoaded)this.createIframe(a);else{this.loadIframeApi();this.iframeQueue.push(a)}},createIframe:function(a){var b=a.pluginMediaElement,c=new YT.Player(a.containerId,
|
54 |
+
{height:a.height,width:a.width,videoId:a.videoId,playerVars:{controls:0},events:{onReady:function(){a.pluginMediaElement.pluginApi=c;mejs.MediaPluginBridge.initPlugin(a.pluginId);setInterval(function(){mejs.YouTubeApi.createEvent(c,b,"timeupdate")},250)},onStateChange:function(d){mejs.YouTubeApi.handleStateChange(d.data,c,b)}}})},createEvent:function(a,b,c){c={type:c,target:b};if(a&&a.getDuration){b.currentTime=c.currentTime=a.getCurrentTime();b.duration=c.duration=a.getDuration();c.paused=b.paused;
|
55 |
+
c.ended=b.ended;c.muted=a.isMuted();c.volume=a.getVolume()/100;c.bytesTotal=a.getVideoBytesTotal();c.bufferedBytes=a.getVideoBytesLoaded();var d=c.bufferedBytes/c.bytesTotal*c.duration;c.target.buffered=c.buffered={start:function(){return 0},end:function(){return d},length:1}}b.dispatchEvent(c.type,c)},iFrameReady:function(){for(this.isIframeLoaded=this.isLoaded=true;this.iframeQueue.length>0;)this.createIframe(this.iframeQueue.pop())},flashPlayers:{},createFlash:function(a){this.flashPlayers[a.pluginId]=
|
56 |
+
a;var b,c="http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid="+a.pluginId+"&version=3&autoplay=0&controls=0&modestbranding=1&loop=0";if(mejs.MediaFeatures.isIE){b=document.createElement("div");a.container.appendChild(b);b.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+a.pluginId+'" width="'+a.width+'" height="'+a.height+'"><param name="movie" value="'+c+'" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else a.container.innerHTML=
|
57 |
+
'<object type="application/x-shockwave-flash" id="'+a.pluginId+'" data="'+c+'" width="'+a.width+'" height="'+a.height+'" style="visibility: visible; "><param name="allowScriptAccess" value="always"><param name="wmode" value="transparent"></object>'},flashReady:function(a){var b=this.flashPlayers[a],c=document.getElementById(a),d=b.pluginMediaElement;d.pluginApi=d.pluginElement=c;mejs.MediaPluginBridge.initPlugin(a);c.cueVideoById(b.videoId);a=b.containerId+"_callback";window[a]=function(e){mejs.YouTubeApi.handleStateChange(e,
|
58 |
+
c,d)};c.addEventListener("onStateChange",a);setInterval(function(){mejs.YouTubeApi.createEvent(c,d,"timeupdate")},250)},handleStateChange:function(a,b,c){switch(a){case -1:c.paused=true;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"loadedmetadata");break;case 0:c.paused=false;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"ended");break;case 1:c.paused=false;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"play");mejs.YouTubeApi.createEvent(b,c,"playing");break;case 2:c.paused=true;c.ended=false;mejs.YouTubeApi.createEvent(b,
|
59 |
+
c,"pause");break;case 3:mejs.YouTubeApi.createEvent(b,c,"progress")}}};function onYouTubePlayerAPIReady(){mejs.YouTubeApi.iFrameReady()}function onYouTubePlayerReady(a){mejs.YouTubeApi.flashReady(a)}window.mejs=mejs;window.MediaElement=mejs.MediaElement;
|
60 |
+
|
61 |
+
/*!
|
62 |
+
* MediaElementPlayer
|
63 |
+
* http://mediaelementjs.com/
|
64 |
+
*
|
65 |
+
* Creates a controller bar for HTML5 <video> add <audio> tags
|
66 |
+
* using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper)
|
67 |
+
*
|
68 |
+
* Copyright 2010-2012, John Dyer (http://j.hn/)
|
69 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
70 |
+
*
|
71 |
+
*/if(typeof jQuery!="undefined")mejs.$=jQuery;else if(typeof ender!="undefined")mejs.$=ender;
|
72 |
+
(function(f){mejs.MepDefaults={poster:"",defaultVideoWidth:480,defaultVideoHeight:270,videoWidth:-1,videoHeight:-1,defaultAudioWidth:400,defaultAudioHeight:30,audioWidth:-1,audioHeight:-1,startVolume:0.8,loop:false,enableAutosize:true,alwaysShowHours:false,showTimecodeFrameCount:false,framesPerSecond:25,autosizeProgress:true,alwaysShowControls:false,iPadUseNativeControls:false,iPhoneUseNativeControls:false,AndroidUseNativeControls:false,features:["playpause","current","progress","duration","tracks",
|
73 |
+
"volume","fullscreen"],isVideo:true,enableKeyboard:true,pauseOtherPlayers:true,keyActions:[{keys:[32,179],action:function(a,b){b.paused||b.ended?b.play():b.pause()}},{keys:[38],action:function(a,b){b.setVolume(Math.min(b.volume+0.1,1))}},{keys:[40],action:function(a,b){b.setVolume(Math.max(b.volume-0.1,0))}},{keys:[37,227],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}b.setCurrentTime(Math.max(b.currentTime-b.duration*0.05,0))}}},{keys:[39,
|
74 |
+
228],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}b.setCurrentTime(Math.min(b.currentTime+b.duration*0.05,b.duration))}}},{keys:[70],action:function(a){if(typeof a.enterFullScreen!="undefined")a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}}]};mejs.mepIndex=0;mejs.players=[];mejs.MediaElementPlayer=function(a,b){if(!(this instanceof mejs.MediaElementPlayer))return new mejs.MediaElementPlayer(a,b);this.$media=this.$node=f(a);
|
75 |
+
this.node=this.media=this.$media[0];if(typeof this.node.player!="undefined")return this.node.player;else this.node.player=this;if(typeof b=="undefined")b=this.$node.data("mejsoptions");this.options=f.extend({},mejs.MepDefaults,b);mejs.players.push(this);this.init();return this};mejs.MediaElementPlayer.prototype={hasFocus:false,controlsAreVisible:true,init:function(){var a=this,b=mejs.MediaFeatures,c=f.extend(true,{},a.options,{success:function(e,g){a.meReady(e,g)},error:function(e){a.handleError(e)}}),
|
76 |
+
d=a.media.tagName.toLowerCase();a.isDynamic=d!=="audio"&&d!=="video";a.isVideo=a.isDynamic?a.options.isVideo:d!=="audio"&&a.options.isVideo;if(b.isiPad&&a.options.iPadUseNativeControls||b.isiPhone&&a.options.iPhoneUseNativeControls){a.$media.attr("controls","controls");if(b.isiPad&&a.media.getAttribute("autoplay")!==null){a.media.load();a.media.play()}}else if(!(b.isAndroid&&a.AndroidUseNativeControls)){a.$media.removeAttr("controls");a.id="mep_"+mejs.mepIndex++;a.container=f('<div id="'+a.id+'" class="mejs-container"><div class="mejs-inner"><div class="mejs-mediaelement"></div><div class="mejs-layers"></div><div class="mejs-controls"></div><div class="mejs-clear"></div></div></div>').addClass(a.$media[0].className).insertBefore(a.$media);
|
77 |
+
a.container.addClass((b.isAndroid?"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=d.substring(0,1).toUpperCase()+d.substring(1);
|
78 |
+
a.width=a.options[d+"Width"]>0||a.options[d+"Width"].toString().indexOf("%")>-1?a.options[d+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+b+"Width"];a.height=a.options[d+"Height"]>0||a.options[d+"Height"].toString().indexOf("%")>-1?a.options[d+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!==null?a.$media.attr("height"):
|
79 |
+
a.options["default"+b+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.height;c.pluginHeight=a.width}mejs.MediaElement(a.$media[0],c)},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true});b.container.find(".mejs-control").css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility",
|
80 |
+
"visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(b.controlsAreVisible)if(a){b.controls.stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block");b.controlsAreVisible=false});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display",
|
81 |
+
"block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false}},controlsTimer:null,startControlsTimer:function(a){var b=this;a=typeof a!="undefined"?a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;
|
82 |
+
this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false);this.controlsEnabled=true},meReady:function(a,b){var c=this,d=mejs.MediaFeatures,e=b.getAttribute("autoplay");e=!(typeof e=="undefined"||e===null||e==="false");var g;if(!c.created){c.created=true;c.media=a;c.domNode=b;if(!(d.isAndroid&&c.options.AndroidUseNativeControls)&&!(d.isiPad&&c.options.iPadUseNativeControls)&&
|
83 |
+
!(d.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media);c.findTracks();for(g in c.options.features){d=c.options.features[g];if(c["build"+d])try{c["build"+d](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);
|
84 |
+
else c.controlsEnabled&&c.showControls(false)});else{(c.media.pluginType=="native"?c.$media:f(c.media.pluginElement)).click(function(){a.paused?a.play():a.pause()});c.container.bind("mouseenter mouseover",function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",
|
85 |
+
function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&&c.startControlsTimer(1E3)})}e&&!c.options.alwaysShowControls&&c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(h){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(h.target.videoHeight)){c.setPlayerSize(h.target.videoWidth,h.target.videoHeight);c.setControlsSize();c.media.setVideoSize(h.target.videoWidth,h.target.videoHeight)}},false)}a.addEventListener("play",
|
86 |
+
function(){for(var h=0,o=mejs.players.length;h<o;h++){var n=mejs.players[h];n.id!=c.id&&c.options.pauseOtherPlayers&&!n.paused&&!n.ended&&n.pause();n.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){try{c.media.setCurrentTime(0)}catch(h){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.media.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",
|
87 |
+
function(){c.updateDuration&&c.updateDuration();c.updateCurrent&&c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width,c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);f(window).resize(function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.container.find(".mejs-overlay-play").hide()}if(e&&
|
88 |
+
a.pluginType=="native"){a.load();a.play()}if(c.options.success)typeof c.options.success=="string"?window[c.options.success](c.media,c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0){var c=this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.options.defaultVideoWidth,
|
89 |
+
d=this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.options.defaultVideoHeight,e=this.container.parent().width();c=parseInt(e*d/c,10);if(this.container.parent()[0].tagName.toLowerCase()==="body"){e=f(window).width();c=f(window).height()}this.container.width(e).height(c);this.$media.width("100%").height("100%");this.container.find("object, embed, iframe").width("100%").height("100%");this.media.setVideoSize&&this.media.setVideoSize(e,c);this.layers.children(".mejs-layer").width("100%").height("100%")}else{this.container.width(this.width).height(this.height);
|
90 |
+
this.layers.children(".mejs-layer").width(this.width).height(this.height)}},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),d=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var e=c.siblings();if(this.options&&!this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){e.each(function(){if(f(this).css("position")!="absolute")a+=f(this).outerWidth(true)});b=this.controls.width()-a-(c.outerWidth(true)-
|
91 |
+
c.width())}c.width(b);d.width(b-(d.outerWidth(true)-d.width()));this.setProgressRail&&this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()},buildposter:function(a,b,c,d){var e=f('<div class="mejs-poster mejs-layer"></div>').appendTo(c);b=a.$media.attr("poster");if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):e.hide();d.addEventListener("play",function(){e.hide()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"),c=b.find("img");if(c.length==
|
92 |
+
0)c=f('<img width="100%" height="100%" />').appendTo(b);c.attr("src",a)},buildoverlays:function(a,b,c,d){if(a.isVideo){var e=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-loading"><span></span></div></div>').hide().appendTo(c),g=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-error"></div></div>').hide().appendTo(c),k=f('<div class="mejs-overlay mejs-layer mejs-overlay-play"><div class="mejs-overlay-button"></div></div>').appendTo(c).click(function(){d.paused?d.play():
|
93 |
+
d.pause()});d.addEventListener("play",function(){k.hide();e.hide();b.find(".mejs-time-buffering").hide();g.hide()},false);d.addEventListener("playing",function(){k.hide();e.hide();b.find(".mejs-time-buffering").hide();g.hide()},false);d.addEventListener("seeking",function(){e.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("seeked",function(){e.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone||k.show()},
|
94 |
+
false);d.addEventListener("waiting",function(){e.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("loadeddata",function(){e.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("canplay",function(){e.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("error",function(){e.hide();b.find(".mejs-time-buffering").hide();g.show();g.find("mejs-overlay-error").html("Error loading this resource")},false)}},buildkeyboard:function(a,b,c,d){f(document).keydown(function(e){if(a.hasFocus&&
|
95 |
+
a.options.enableKeyboard)for(var g=0,k=a.options.keyActions.length;g<k;g++)for(var h=a.options.keyActions[g],o=0,n=h.keys.length;o<n;o++)if(e.keyCode==h.keys[o]){e.preventDefault();h.action(a,d);return false}return true});f(document).click(function(e){if(f(e.target).closest(".mejs-container").length==0)a.hasFocus=false})},findTracks:function(){var a=this,b=a.$media.find("track");a.tracks=[];b.each(function(c,d){d=f(d);a.tracks.push({srclang:d.attr("srclang").toLowerCase(),src:d.attr("src"),kind:d.attr("kind"),
|
96 |
+
label:d.attr("label")||"",entries:[],isLoaded:false})})},changeSkin:function(a){this.container[0].className="mejs-container "+a;this.setPlayerSize(this.width,this.height);this.setControlsSize()},play:function(){this.media.play()},pause:function(){this.media.pause()},load:function(){this.media.load()},setMuted:function(a){this.media.setMuted(a)},setCurrentTime:function(a){this.media.setCurrentTime(a)},getCurrentTime:function(){return this.media.currentTime},setVolume:function(a){this.media.setVolume(a)},
|
97 |
+
getVolume:function(){return this.media.volume},setSrc:function(a){this.media.setSrc(a)},remove:function(){if(this.media.pluginType=="flash")this.media.remove();else this.media.pluginType=="native"&&this.media.prop("controls",true);this.isDynamic||this.$node.insertBefore(this.container);this.container.remove()}};if(typeof jQuery!="undefined")jQuery.fn.mediaelementplayer=function(a){return this.each(function(){new mejs.MediaElementPlayer(this,a)})};f(document).ready(function(){f(".mejs-player").mediaelementplayer()});
|
98 |
+
window.MediaElementPlayer=mejs.MediaElementPlayer})(mejs.$);
|
99 |
+
(function(f){f.extend(mejs.MepDefaults,{playpauseText:"Play/Pause"});f.extend(MediaElementPlayer.prototype,{buildplaypause:function(a,b,c,d){var e=f('<div class="mejs-button mejs-playpause-button mejs-play" ><button type="button" aria-controls="'+this.id+'" title="'+this.options.playpauseText+'"></button></div>').appendTo(b).click(function(g){g.preventDefault();d.paused?d.play():d.pause();return false});d.addEventListener("play",function(){e.removeClass("mejs-play").addClass("mejs-pause")},false);
|
100 |
+
d.addEventListener("playing",function(){e.removeClass("mejs-play").addClass("mejs-pause")},false);d.addEventListener("pause",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false);d.addEventListener("paused",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$);
|
101 |
+
(function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,d){f('<div class="mejs-button mejs-stop-button mejs-stop"><button type="button" aria-controls="'+this.id+'" title="'+this.options.stopText+'"></button></div>').appendTo(b).click(function(){d.paused||d.pause();if(d.currentTime>0){d.setCurrentTime(0);b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left","0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));
|
102 |
+
b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$);
|
103 |
+
(function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,d){f('<div class="mejs-time-rail"><span class="mejs-time-total"><span class="mejs-time-buffering"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span></span></div>').appendTo(b);b.find(".mejs-time-buffering").hide();var e=
|
104 |
+
b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var g=b.find(".mejs-time-current"),k=b.find(".mejs-time-handle"),h=b.find(".mejs-time-float"),o=b.find(".mejs-time-float-current"),n=function(l){l=l.pageX;var q=e.offset(),i=e.outerWidth(),j=0;j=0;var m=l-q.left;if(l>q.left&&l<=i+q.left&&d.duration){j=(l-q.left)/i;j=j<=0.02?0:j*d.duration;p&&d.setCurrentTime(j);if(!mejs.MediaFeatures.hasTouch){h.css("left",m);o.html(mejs.Utility.secondsToTimeCode(j));h.show()}}},p=false;e.bind("mousedown",function(l){if(l.which===
|
105 |
+
1){p=true;n(l);f(document).bind("mousemove.dur",function(q){n(q)}).bind("mouseup.dur",function(){p=false;h.hide();f(document).unbind(".dur")});return false}}).bind("mouseenter",function(){f(document).bind("mousemove.dur",function(l){n(l)});mejs.MediaFeatures.hasTouch||h.show()}).bind("mouseleave",function(){if(!p){f(document).unbind(".dur");h.hide()}});d.addEventListener("progress",function(l){a.setProgressRail(l);a.setCurrentRail(l)},false);d.addEventListener("timeupdate",function(l){a.setProgressRail(l);
|
106 |
+
a.setCurrentRail(l)},false);this.loaded=c;this.total=e;this.current=g;this.handle=k},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal;else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1,Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*
|
107 |
+
c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=this.total.width()*this.media.currentTime/this.media.duration,b=a-this.handle.outerWidth(true)/2;this.current.width(a);this.handle.css("left",b)}}})})(mejs.$);
|
108 |
+
(function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:" <span> | </span> "});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,d){f('<div class="mejs-time"><span class="mejs-currenttime">'+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"</span></div>").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");d.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a,
|
109 |
+
b,c,d){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+'<span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span>").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container");
|
110 |
+
f('<div class="mejs-time mejs-duration-container"><span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span></div>").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");d.addEventListener("timeupdate",function(){a.updateDuration()},
|
111 |
+
false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){if(this.media.duration&&this.durationD)this.durationD.html(mejs.Utility.secondsToTimeCode(this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$);
|
112 |
+
(function(f){f.extend(mejs.MepDefaults,{muteText:"Mute Toggle",hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,d){if(!(mejs.MediaFeatures.hasTouch&&this.options.hideVolumeOnTouchDevices)){var e=this.isVideo?this.options.videoVolume:this.options.audioVolume,g=e=="horizontal"?f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+this.id+'" title="'+this.options.muteText+
|
113 |
+
'"></button></div><div class="mejs-horizontal-volume-slider"><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current"></div><div class="mejs-horizontal-volume-handle"></div></div>').appendTo(b):f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+this.id+'" title="'+this.options.muteText+'"></button><div class="mejs-volume-slider"><div class="mejs-volume-total"></div><div class="mejs-volume-current"></div><div class="mejs-volume-handle"></div></div></div>').appendTo(b),
|
114 |
+
k=this.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),h=this.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),o=this.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),n=this.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),p=function(j,m){if(!k.is(":visible")&&typeof m!="undefined"){k.show();p(j,true);k.hide()}else{j=Math.max(0,j);j=Math.min(j,1);j==0?g.removeClass("mejs-mute").addClass("mejs-unmute"):g.removeClass("mejs-unmute").addClass("mejs-mute");
|
115 |
+
if(e=="vertical"){var r=h.height(),s=h.position(),t=r-r*j;n.css("top",s.top+t-n.height()/2);o.height(r-t);o.css("top",s.top+t)}else{r=h.width();s=h.position();r=r*j;n.css("left",s.left+r-n.width()/2);o.width(r)}}},l=function(j){var m=null,r=h.offset();if(e=="vertical"){m=h.height();parseInt(h.css("top").replace(/px/,""),10);m=(m-(j.pageY-r.top))/m;if(r.top==0||r.left==0)return}else{m=h.width();m=(j.pageX-r.left)/m}m=Math.max(0,m);m=Math.min(m,1);p(m);m==0?d.setMuted(true):d.setMuted(false);d.setVolume(m)},
|
116 |
+
q=false,i=false;g.hover(function(){k.show();i=true},function(){i=false;!q&&e=="vertical"&&k.hide()});k.bind("mouseover",function(){i=true}).bind("mousedown",function(j){l(j);f(document).bind("mousemove.vol",function(m){l(m)}).bind("mouseup.vol",function(){q=false;f(document).unbind(".vol");!i&&e=="vertical"&&k.hide()});q=true;return false});g.find("button").click(function(){d.setMuted(!d.muted)});d.addEventListener("volumechange",function(){if(!q)if(d.muted){p(0);g.removeClass("mejs-mute").addClass("mejs-unmute")}else{p(d.volume);
|
117 |
+
g.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(this.container.is(":visible")){p(a.options.startVolume);d.pluginType==="native"&&d.setVolume(a.options.startVolume)}}}})})(mejs.$);
|
118 |
+
(function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:"Fullscreen"});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,docStyleOverflow:null,isInIframe:false,buildfullscreen:function(a,b,c,d){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;if(mejs.MediaFeatures.hasTrueNativeFullScreen){c=null;c=mejs.MediaFeatures.hasMozNativeFullScreen?f(document):a.container;c.bind(mejs.MediaFeatures.fullScreenEventName,
|
119 |
+
function(){if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen=true;a.setControlsSize()}else{a.isNativeFullScreen=false;a.exitFullScreen()}})}var e=this,g=f('<div class="mejs-button mejs-fullscreen-button"><button type="button" aria-controls="'+e.id+'" title="'+e.options.fullscreenText+'"></button></div>').appendTo(b);if(e.media.pluginType==="native"||!e.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||
|
120 |
+
a.isFullScreen?a.exitFullScreen():a.enterFullScreen()});else{var k=null;b=function(){var i=document.createElement("x"),j=document.documentElement,m=window.getComputedStyle;if(!("pointerEvents"in i.style))return false;i.style.pointerEvents="auto";i.style.pointerEvents="x";j.appendChild(i);m=m&&m(i,"").pointerEvents==="auto";j.removeChild(i);return!!m}();console.log("supportsPointerEvents",b);if(b&&!mejs.MediaFeatures.isOpera){var h=false,o=function(){if(h){n.hide();p.hide();l.hide();g.css("pointer-events",
|
121 |
+
"");e.controls.css("pointer-events","");h=false}},n=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(o),p=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(o),l=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(o),q=function(){var i={position:"absolute",top:0,left:0};n.css(i);p.css(i);l.css(i);n.width(e.container.width()).height(e.container.height()-e.controls.height());i=g.offset().left-e.container.offset().left;fullScreenBtnWidth=
|
122 |
+
g.outerWidth(true);p.width(i).height(e.controls.height()).css({top:e.container.height()-e.controls.height()});l.width(e.container.width()-i-fullScreenBtnWidth).height(e.controls.height()).css({top:e.container.height()-e.controls.height(),left:i+fullScreenBtnWidth})};f(document).resize(function(){q()});g.mouseover(function(){if(!e.isFullScreen){var i=g.offset(),j=a.container.offset();d.positionFullscreenButton(i.left-j.left,i.top-j.top,false);g.css("pointer-events","none");e.controls.css("pointer-events",
|
123 |
+
"none");n.show();l.show();p.show();q();h=true}});d.addEventListener("fullscreenchange",function(){o()})}else g.mouseover(function(){if(k!==null){clearTimeout(k);delete k}var i=g.offset(),j=a.container.offset();d.positionFullscreenButton(i.left-j.left,i.top-j.top,true)}).mouseout(function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){d.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;f(document).bind("keydown",function(i){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||
|
124 |
+
e.isFullScreen)&&i.keyCode==27)a.exitFullScreen()})}},enterFullScreen:function(){var a=this;if(!(a.media.pluginType!=="native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){docStyleOverflow=document.documentElement.style.overflow;document.documentElement.style.overflow="hidden";normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&
|
125 |
+
setTimeout(function c(){if(a.isNativeFullScreen)f(window).width()!==screen.width?a.exitFullScreen():setTimeout(c,500)},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},
|
126 |
+
250);else{a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find("object, embed, iframe").width("100%").height("100%");a.media.setVideoSize(f(window).width(),
|
127 |
+
f(window).height())}a.layers.children("div").width("100%").height("100%");a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true}},exitFullScreen:function(){if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&&(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen();document.documentElement.style.overflow=
|
128 |
+
docStyleOverflow;this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find("object embed").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight);this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen");this.setControlsSize();this.isFullScreen=
|
129 |
+
false}}})})(mejs.$);
|
130 |
+
(function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:"Captions/Subtitles"});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,d){if(a.isVideo)if(a.tracks.length!=0){var e;a.chapters=f('<div class="mejs-chapters mejs-layer"></div>').prependTo(c).hide();a.captions=f('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position"><span class="mejs-captions-text"></span></div></div>').prependTo(c).hide();a.captionsText=a.captions.find(".mejs-captions-text");
|
131 |
+
a.captionsButton=f('<div class="mejs-button mejs-captions-button"><button type="button" aria-controls="'+this.id+'" title="'+this.options.tracksText+'"></button><div class="mejs-captions-selector"><ul><li><input type="radio" name="'+a.id+'_captions" id="'+a.id+'_captions_none" value="none" checked="checked" /><label for="'+a.id+'_captions_none">None</label></li></ul></div></div>').appendTo(b).hover(function(){f(this).find(".mejs-captions-selector").css("visibility","visible")},function(){f(this).find(".mejs-captions-selector").css("visibility",
|
132 |
+
"hidden")}).delegate("input[type=radio]","click",function(){lang=this.value;if(lang=="none")a.selectedTrack=null;else for(e=0;e<a.tracks.length;e++)if(a.tracks[e].srclang==lang){a.selectedTrack=a.tracks[e];a.captions.attr("lang",a.selectedTrack.srclang);a.displayCaptions();break}});a.options.alwaysShowControls?a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover"):a.container.bind("mouseenter",function(){a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover")}).bind("mouseleave",
|
133 |
+
function(){d.paused||a.container.find(".mejs-captions-position").removeClass("mejs-captions-position-hover")});a.trackToLoad=-1;a.selectedTrack=null;a.isLoadingTrack=false;for(e=0;e<a.tracks.length;e++)a.tracks[e].kind=="subtitles"&&a.addTrackButton(a.tracks[e].srclang,a.tracks[e].label);a.loadNextTrack();d.addEventListener("timeupdate",function(){a.displayCaptions()},false);d.addEventListener("loadedmetadata",function(){a.displayChapters()},false);a.container.hover(function(){if(a.hasChapters){a.chapters.css("visibility",
|
134 |
+
"visible");a.chapters.fadeIn(200).height(a.chapters.find(".mejs-chapter").outerHeight())}},function(){a.hasChapters&&!d.paused&&a.chapters.fadeOut(200,function(){f(this).css("visibility","hidden");f(this).css("display","block")})});a.node.getAttribute("autoplay")!==null&&a.chapters.css("visibility","hidden")}},loadNextTrack:function(){this.trackToLoad++;if(this.trackToLoad<this.tracks.length){this.isLoadingTrack=true;this.loadTrack(this.trackToLoad)}else this.isLoadingTrack=false},loadTrack:function(a){var b=
|
135 |
+
this,c=b.tracks[a],d=function(){c.isLoaded=true;b.enableTrackButton(c.srclang,c.label);b.loadNextTrack()};c.isTranslation?mejs.TrackFormatParser.translateTrackText(b.tracks[0].entries,b.tracks[0].srclang,c.srclang,b.options.googleApiKey,function(e){c.entries=e;d()}):f.ajax({url:c.src,success:function(e){c.entries=mejs.TrackFormatParser.parse(e);d();c.kind=="chapters"&&b.media.duration>0&&b.drawChapters(c)},error:function(){b.loadNextTrack()}})},enableTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||
|
136 |
+
a;this.captionsButton.find("input[value="+a+"]").prop("disabled",false).siblings("label").html(b);this.options.startLanguage==a&&f("#"+this.id+"_captions_"+a).click();this.adjustLanguageBox()},addTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("ul").append(f('<li><input type="radio" name="'+this.id+'_captions" id="'+this.id+"_captions_"+a+'" value="'+a+'" disabled="disabled" /><label for="'+this.id+"_captions_"+a+'">'+b+" (loading)</label></li>"));this.adjustLanguageBox();
|
137 |
+
this.container.find(".mejs-captions-translations option[value="+a+"]").remove()},adjustLanguageBox:function(){this.captionsButton.find(".mejs-captions-selector").height(this.captionsButton.find(".mejs-captions-selector ul").outerHeight(true)+this.captionsButton.find(".mejs-captions-translations").outerHeight(true))},displayCaptions:function(){if(typeof this.tracks!="undefined"){var a,b=this.selectedTrack;if(b!=null&&b.isLoaded)for(a=0;a<b.entries.times.length;a++)if(this.media.currentTime>=b.entries.times[a].start&&
|
138 |
+
this.media.currentTime<=b.entries.times[a].stop){this.captionsText.html(b.entries.text[a]);this.captions.show().height(0);return}this.captions.hide()}},displayChapters:function(){var a;for(a=0;a<this.tracks.length;a++)if(this.tracks[a].kind=="chapters"&&this.tracks[a].isLoaded){this.drawChapters(this.tracks[a]);this.hasChapters=true;break}},drawChapters:function(a){var b=this,c,d,e=d=0;b.chapters.empty();for(c=0;c<a.entries.times.length;c++){d=a.entries.times[c].stop-a.entries.times[c].start;d=Math.floor(d/
|
139 |
+
b.media.duration*100);if(d+e>100||c==a.entries.times.length-1&&d+e<100)d=100-e;b.chapters.append(f('<div class="mejs-chapter" rel="'+a.entries.times[c].start+'" style="left: '+e.toString()+"%;width: "+d.toString()+'%;"><div class="mejs-chapter-block'+(c==a.entries.times.length-1?" mejs-chapter-block-last":"")+'"><span class="ch-title">'+a.entries.text[c]+'</span><span class="ch-time">'+mejs.Utility.secondsToTimeCode(a.entries.times[c].start)+"–"+mejs.Utility.secondsToTimeCode(a.entries.times[c].stop)+
|
140 |
+
"</span></div></div>"));e+=d}b.chapters.find("div.mejs-chapter").click(function(){b.media.setCurrentTime(parseFloat(f(this).attr("rel")));b.media.paused&&b.media.play()});b.chapters.show()}});mejs.language={codes:{af:"Afrikaans",sq:"Albanian",ar:"Arabic",be:"Belarusian",bg:"Bulgarian",ca:"Catalan",zh:"Chinese","zh-cn":"Chinese Simplified","zh-tw":"Chinese Traditional",hr:"Croatian",cs:"Czech",da:"Danish",nl:"Dutch",en:"English",et:"Estonian",tl:"Filipino",fi:"Finnish",fr:"French",gl:"Galician",de:"German",
|
141 |
+
el:"Greek",ht:"Haitian Creole",iw:"Hebrew",hi:"Hindi",hu:"Hungarian",is:"Icelandic",id:"Indonesian",ga:"Irish",it:"Italian",ja:"Japanese",ko:"Korean",lv:"Latvian",lt:"Lithuanian",mk:"Macedonian",ms:"Malay",mt:"Maltese",no:"Norwegian",fa:"Persian",pl:"Polish",pt:"Portuguese",ro:"Romanian",ru:"Russian",sr:"Serbian",sk:"Slovak",sl:"Slovenian",es:"Spanish",sw:"Swahili",sv:"Swedish",tl:"Tagalog",th:"Thai",tr:"Turkish",uk:"Ukrainian",vi:"Vietnamese",cy:"Welsh",yi:"Yiddish"}};mejs.TrackFormatParser={pattern_identifier:/^([a-zA-z]+-)?[0-9]+$/,
|
142 |
+
pattern_timecode:/^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/,split2:function(a,b){return a.split(b)},parse:function(a){var b=0;a=this.split2(a,/\r?\n/);for(var c={text:[],times:[]},d,e;b<a.length;b++)if(this.pattern_identifier.exec(a[b])){b++;if((d=this.pattern_timecode.exec(a[b]))&&b<a.length){b++;e=a[b];for(b++;a[b]!==""&&b<a.length;){e=e+"\n"+a[b];b++}c.text.push(e);c.times.push({start:mejs.Utility.timeCodeToSeconds(d[1]),stop:mejs.Utility.timeCodeToSeconds(d[3]),
|
143 |
+
settings:d[5]})}}return c}};if("x\n\ny".split(/\n/gi).length!=3)mejs.TrackFormatParser.split2=function(a,b){var c=[],d="",e;for(e=0;e<a.length;e++){d+=a.substring(e,e+1);if(b.test(d)){c.push(d.replace(b,""));d=""}}c.push(d);return c}})(mejs.$);
|
144 |
+
(function(f){f.extend(mejs.MepDefaults,{contextMenuItems:[{render:function(a){if(typeof a.enterFullScreen=="undefined")return null;return a.isFullScreen?"Turn off Fullscreen":"Go Fullscreen"},click:function(a){a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}},{render:function(a){return a.media.muted?"Unmute":"Mute"},click:function(a){a.media.muted?a.setMuted(false):a.setMuted(true)}},{isSeparator:true},{render:function(){return"Download Video"},click:function(a){window.location.href=a.media.currentSrc}}]});
|
145 |
+
f.extend(MediaElementPlayer.prototype,{buildcontextmenu:function(a){a.contextMenu=f('<div class="mejs-contextmenu"></div>').appendTo(f("body")).hide();a.container.bind("contextmenu",function(b){if(a.isContextMenuEnabled){b.preventDefault();a.renderContextMenu(b.clientX-1,b.clientY-1);return false}});a.container.bind("click",function(){a.contextMenu.hide()});a.contextMenu.bind("mouseleave",function(){a.startContextMenuTimer()})},isContextMenuEnabled:true,enableContextMenu:function(){this.isContextMenuEnabled=
|
146 |
+
true},disableContextMenu:function(){this.isContextMenuEnabled=false},contextMenuTimeout:null,startContextMenuTimer:function(){var a=this;a.killContextMenuTimer();a.contextMenuTimer=setTimeout(function(){a.hideContextMenu();a.killContextMenuTimer()},750)},killContextMenuTimer:function(){var a=this.contextMenuTimer;if(a!=null){clearTimeout(a);delete a}},hideContextMenu:function(){this.contextMenu.hide()},renderContextMenu:function(a,b){for(var c=this,d="",e=c.options.contextMenuItems,g=0,k=e.length;g<
|
147 |
+
k;g++)if(e[g].isSeparator)d+='<div class="mejs-contextmenu-separator"></div>';else{var h=e[g].render(c);if(h!=null)d+='<div class="mejs-contextmenu-item" data-itemindex="'+g+'" id="element-'+Math.random()*1E6+'">'+h+"</div>"}c.contextMenu.empty().append(f(d)).css({top:b,left:a}).show();c.contextMenu.find(".mejs-contextmenu-item").each(function(){var o=f(this),n=parseInt(o.data("itemindex"),10),p=c.options.contextMenuItems[n];typeof p.show!="undefined"&&p.show(o,c);o.click(function(){typeof p.click!=
|
148 |
+
"undefined"&&p.click(c);c.contextMenu.hide()})});setTimeout(function(){c.killControlsTimer("rev3")},100)}})})(mejs.$);
|
149 |
+
|
includes/media-element/mediaelement.js
ADDED
@@ -0,0 +1,1517 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* MediaElement.js
|
3 |
+
* HTML5 <video> and <audio> shim and player
|
4 |
+
* http://mediaelementjs.com/
|
5 |
+
*
|
6 |
+
* Creates a JavaScript object that mimics HTML5 MediaElement API
|
7 |
+
* for browsers that don't understand HTML5 or can't play the provided codec
|
8 |
+
* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
|
9 |
+
*
|
10 |
+
* Copyright 2010-2012, John Dyer (http://j.hn)
|
11 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
12 |
+
*
|
13 |
+
*/
|
14 |
+
// Namespace
|
15 |
+
var mejs = mejs || {};
|
16 |
+
|
17 |
+
// version number
|
18 |
+
mejs.version = '2.9.1';
|
19 |
+
|
20 |
+
// player number (for missing, same id attr)
|
21 |
+
mejs.meIndex = 0;
|
22 |
+
|
23 |
+
// media types accepted by plugins
|
24 |
+
mejs.plugins = {
|
25 |
+
silverlight: [
|
26 |
+
{version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
|
27 |
+
],
|
28 |
+
flash: [
|
29 |
+
{version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg', 'video/youtube', 'video/x-youtube']}
|
30 |
+
//,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!)
|
31 |
+
],
|
32 |
+
youtube: [
|
33 |
+
{version: null, types: ['video/youtube', 'video/x-youtube']}
|
34 |
+
],
|
35 |
+
vimeo: [
|
36 |
+
{version: null, types: ['video/vimeo']}
|
37 |
+
]
|
38 |
+
};
|
39 |
+
|
40 |
+
/*
|
41 |
+
Utility methods
|
42 |
+
*/
|
43 |
+
mejs.Utility = {
|
44 |
+
encodeUrl: function(url) {
|
45 |
+
return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
|
46 |
+
},
|
47 |
+
escapeHTML: function(s) {
|
48 |
+
return s.toString().split('&').join('&').split('<').join('<').split('"').join('"');
|
49 |
+
},
|
50 |
+
absolutizeUrl: function(url) {
|
51 |
+
var el = document.createElement('div');
|
52 |
+
el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
|
53 |
+
return el.firstChild.href;
|
54 |
+
},
|
55 |
+
getScriptPath: function(scriptNames) {
|
56 |
+
var
|
57 |
+
i = 0,
|
58 |
+
j,
|
59 |
+
path = '',
|
60 |
+
name = '',
|
61 |
+
script,
|
62 |
+
scripts = document.getElementsByTagName('script'),
|
63 |
+
il = scripts.length,
|
64 |
+
jl = scriptNames.length;
|
65 |
+
|
66 |
+
for (; i < il; i++) {
|
67 |
+
script = scripts[i].src;
|
68 |
+
for (j = 0; j < jl; j++) {
|
69 |
+
name = scriptNames[j];
|
70 |
+
if (script.indexOf(name) > -1) {
|
71 |
+
path = script.substring(0, script.indexOf(name));
|
72 |
+
break;
|
73 |
+
}
|
74 |
+
}
|
75 |
+
if (path !== '') {
|
76 |
+
break;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
return path;
|
80 |
+
},
|
81 |
+
secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
|
82 |
+
//add framecount
|
83 |
+
if (typeof showFrameCount == 'undefined') {
|
84 |
+
showFrameCount=false;
|
85 |
+
} else if(typeof fps == 'undefined') {
|
86 |
+
fps = 25;
|
87 |
+
}
|
88 |
+
|
89 |
+
var hours = Math.floor(time / 3600) % 24,
|
90 |
+
minutes = Math.floor(time / 60) % 60,
|
91 |
+
seconds = Math.floor(time % 60),
|
92 |
+
frames = Math.floor(((time % 1)*fps).toFixed(3)),
|
93 |
+
result =
|
94 |
+
( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
|
95 |
+
+ (minutes < 10 ? '0' + minutes : minutes) + ':'
|
96 |
+
+ (seconds < 10 ? '0' + seconds : seconds)
|
97 |
+
+ ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
|
98 |
+
|
99 |
+
return result;
|
100 |
+
},
|
101 |
+
|
102 |
+
timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
|
103 |
+
if (typeof showFrameCount == 'undefined') {
|
104 |
+
showFrameCount=false;
|
105 |
+
} else if(typeof fps == 'undefined') {
|
106 |
+
fps = 25;
|
107 |
+
}
|
108 |
+
|
109 |
+
var tc_array = hh_mm_ss_ff.split(":"),
|
110 |
+
tc_hh = parseInt(tc_array[0], 10),
|
111 |
+
tc_mm = parseInt(tc_array[1], 10),
|
112 |
+
tc_ss = parseInt(tc_array[2], 10),
|
113 |
+
tc_ff = 0,
|
114 |
+
tc_in_seconds = 0;
|
115 |
+
|
116 |
+
if (showFrameCount) {
|
117 |
+
tc_ff = parseInt(tc_array[3])/fps;
|
118 |
+
}
|
119 |
+
|
120 |
+
tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
|
121 |
+
|
122 |
+
return tc_in_seconds;
|
123 |
+
},
|
124 |
+
|
125 |
+
/* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
|
126 |
+
removeSwf: function(id) {
|
127 |
+
var obj = document.getElementById(id);
|
128 |
+
if (obj && obj.nodeName == "OBJECT") {
|
129 |
+
if (mejs.MediaFeatures.isIE) {
|
130 |
+
obj.style.display = "none";
|
131 |
+
(function(){
|
132 |
+
if (obj.readyState == 4) {
|
133 |
+
mejs.Utility.removeObjectInIE(id);
|
134 |
+
} else {
|
135 |
+
setTimeout(arguments.callee, 10);
|
136 |
+
}
|
137 |
+
})();
|
138 |
+
} else {
|
139 |
+
obj.parentNode.removeChild(obj);
|
140 |
+
}
|
141 |
+
}
|
142 |
+
},
|
143 |
+
removeObjectInIE: function(id) {
|
144 |
+
var obj = document.getElementById(id);
|
145 |
+
if (obj) {
|
146 |
+
for (var i in obj) {
|
147 |
+
if (typeof obj[i] == "function") {
|
148 |
+
obj[i] = null;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
obj.parentNode.removeChild(obj);
|
152 |
+
}
|
153 |
+
}
|
154 |
+
};
|
155 |
+
|
156 |
+
|
157 |
+
// Core detector, plugins are added below
|
158 |
+
mejs.PluginDetector = {
|
159 |
+
|
160 |
+
// main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
|
161 |
+
hasPluginVersion: function(plugin, v) {
|
162 |
+
var pv = this.plugins[plugin];
|
163 |
+
v[1] = v[1] || 0;
|
164 |
+
v[2] = v[2] || 0;
|
165 |
+
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
|
166 |
+
},
|
167 |
+
|
168 |
+
// cached values
|
169 |
+
nav: window.navigator,
|
170 |
+
ua: window.navigator.userAgent.toLowerCase(),
|
171 |
+
|
172 |
+
// stored version numbers
|
173 |
+
plugins: [],
|
174 |
+
|
175 |
+
// runs detectPlugin() and stores the version number
|
176 |
+
addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
|
177 |
+
this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
|
178 |
+
},
|
179 |
+
|
180 |
+
// get the version number from the mimetype (all but IE) or ActiveX (IE)
|
181 |
+
detectPlugin: function(pluginName, mimeType, activeX, axDetect) {
|
182 |
+
|
183 |
+
var version = [0,0,0],
|
184 |
+
description,
|
185 |
+
i,
|
186 |
+
ax;
|
187 |
+
|
188 |
+
// Firefox, Webkit, Opera
|
189 |
+
if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
|
190 |
+
description = this.nav.plugins[pluginName].description;
|
191 |
+
if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
|
192 |
+
version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
|
193 |
+
for (i=0; i<version.length; i++) {
|
194 |
+
version[i] = parseInt(version[i].match(/\d+/), 10);
|
195 |
+
}
|
196 |
+
}
|
197 |
+
// Internet Explorer / ActiveX
|
198 |
+
} else if (typeof(window.ActiveXObject) != 'undefined') {
|
199 |
+
try {
|
200 |
+
ax = new ActiveXObject(activeX);
|
201 |
+
if (ax) {
|
202 |
+
version = axDetect(ax);
|
203 |
+
}
|
204 |
+
}
|
205 |
+
catch (e) { }
|
206 |
+
}
|
207 |
+
return version;
|
208 |
+
}
|
209 |
+
};
|
210 |
+
|
211 |
+
// Add Flash detection
|
212 |
+
mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
|
213 |
+
// adapted from SWFObject
|
214 |
+
var version = [],
|
215 |
+
d = ax.GetVariable("$version");
|
216 |
+
if (d) {
|
217 |
+
d = d.split(" ")[1].split(",");
|
218 |
+
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
219 |
+
}
|
220 |
+
return version;
|
221 |
+
});
|
222 |
+
|
223 |
+
// Add Silverlight detection
|
224 |
+
mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
|
225 |
+
// Silverlight cannot report its version number to IE
|
226 |
+
// but it does have a isVersionSupported function, so we have to loop through it to get a version number.
|
227 |
+
// adapted from http://www.silverlightversion.com/
|
228 |
+
var v = [0,0,0,0],
|
229 |
+
loopMatch = function(ax, v, i, n) {
|
230 |
+
while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
|
231 |
+
v[i]+=n;
|
232 |
+
}
|
233 |
+
v[i] -= n;
|
234 |
+
};
|
235 |
+
loopMatch(ax, v, 0, 1);
|
236 |
+
loopMatch(ax, v, 1, 1);
|
237 |
+
loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
|
238 |
+
loopMatch(ax, v, 2, 1000);
|
239 |
+
loopMatch(ax, v, 2, 100);
|
240 |
+
loopMatch(ax, v, 2, 10);
|
241 |
+
loopMatch(ax, v, 2, 1);
|
242 |
+
loopMatch(ax, v, 3, 1);
|
243 |
+
|
244 |
+
return v;
|
245 |
+
});
|
246 |
+
// add adobe acrobat
|
247 |
+
/*
|
248 |
+
PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) {
|
249 |
+
var version = [],
|
250 |
+
d = ax.GetVersions().split(',')[0].split('=')[1].split('.');
|
251 |
+
|
252 |
+
if (d) {
|
253 |
+
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
254 |
+
}
|
255 |
+
return version;
|
256 |
+
});
|
257 |
+
*/
|
258 |
+
// necessary detection (fixes for <IE9)
|
259 |
+
mejs.MediaFeatures = {
|
260 |
+
init: function() {
|
261 |
+
var
|
262 |
+
t = this,
|
263 |
+
d = document,
|
264 |
+
nav = mejs.PluginDetector.nav,
|
265 |
+
ua = mejs.PluginDetector.ua.toLowerCase(),
|
266 |
+
i,
|
267 |
+
v,
|
268 |
+
html5Elements = ['source','track','audio','video'];
|
269 |
+
|
270 |
+
// detect browsers (only the ones that have some kind of quirk we need to work around)
|
271 |
+
t.isiPad = (ua.match(/ipad/i) !== null);
|
272 |
+
t.isiPhone = (ua.match(/iphone/i) !== null);
|
273 |
+
t.isiOS = t.isiPhone || t.isiPad;
|
274 |
+
t.isAndroid = (ua.match(/android/i) !== null);
|
275 |
+
t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
|
276 |
+
t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
|
277 |
+
t.isChrome = (ua.match(/chrome/gi) !== null);
|
278 |
+
t.isFirefox = (ua.match(/firefox/gi) !== null);
|
279 |
+
t.isWebkit = (ua.match(/webkit/gi) !== null);
|
280 |
+
t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit;
|
281 |
+
t.isOpera = (ua.match(/opera/gi) !== null);
|
282 |
+
t.hasTouch = ('ontouchstart' in window);
|
283 |
+
|
284 |
+
// create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
|
285 |
+
for (i=0; i<html5Elements.length; i++) {
|
286 |
+
v = document.createElement(html5Elements[i]);
|
287 |
+
}
|
288 |
+
|
289 |
+
t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid);
|
290 |
+
|
291 |
+
// detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails)
|
292 |
+
|
293 |
+
// iOS
|
294 |
+
t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined');
|
295 |
+
|
296 |
+
// Webkit/firefox
|
297 |
+
t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
|
298 |
+
t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined');
|
299 |
+
|
300 |
+
t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen);
|
301 |
+
t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen;
|
302 |
+
if (t.hasMozNativeFullScreen) {
|
303 |
+
t.nativeFullScreenEnabled = v.mozFullScreenEnabled;
|
304 |
+
}
|
305 |
+
|
306 |
+
|
307 |
+
if (this.isChrome) {
|
308 |
+
t.hasSemiNativeFullScreen = false;
|
309 |
+
}
|
310 |
+
|
311 |
+
if (t.hasTrueNativeFullScreen) {
|
312 |
+
t.fullScreenEventName = (t.hasWebkitNativeFullScreen) ? 'webkitfullscreenchange' : 'mozfullscreenchange';
|
313 |
+
|
314 |
+
|
315 |
+
t.isFullScreen = function() {
|
316 |
+
if (v.mozRequestFullScreen) {
|
317 |
+
return d.mozFullScreen;
|
318 |
+
} else if (v.webkitRequestFullScreen) {
|
319 |
+
return d.webkitIsFullScreen;
|
320 |
+
}
|
321 |
+
}
|
322 |
+
|
323 |
+
t.requestFullScreen = function(el) {
|
324 |
+
|
325 |
+
if (t.hasWebkitNativeFullScreen) {
|
326 |
+
el.webkitRequestFullScreen();
|
327 |
+
} else if (t.hasMozNativeFullScreen) {
|
328 |
+
el.mozRequestFullScreen();
|
329 |
+
}
|
330 |
+
}
|
331 |
+
|
332 |
+
t.cancelFullScreen = function() {
|
333 |
+
if (t.hasWebkitNativeFullScreen) {
|
334 |
+
document.webkitCancelFullScreen();
|
335 |
+
} else if (t.hasMozNativeFullScreen) {
|
336 |
+
document.mozCancelFullScreen();
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
}
|
341 |
+
|
342 |
+
|
343 |
+
// OS X 10.5 can't do this even if it says it can :(
|
344 |
+
if (t.hasSemiNativeFullScreen && ua.match(/mac os x 10_5/i)) {
|
345 |
+
t.hasNativeFullScreen = false;
|
346 |
+
t.hasSemiNativeFullScreen = false;
|
347 |
+
}
|
348 |
+
|
349 |
+
}
|
350 |
+
};
|
351 |
+
mejs.MediaFeatures.init();
|
352 |
+
|
353 |
+
|
354 |
+
/*
|
355 |
+
extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
|
356 |
+
*/
|
357 |
+
mejs.HtmlMediaElement = {
|
358 |
+
pluginType: 'native',
|
359 |
+
isFullScreen: false,
|
360 |
+
|
361 |
+
setCurrentTime: function (time) {
|
362 |
+
this.currentTime = time;
|
363 |
+
},
|
364 |
+
|
365 |
+
setMuted: function (muted) {
|
366 |
+
this.muted = muted;
|
367 |
+
},
|
368 |
+
|
369 |
+
setVolume: function (volume) {
|
370 |
+
this.volume = volume;
|
371 |
+
},
|
372 |
+
|
373 |
+
// for parity with the plugin versions
|
374 |
+
stop: function () {
|
375 |
+
this.pause();
|
376 |
+
},
|
377 |
+
|
378 |
+
// This can be a url string
|
379 |
+
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
380 |
+
setSrc: function (url) {
|
381 |
+
|
382 |
+
// Fix for IE9 which can't set .src when there are <source> elements. Awesome, right?
|
383 |
+
var
|
384 |
+
existingSources = this.getElementsByTagName('source');
|
385 |
+
while (existingSources.length > 0){
|
386 |
+
this.removeChild(existingSources[0]);
|
387 |
+
}
|
388 |
+
|
389 |
+
if (typeof url == 'string') {
|
390 |
+
this.src = url;
|
391 |
+
} else {
|
392 |
+
var i, media;
|
393 |
+
|
394 |
+
for (i=0; i<url.length; i++) {
|
395 |
+
media = url[i];
|
396 |
+
if (this.canPlayType(media.type)) {
|
397 |
+
this.src = media.src;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
}
|
401 |
+
},
|
402 |
+
|
403 |
+
setVideoSize: function (width, height) {
|
404 |
+
this.width = width;
|
405 |
+
this.height = height;
|
406 |
+
}
|
407 |
+
};
|
408 |
+
|
409 |
+
/*
|
410 |
+
Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember]
|
411 |
+
*/
|
412 |
+
mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
|
413 |
+
this.id = pluginid;
|
414 |
+
this.pluginType = pluginType;
|
415 |
+
this.src = mediaUrl;
|
416 |
+
this.events = {};
|
417 |
+
};
|
418 |
+
|
419 |
+
// JavaScript values and ExternalInterface methods that match HTML5 video properties methods
|
420 |
+
// http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html
|
421 |
+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
422 |
+
mejs.PluginMediaElement.prototype = {
|
423 |
+
|
424 |
+
// special
|
425 |
+
pluginElement: null,
|
426 |
+
pluginType: '',
|
427 |
+
isFullScreen: false,
|
428 |
+
|
429 |
+
// not implemented :(
|
430 |
+
playbackRate: -1,
|
431 |
+
defaultPlaybackRate: -1,
|
432 |
+
seekable: [],
|
433 |
+
played: [],
|
434 |
+
|
435 |
+
// HTML5 read-only properties
|
436 |
+
paused: true,
|
437 |
+
ended: false,
|
438 |
+
seeking: false,
|
439 |
+
duration: 0,
|
440 |
+
error: null,
|
441 |
+
tagName: '',
|
442 |
+
|
443 |
+
// HTML5 get/set properties, but only set (updated by event handlers)
|
444 |
+
muted: false,
|
445 |
+
volume: 1,
|
446 |
+
currentTime: 0,
|
447 |
+
|
448 |
+
// HTML5 methods
|
449 |
+
play: function () {
|
450 |
+
if (this.pluginApi != null) {
|
451 |
+
if (this.pluginType == 'youtube') {
|
452 |
+
this.pluginApi.playVideo();
|
453 |
+
} else {
|
454 |
+
this.pluginApi.playMedia();
|
455 |
+
}
|
456 |
+
this.paused = false;
|
457 |
+
}
|
458 |
+
},
|
459 |
+
load: function () {
|
460 |
+
if (this.pluginApi != null) {
|
461 |
+
if (this.pluginType == 'youtube') {
|
462 |
+
} else {
|
463 |
+
this.pluginApi.loadMedia();
|
464 |
+
}
|
465 |
+
|
466 |
+
this.paused = false;
|
467 |
+
}
|
468 |
+
},
|
469 |
+
pause: function () {
|
470 |
+
if (this.pluginApi != null) {
|
471 |
+
if (this.pluginType == 'youtube') {
|
472 |
+
this.pluginApi.pauseVideo();
|
473 |
+
} else {
|
474 |
+
this.pluginApi.pauseMedia();
|
475 |
+
}
|
476 |
+
|
477 |
+
|
478 |
+
this.paused = true;
|
479 |
+
}
|
480 |
+
},
|
481 |
+
stop: function () {
|
482 |
+
if (this.pluginApi != null) {
|
483 |
+
if (this.pluginType == 'youtube') {
|
484 |
+
this.pluginApi.stopVideo();
|
485 |
+
} else {
|
486 |
+
this.pluginApi.stopMedia();
|
487 |
+
}
|
488 |
+
this.paused = true;
|
489 |
+
}
|
490 |
+
},
|
491 |
+
canPlayType: function(type) {
|
492 |
+
var i,
|
493 |
+
j,
|
494 |
+
pluginInfo,
|
495 |
+
pluginVersions = mejs.plugins[this.pluginType];
|
496 |
+
|
497 |
+
for (i=0; i<pluginVersions.length; i++) {
|
498 |
+
pluginInfo = pluginVersions[i];
|
499 |
+
|
500 |
+
// test if user has the correct plugin version
|
501 |
+
if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) {
|
502 |
+
|
503 |
+
// test for plugin playback types
|
504 |
+
for (j=0; j<pluginInfo.types.length; j++) {
|
505 |
+
// find plugin that can play the type
|
506 |
+
if (type == pluginInfo.types[j]) {
|
507 |
+
return true;
|
508 |
+
}
|
509 |
+
}
|
510 |
+
}
|
511 |
+
}
|
512 |
+
|
513 |
+
return false;
|
514 |
+
},
|
515 |
+
|
516 |
+
positionFullscreenButton: function(x,y,visibleAndAbove) {
|
517 |
+
if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) {
|
518 |
+
this.pluginApi.positionFullscreenButton(x,y,visibleAndAbove);
|
519 |
+
}
|
520 |
+
},
|
521 |
+
|
522 |
+
hideFullscreenButton: function() {
|
523 |
+
if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) {
|
524 |
+
this.pluginApi.hideFullscreenButton();
|
525 |
+
}
|
526 |
+
},
|
527 |
+
|
528 |
+
|
529 |
+
// custom methods since not all JavaScript implementations support get/set
|
530 |
+
|
531 |
+
// This can be a url string
|
532 |
+
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
533 |
+
setSrc: function (url) {
|
534 |
+
if (typeof url == 'string') {
|
535 |
+
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url));
|
536 |
+
this.src = mejs.Utility.absolutizeUrl(url);
|
537 |
+
} else {
|
538 |
+
var i, media;
|
539 |
+
|
540 |
+
for (i=0; i<url.length; i++) {
|
541 |
+
media = url[i];
|
542 |
+
if (this.canPlayType(media.type)) {
|
543 |
+
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
|
544 |
+
this.src = mejs.Utility.absolutizeUrl(url);
|
545 |
+
}
|
546 |
+
}
|
547 |
+
}
|
548 |
+
|
549 |
+
},
|
550 |
+
setCurrentTime: function (time) {
|
551 |
+
if (this.pluginApi != null) {
|
552 |
+
if (this.pluginType == 'youtube') {
|
553 |
+
this.pluginApi.seekTo(time);
|
554 |
+
} else {
|
555 |
+
this.pluginApi.setCurrentTime(time);
|
556 |
+
}
|
557 |
+
|
558 |
+
|
559 |
+
|
560 |
+
this.currentTime = time;
|
561 |
+
}
|
562 |
+
},
|
563 |
+
setVolume: function (volume) {
|
564 |
+
if (this.pluginApi != null) {
|
565 |
+
// same on YouTube and MEjs
|
566 |
+
if (this.pluginType == 'youtube') {
|
567 |
+
this.pluginApi.setVolume(volume * 100);
|
568 |
+
} else {
|
569 |
+
this.pluginApi.setVolume(volume);
|
570 |
+
}
|
571 |
+
this.volume = volume;
|
572 |
+
}
|
573 |
+
},
|
574 |
+
setMuted: function (muted) {
|
575 |
+
if (this.pluginApi != null) {
|
576 |
+
if (this.pluginType == 'youtube') {
|
577 |
+
if (muted) {
|
578 |
+
this.pluginApi.mute();
|
579 |
+
} else {
|
580 |
+
this.pluginApi.unMute();
|
581 |
+
}
|
582 |
+
this.muted = muted;
|
583 |
+
this.dispatchEvent('volumechange');
|
584 |
+
} else {
|
585 |
+
this.pluginApi.setMuted(muted);
|
586 |
+
}
|
587 |
+
this.muted = muted;
|
588 |
+
}
|
589 |
+
},
|
590 |
+
|
591 |
+
// additional non-HTML5 methods
|
592 |
+
setVideoSize: function (width, height) {
|
593 |
+
|
594 |
+
//if (this.pluginType == 'flash' || this.pluginType == 'silverlight') {
|
595 |
+
if ( this.pluginElement.style) {
|
596 |
+
this.pluginElement.style.width = width + 'px';
|
597 |
+
this.pluginElement.style.height = height + 'px';
|
598 |
+
}
|
599 |
+
if (this.pluginApi != null && this.pluginApi.setVideoSize) {
|
600 |
+
this.pluginApi.setVideoSize(width, height);
|
601 |
+
}
|
602 |
+
//}
|
603 |
+
},
|
604 |
+
|
605 |
+
setFullscreen: function (fullscreen) {
|
606 |
+
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
607 |
+
this.pluginApi.setFullscreen(fullscreen);
|
608 |
+
}
|
609 |
+
},
|
610 |
+
|
611 |
+
enterFullScreen: function() {
|
612 |
+
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
613 |
+
this.setFullscreen(true);
|
614 |
+
}
|
615 |
+
|
616 |
+
},
|
617 |
+
|
618 |
+
exitFullScreen: function() {
|
619 |
+
if (this.pluginApi != null && this.pluginApi.setFullscreen) {
|
620 |
+
this.setFullscreen(false);
|
621 |
+
}
|
622 |
+
},
|
623 |
+
|
624 |
+
// start: fake events
|
625 |
+
addEventListener: function (eventName, callback, bubble) {
|
626 |
+
this.events[eventName] = this.events[eventName] || [];
|
627 |
+
this.events[eventName].push(callback);
|
628 |
+
},
|
629 |
+
removeEventListener: function (eventName, callback) {
|
630 |
+
if (!eventName) { this.events = {}; return true; }
|
631 |
+
var callbacks = this.events[eventName];
|
632 |
+
if (!callbacks) return true;
|
633 |
+
if (!callback) { this.events[eventName] = []; return true; }
|
634 |
+
for (i = 0; i < callbacks.length; i++) {
|
635 |
+
if (callbacks[i] === callback) {
|
636 |
+
this.events[eventName].splice(i, 1);
|
637 |
+
return true;
|
638 |
+
}
|
639 |
+
}
|
640 |
+
return false;
|
641 |
+
},
|
642 |
+
dispatchEvent: function (eventName) {
|
643 |
+
var i,
|
644 |
+
args,
|
645 |
+
callbacks = this.events[eventName];
|
646 |
+
|
647 |
+
if (callbacks) {
|
648 |
+
args = Array.prototype.slice.call(arguments, 1);
|
649 |
+
for (i = 0; i < callbacks.length; i++) {
|
650 |
+
callbacks[i].apply(null, args);
|
651 |
+
}
|
652 |
+
}
|
653 |
+
},
|
654 |
+
// end: fake events
|
655 |
+
|
656 |
+
// fake DOM attribute methods
|
657 |
+
attributes: {},
|
658 |
+
hasAttribute: function(name){
|
659 |
+
return (name in this.attributes);
|
660 |
+
},
|
661 |
+
removeAttribute: function(name){
|
662 |
+
delete this.attributes[name];
|
663 |
+
},
|
664 |
+
getAttribute: function(name){
|
665 |
+
if (this.hasAttribute(name)) {
|
666 |
+
return this.attributes[name];
|
667 |
+
}
|
668 |
+
return '';
|
669 |
+
},
|
670 |
+
setAttribute: function(name, value){
|
671 |
+
this.attributes[name] = value;
|
672 |
+
},
|
673 |
+
|
674 |
+
remove: function() {
|
675 |
+
mejs.Utility.removeSwf(this.pluginElement.id);
|
676 |
+
}
|
677 |
+
};
|
678 |
+
|
679 |
+
// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
|
680 |
+
mejs.MediaPluginBridge = {
|
681 |
+
|
682 |
+
pluginMediaElements:{},
|
683 |
+
htmlMediaElements:{},
|
684 |
+
|
685 |
+
registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
|
686 |
+
this.pluginMediaElements[id] = pluginMediaElement;
|
687 |
+
this.htmlMediaElements[id] = htmlMediaElement;
|
688 |
+
},
|
689 |
+
|
690 |
+
// when Flash/Silverlight is ready, it calls out to this method
|
691 |
+
initPlugin: function (id) {
|
692 |
+
|
693 |
+
var pluginMediaElement = this.pluginMediaElements[id],
|
694 |
+
htmlMediaElement = this.htmlMediaElements[id];
|
695 |
+
|
696 |
+
if (pluginMediaElement) {
|
697 |
+
// find the javascript bridge
|
698 |
+
switch (pluginMediaElement.pluginType) {
|
699 |
+
case "flash":
|
700 |
+
pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
|
701 |
+
break;
|
702 |
+
case "silverlight":
|
703 |
+
pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
|
704 |
+
pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
|
705 |
+
break;
|
706 |
+
}
|
707 |
+
|
708 |
+
if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
|
709 |
+
pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
|
710 |
+
}
|
711 |
+
}
|
712 |
+
},
|
713 |
+
|
714 |
+
// receives events from Flash/Silverlight and sends them out as HTML5 media events
|
715 |
+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
716 |
+
fireEvent: function (id, eventName, values) {
|
717 |
+
|
718 |
+
var
|
719 |
+
e,
|
720 |
+
i,
|
721 |
+
bufferedTime,
|
722 |
+
pluginMediaElement = this.pluginMediaElements[id];
|
723 |
+
|
724 |
+
pluginMediaElement.ended = false;
|
725 |
+
pluginMediaElement.paused = true;
|
726 |
+
|
727 |
+
// fake event object to mimic real HTML media event.
|
728 |
+
e = {
|
729 |
+
type: eventName,
|
730 |
+
target: pluginMediaElement
|
731 |
+
};
|
732 |
+
|
733 |
+
// attach all values to element and event object
|
734 |
+
for (i in values) {
|
735 |
+
pluginMediaElement[i] = values[i];
|
736 |
+
e[i] = values[i];
|
737 |
+
}
|
738 |
+
|
739 |
+
// fake the newer W3C buffered TimeRange (loaded and total have been removed)
|
740 |
+
bufferedTime = values.bufferedTime || 0;
|
741 |
+
|
742 |
+
e.target.buffered = e.buffered = {
|
743 |
+
start: function(index) {
|
744 |
+
return 0;
|
745 |
+
},
|
746 |
+
end: function (index) {
|
747 |
+
return bufferedTime;
|
748 |
+
},
|
749 |
+
length: 1
|
750 |
+
};
|
751 |
+
|
752 |
+
pluginMediaElement.dispatchEvent(e.type, e);
|
753 |
+
}
|
754 |
+
};
|
755 |
+
|
756 |
+
/*
|
757 |
+
Default options
|
758 |
+
*/
|
759 |
+
mejs.MediaElementDefaults = {
|
760 |
+
// allows testing on HTML5, flash, silverlight
|
761 |
+
// auto: attempts to detect what the browser can do
|
762 |
+
// native: forces HTML5 playback
|
763 |
+
// shim: disallows HTML5, will attempt either Flash or Silverlight
|
764 |
+
// none: forces fallback view
|
765 |
+
mode: 'auto',
|
766 |
+
// remove or reorder to change plugin priority and availability
|
767 |
+
plugins: ['flash','silverlight','youtube','vimeo'],
|
768 |
+
// shows debug errors on screen
|
769 |
+
enablePluginDebug: false,
|
770 |
+
// overrides the type specified, useful for dynamic instantiation
|
771 |
+
type: '',
|
772 |
+
// path to Flash and Silverlight plugins
|
773 |
+
pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
|
774 |
+
// name of flash file
|
775 |
+
flashName: 'flashmediaelement.swf',
|
776 |
+
// turns on the smoothing filter in Flash
|
777 |
+
enablePluginSmoothing: false,
|
778 |
+
// name of silverlight file
|
779 |
+
silverlightName: 'silverlightmediaelement.xap',
|
780 |
+
// default if the <video width> is not specified
|
781 |
+
defaultVideoWidth: 480,
|
782 |
+
// default if the <video height> is not specified
|
783 |
+
defaultVideoHeight: 270,
|
784 |
+
// overrides <video width>
|
785 |
+
pluginWidth: -1,
|
786 |
+
// overrides <video height>
|
787 |
+
pluginHeight: -1,
|
788 |
+
// additional plugin variables in 'key=value' form
|
789 |
+
pluginVars: [],
|
790 |
+
// rate in milliseconds for Flash and Silverlight to fire the timeupdate event
|
791 |
+
// larger number is less accurate, but less strain on plugin->JavaScript bridge
|
792 |
+
timerRate: 250,
|
793 |
+
// initial volume for player
|
794 |
+
startVolume: 0.8,
|
795 |
+
success: function () { },
|
796 |
+
error: function () { }
|
797 |
+
};
|
798 |
+
|
799 |
+
/*
|
800 |
+
Determines if a browser supports the <video> or <audio> element
|
801 |
+
and returns either the native element or a Flash/Silverlight version that
|
802 |
+
mimics HTML5 MediaElement
|
803 |
+
*/
|
804 |
+
mejs.MediaElement = function (el, o) {
|
805 |
+
return mejs.HtmlMediaElementShim.create(el,o);
|
806 |
+
};
|
807 |
+
|
808 |
+
mejs.HtmlMediaElementShim = {
|
809 |
+
|
810 |
+
create: function(el, o) {
|
811 |
+
var
|
812 |
+
options = mejs.MediaElementDefaults,
|
813 |
+
htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el,
|
814 |
+
tagName = htmlMediaElement.tagName.toLowerCase(),
|
815 |
+
isMediaTag = (tagName === 'audio' || tagName === 'video'),
|
816 |
+
src = (isMediaTag) ? htmlMediaElement.getAttribute('src') : htmlMediaElement.getAttribute('href'),
|
817 |
+
poster = htmlMediaElement.getAttribute('poster'),
|
818 |
+
autoplay = htmlMediaElement.getAttribute('autoplay'),
|
819 |
+
preload = htmlMediaElement.getAttribute('preload'),
|
820 |
+
controls = htmlMediaElement.getAttribute('controls'),
|
821 |
+
playback,
|
822 |
+
prop;
|
823 |
+
|
824 |
+
// extend options
|
825 |
+
for (prop in o) {
|
826 |
+
options[prop] = o[prop];
|
827 |
+
}
|
828 |
+
|
829 |
+
// clean up attributes
|
830 |
+
src = (typeof src == 'undefined' || src === null || src == '') ? null : src;
|
831 |
+
poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
|
832 |
+
preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
|
833 |
+
autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
|
834 |
+
controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
|
835 |
+
|
836 |
+
// test for HTML5 and plugin capabilities
|
837 |
+
playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
|
838 |
+
playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '';
|
839 |
+
|
840 |
+
if (playback.method == 'native') {
|
841 |
+
// second fix for android
|
842 |
+
if (mejs.MediaFeatures.isBustedAndroid) {
|
843 |
+
htmlMediaElement.src = playback.url;
|
844 |
+
htmlMediaElement.addEventListener('click', function() {
|
845 |
+
htmlMediaElement.play();
|
846 |
+
}, false);
|
847 |
+
}
|
848 |
+
|
849 |
+
// add methods to native HTMLMediaElement
|
850 |
+
return this.updateNative(playback, options, autoplay, preload);
|
851 |
+
} else if (playback.method !== '') {
|
852 |
+
// create plugin to mimic HTMLMediaElement
|
853 |
+
|
854 |
+
return this.createPlugin( playback, options, poster, autoplay, preload, controls);
|
855 |
+
} else {
|
856 |
+
// boo, no HTML5, no Flash, no Silverlight.
|
857 |
+
this.createErrorMessage( playback, options, poster );
|
858 |
+
|
859 |
+
return this;
|
860 |
+
}
|
861 |
+
},
|
862 |
+
|
863 |
+
determinePlayback: function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) {
|
864 |
+
var
|
865 |
+
mediaFiles = [],
|
866 |
+
i,
|
867 |
+
j,
|
868 |
+
k,
|
869 |
+
l,
|
870 |
+
n,
|
871 |
+
type,
|
872 |
+
result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')},
|
873 |
+
pluginName,
|
874 |
+
pluginVersions,
|
875 |
+
pluginInfo,
|
876 |
+
dummy;
|
877 |
+
|
878 |
+
// STEP 1: Get URL and type from <video src> or <source src>
|
879 |
+
|
880 |
+
// supplied type overrides <video type> and <source type>
|
881 |
+
if (typeof options.type != 'undefined' && options.type !== '') {
|
882 |
+
|
883 |
+
// accept either string or array of types
|
884 |
+
if (typeof options.type == 'string') {
|
885 |
+
mediaFiles.push({type:options.type, url:src});
|
886 |
+
} else {
|
887 |
+
|
888 |
+
for (i=0; i<options.type.length; i++) {
|
889 |
+
mediaFiles.push({type:options.type[i], url:src});
|
890 |
+
}
|
891 |
+
}
|
892 |
+
|
893 |
+
// test for src attribute first
|
894 |
+
} else if (src !== null) {
|
895 |
+
type = this.formatType(src, htmlMediaElement.getAttribute('type'));
|
896 |
+
mediaFiles.push({type:type, url:src});
|
897 |
+
|
898 |
+
// then test for <source> elements
|
899 |
+
} else {
|
900 |
+
// test <source> types to see if they are usable
|
901 |
+
for (i = 0; i < htmlMediaElement.childNodes.length; i++) {
|
902 |
+
n = htmlMediaElement.childNodes[i];
|
903 |
+
if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
|
904 |
+
src = n.getAttribute('src');
|
905 |
+
type = this.formatType(src, n.getAttribute('type'));
|
906 |
+
mediaFiles.push({type:type, url:src});
|
907 |
+
}
|
908 |
+
}
|
909 |
+
}
|
910 |
+
|
911 |
+
// in the case of dynamicly created players
|
912 |
+
// check for audio types
|
913 |
+
if (!isMediaTag && mediaFiles.length > 0 && mediaFiles[0].url !== null && this.getTypeFromFile(mediaFiles[0].url).indexOf('audio') > -1) {
|
914 |
+
result.isVideo = false;
|
915 |
+
}
|
916 |
+
|
917 |
+
|
918 |
+
// STEP 2: Test for playback method
|
919 |
+
|
920 |
+
// special case for Android which sadly doesn't implement the canPlayType function (always returns '')
|
921 |
+
if (mejs.MediaFeatures.isBustedAndroid) {
|
922 |
+
htmlMediaElement.canPlayType = function(type) {
|
923 |
+
return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : '';
|
924 |
+
};
|
925 |
+
}
|
926 |
+
|
927 |
+
|
928 |
+
// test for native playback first
|
929 |
+
if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'native')) {
|
930 |
+
|
931 |
+
if (!isMediaTag) {
|
932 |
+
|
933 |
+
// create a real HTML5 Media Element
|
934 |
+
dummy = document.createElement( result.isVideo ? 'video' : 'audio');
|
935 |
+
htmlMediaElement.parentNode.insertBefore(dummy, htmlMediaElement);
|
936 |
+
htmlMediaElement.style.display = 'none';
|
937 |
+
|
938 |
+
// use this one from now on
|
939 |
+
result.htmlMediaElement = htmlMediaElement = dummy;
|
940 |
+
}
|
941 |
+
|
942 |
+
for (i=0; i<mediaFiles.length; i++) {
|
943 |
+
// normal check
|
944 |
+
if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
|
945 |
+
// special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
|
946 |
+
|| htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
|
947 |
+
result.method = 'native';
|
948 |
+
result.url = mediaFiles[i].url;
|
949 |
+
break;
|
950 |
+
}
|
951 |
+
}
|
952 |
+
|
953 |
+
if (result.method === 'native') {
|
954 |
+
if (result.url !== null) {
|
955 |
+
htmlMediaElement.src = result.url;
|
956 |
+
}
|
957 |
+
|
958 |
+
return result;
|
959 |
+
}
|
960 |
+
}
|
961 |
+
|
962 |
+
// if native playback didn't work, then test plugins
|
963 |
+
if (options.mode === 'auto' || options.mode === 'shim') {
|
964 |
+
for (i=0; i<mediaFiles.length; i++) {
|
965 |
+
type = mediaFiles[i].type;
|
966 |
+
|
967 |
+
// test all plugins in order of preference [silverlight, flash]
|
968 |
+
for (j=0; j<options.plugins.length; j++) {
|
969 |
+
|
970 |
+
pluginName = options.plugins[j];
|
971 |
+
|
972 |
+
// test version of plugin (for future features)
|
973 |
+
pluginVersions = mejs.plugins[pluginName];
|
974 |
+
|
975 |
+
for (k=0; k<pluginVersions.length; k++) {
|
976 |
+
pluginInfo = pluginVersions[k];
|
977 |
+
|
978 |
+
// test if user has the correct plugin version
|
979 |
+
|
980 |
+
// for youtube/vimeo
|
981 |
+
if (pluginInfo.version == null ||
|
982 |
+
|
983 |
+
mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
|
984 |
+
|
985 |
+
// test for plugin playback types
|
986 |
+
for (l=0; l<pluginInfo.types.length; l++) {
|
987 |
+
// find plugin that can play the type
|
988 |
+
if (type == pluginInfo.types[l]) {
|
989 |
+
result.method = pluginName;
|
990 |
+
result.url = mediaFiles[i].url;
|
991 |
+
return result;
|
992 |
+
}
|
993 |
+
}
|
994 |
+
}
|
995 |
+
}
|
996 |
+
}
|
997 |
+
}
|
998 |
+
}
|
999 |
+
|
1000 |
+
// what if there's nothing to play? just grab the first available
|
1001 |
+
if (result.method === '' && mediaFiles.length > 0) {
|
1002 |
+
result.url = mediaFiles[0].url;
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
return result;
|
1006 |
+
},
|
1007 |
+
|
1008 |
+
formatType: function(url, type) {
|
1009 |
+
var ext;
|
1010 |
+
|
1011 |
+
// if no type is supplied, fake it with the extension
|
1012 |
+
if (url && !type) {
|
1013 |
+
return this.getTypeFromFile(url);
|
1014 |
+
} else {
|
1015 |
+
// only return the mime part of the type in case the attribute contains the codec
|
1016 |
+
// see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
|
1017 |
+
// `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4`
|
1018 |
+
|
1019 |
+
if (type && ~type.indexOf(';')) {
|
1020 |
+
return type.substr(0, type.indexOf(';'));
|
1021 |
+
} else {
|
1022 |
+
return type;
|
1023 |
+
}
|
1024 |
+
}
|
1025 |
+
},
|
1026 |
+
|
1027 |
+
getTypeFromFile: function(url) {
|
1028 |
+
var ext = url.substring(url.lastIndexOf('.') + 1);
|
1029 |
+
return (/(mp4|m4v|ogg|ogv|webm|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + ext;
|
1030 |
+
},
|
1031 |
+
|
1032 |
+
createErrorMessage: function(playback, options, poster) {
|
1033 |
+
var
|
1034 |
+
htmlMediaElement = playback.htmlMediaElement,
|
1035 |
+
errorContainer = document.createElement('div');
|
1036 |
+
|
1037 |
+
errorContainer.className = 'me-cannotplay';
|
1038 |
+
|
1039 |
+
try {
|
1040 |
+
errorContainer.style.width = htmlMediaElement.width + 'px';
|
1041 |
+
errorContainer.style.height = htmlMediaElement.height + 'px';
|
1042 |
+
} catch (e) {}
|
1043 |
+
|
1044 |
+
errorContainer.innerHTML = (poster !== '') ?
|
1045 |
+
'<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
|
1046 |
+
'<a href="' + playback.url + '"><span>Download File</span></a>';
|
1047 |
+
|
1048 |
+
htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
|
1049 |
+
htmlMediaElement.style.display = 'none';
|
1050 |
+
|
1051 |
+
options.error(htmlMediaElement);
|
1052 |
+
},
|
1053 |
+
|
1054 |
+
createPlugin:function(playback, options, poster, autoplay, preload, controls) {
|
1055 |
+
var
|
1056 |
+
htmlMediaElement = playback.htmlMediaElement,
|
1057 |
+
width = 1,
|
1058 |
+
height = 1,
|
1059 |
+
pluginid = 'me_' + playback.method + '_' + (mejs.meIndex++),
|
1060 |
+
pluginMediaElement = new mejs.PluginMediaElement(pluginid, playback.method, playback.url),
|
1061 |
+
container = document.createElement('div'),
|
1062 |
+
specialIEContainer,
|
1063 |
+
node,
|
1064 |
+
initVars;
|
1065 |
+
|
1066 |
+
// copy tagName from html media element
|
1067 |
+
pluginMediaElement.tagName = htmlMediaElement.tagName
|
1068 |
+
|
1069 |
+
// copy attributes from html media element to plugin media element
|
1070 |
+
for (var i = 0; i < htmlMediaElement.attributes.length; i++) {
|
1071 |
+
var attribute = htmlMediaElement.attributes[i];
|
1072 |
+
if (attribute.specified == true) {
|
1073 |
+
pluginMediaElement.setAttribute(attribute.name, attribute.value);
|
1074 |
+
}
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
// check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
|
1078 |
+
node = htmlMediaElement.parentNode;
|
1079 |
+
while (node !== null && node.tagName.toLowerCase() != 'body') {
|
1080 |
+
if (node.parentNode.tagName.toLowerCase() == 'p') {
|
1081 |
+
node.parentNode.parentNode.insertBefore(node, node.parentNode);
|
1082 |
+
break;
|
1083 |
+
}
|
1084 |
+
node = node.parentNode;
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
if (playback.isVideo) {
|
1088 |
+
width = (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
|
1089 |
+
height = (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
|
1090 |
+
|
1091 |
+
// in case of '%' make sure it's encoded
|
1092 |
+
width = mejs.Utility.encodeUrl(width);
|
1093 |
+
height = mejs.Utility.encodeUrl(height);
|
1094 |
+
|
1095 |
+
} else {
|
1096 |
+
if (options.enablePluginDebug) {
|
1097 |
+
width = 320;
|
1098 |
+
height = 240;
|
1099 |
+
}
|
1100 |
+
}
|
1101 |
+
|
1102 |
+
// register plugin
|
1103 |
+
pluginMediaElement.success = options.success;
|
1104 |
+
mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
|
1105 |
+
|
1106 |
+
// add container (must be added to DOM before inserting HTML for IE)
|
1107 |
+
container.className = 'me-plugin';
|
1108 |
+
container.id = pluginid + '_container';
|
1109 |
+
|
1110 |
+
if (playback.isVideo) {
|
1111 |
+
htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
|
1112 |
+
} else {
|
1113 |
+
document.body.insertBefore(container, document.body.childNodes[0]);
|
1114 |
+
}
|
1115 |
+
|
1116 |
+
// flash/silverlight vars
|
1117 |
+
initVars = [
|
1118 |
+
'id=' + pluginid,
|
1119 |
+
'isvideo=' + ((playback.isVideo) ? "true" : "false"),
|
1120 |
+
'autoplay=' + ((autoplay) ? "true" : "false"),
|
1121 |
+
'preload=' + preload,
|
1122 |
+
'width=' + width,
|
1123 |
+
'startvolume=' + options.startVolume,
|
1124 |
+
'timerrate=' + options.timerRate,
|
1125 |
+
'height=' + height];
|
1126 |
+
|
1127 |
+
if (playback.url !== null) {
|
1128 |
+
if (playback.method == 'flash') {
|
1129 |
+
initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
|
1130 |
+
} else {
|
1131 |
+
initVars.push('file=' + playback.url);
|
1132 |
+
}
|
1133 |
+
}
|
1134 |
+
if (options.enablePluginDebug) {
|
1135 |
+
initVars.push('debug=true');
|
1136 |
+
}
|
1137 |
+
if (options.enablePluginSmoothing) {
|
1138 |
+
initVars.push('smoothing=true');
|
1139 |
+
}
|
1140 |
+
if (controls) {
|
1141 |
+
initVars.push('controls=true'); // shows controls in the plugin if desired
|
1142 |
+
}
|
1143 |
+
if (options.pluginVars) {
|
1144 |
+
initVars = initVars.concat(options.pluginVars);
|
1145 |
+
}
|
1146 |
+
|
1147 |
+
switch (playback.method) {
|
1148 |
+
case 'silverlight':
|
1149 |
+
container.innerHTML =
|
1150 |
+
'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '">' +
|
1151 |
+
'<param name="initParams" value="' + initVars.join(',') + '" />' +
|
1152 |
+
'<param name="windowless" value="true" />' +
|
1153 |
+
'<param name="background" value="black" />' +
|
1154 |
+
'<param name="minRuntimeVersion" value="3.0.0.0" />' +
|
1155 |
+
'<param name="autoUpgrade" value="true" />' +
|
1156 |
+
'<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' +
|
1157 |
+
'</object>';
|
1158 |
+
break;
|
1159 |
+
|
1160 |
+
case 'flash':
|
1161 |
+
|
1162 |
+
if (mejs.MediaFeatures.isIE) {
|
1163 |
+
specialIEContainer = document.createElement('div');
|
1164 |
+
container.appendChild(specialIEContainer);
|
1165 |
+
specialIEContainer.outerHTML =
|
1166 |
+
'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
|
1167 |
+
'id="' + pluginid + '" width="' + width + '" height="' + height + '">' +
|
1168 |
+
'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
|
1169 |
+
'<param name="flashvars" value="' + initVars.join('&') + '" />' +
|
1170 |
+
'<param name="quality" value="high" />' +
|
1171 |
+
'<param name="bgcolor" value="#000000" />' +
|
1172 |
+
'<param name="wmode" value="transparent" />' +
|
1173 |
+
'<param name="allowScriptAccess" value="always" />' +
|
1174 |
+
'<param name="allowFullScreen" value="true" />' +
|
1175 |
+
'</object>';
|
1176 |
+
|
1177 |
+
} else {
|
1178 |
+
|
1179 |
+
container.innerHTML =
|
1180 |
+
'<embed id="' + pluginid + '" name="' + pluginid + '" ' +
|
1181 |
+
'play="true" ' +
|
1182 |
+
'loop="false" ' +
|
1183 |
+
'quality="high" ' +
|
1184 |
+
'bgcolor="#000000" ' +
|
1185 |
+
'wmode="transparent" ' +
|
1186 |
+
'allowScriptAccess="always" ' +
|
1187 |
+
'allowFullScreen="true" ' +
|
1188 |
+
'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' +
|
1189 |
+
'src="' + options.pluginPath + options.flashName + '" ' +
|
1190 |
+
'flashvars="' + initVars.join('&') + '" ' +
|
1191 |
+
'width="' + width + '" ' +
|
1192 |
+
'height="' + height + '"></embed>';
|
1193 |
+
}
|
1194 |
+
break;
|
1195 |
+
|
1196 |
+
case 'youtube':
|
1197 |
+
|
1198 |
+
|
1199 |
+
var
|
1200 |
+
videoId = playback.url.substr(playback.url.lastIndexOf('=')+1);
|
1201 |
+
youtubeSettings = {
|
1202 |
+
container: container,
|
1203 |
+
containerId: container.id,
|
1204 |
+
pluginMediaElement: pluginMediaElement,
|
1205 |
+
pluginId: pluginid,
|
1206 |
+
videoId: videoId,
|
1207 |
+
height: height,
|
1208 |
+
width: width
|
1209 |
+
};
|
1210 |
+
|
1211 |
+
if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) {
|
1212 |
+
mejs.YouTubeApi.createFlash(youtubeSettings);
|
1213 |
+
} else {
|
1214 |
+
mejs.YouTubeApi.enqueueIframe(youtubeSettings);
|
1215 |
+
}
|
1216 |
+
|
1217 |
+
break;
|
1218 |
+
|
1219 |
+
// DEMO Code. Does NOT work.
|
1220 |
+
case 'vimeo':
|
1221 |
+
console.log('vimeoid');
|
1222 |
+
|
1223 |
+
pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
|
1224 |
+
|
1225 |
+
container.innerHTML =
|
1226 |
+
'<object width="' + width + '" height="' + height + '">' +
|
1227 |
+
'<param name="allowfullscreen" value="true" />' +
|
1228 |
+
'<param name="allowscriptaccess" value="always" />' +
|
1229 |
+
'<param name="flashvars" value="api=1" />' +
|
1230 |
+
'<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" />' +
|
1231 |
+
'<embed src="//vimeo.com/moogaloop.swf?api=1&clip_id=' + pluginMediaElement.vimeoid + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '"></embed>' +
|
1232 |
+
'</object>';
|
1233 |
+
|
1234 |
+
break;
|
1235 |
+
}
|
1236 |
+
// hide original element
|
1237 |
+
htmlMediaElement.style.display = 'none';
|
1238 |
+
|
1239 |
+
// FYI: options.success will be fired by the MediaPluginBridge
|
1240 |
+
|
1241 |
+
return pluginMediaElement;
|
1242 |
+
},
|
1243 |
+
|
1244 |
+
updateNative: function(playback, options, autoplay, preload) {
|
1245 |
+
|
1246 |
+
var htmlMediaElement = playback.htmlMediaElement,
|
1247 |
+
m;
|
1248 |
+
|
1249 |
+
|
1250 |
+
// add methods to video object to bring it into parity with Flash Object
|
1251 |
+
for (m in mejs.HtmlMediaElement) {
|
1252 |
+
htmlMediaElement[m] = mejs.HtmlMediaElement[m];
|
1253 |
+
}
|
1254 |
+
|
1255 |
+
/*
|
1256 |
+
Chrome now supports preload="none"
|
1257 |
+
if (mejs.MediaFeatures.isChrome) {
|
1258 |
+
|
1259 |
+
// special case to enforce preload attribute (Chrome doesn't respect this)
|
1260 |
+
if (preload === 'none' && !autoplay) {
|
1261 |
+
|
1262 |
+
// forces the browser to stop loading (note: fails in IE9)
|
1263 |
+
htmlMediaElement.src = '';
|
1264 |
+
htmlMediaElement.load();
|
1265 |
+
htmlMediaElement.canceledPreload = true;
|
1266 |
+
|
1267 |
+
htmlMediaElement.addEventListener('play',function() {
|
1268 |
+
if (htmlMediaElement.canceledPreload) {
|
1269 |
+
htmlMediaElement.src = playback.url;
|
1270 |
+
htmlMediaElement.load();
|
1271 |
+
htmlMediaElement.play();
|
1272 |
+
htmlMediaElement.canceledPreload = false;
|
1273 |
+
}
|
1274 |
+
}, false);
|
1275 |
+
// for some reason Chrome forgets how to autoplay sometimes.
|
1276 |
+
} else if (autoplay) {
|
1277 |
+
htmlMediaElement.load();
|
1278 |
+
htmlMediaElement.play();
|
1279 |
+
}
|
1280 |
+
}
|
1281 |
+
*/
|
1282 |
+
|
1283 |
+
// fire success code
|
1284 |
+
options.success(htmlMediaElement, htmlMediaElement);
|
1285 |
+
|
1286 |
+
return htmlMediaElement;
|
1287 |
+
}
|
1288 |
+
};
|
1289 |
+
|
1290 |
+
/*
|
1291 |
+
- test on IE (object vs. embed)
|
1292 |
+
- determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE)
|
1293 |
+
- fullscreen?
|
1294 |
+
*/
|
1295 |
+
|
1296 |
+
// YouTube Flash and Iframe API
|
1297 |
+
mejs.YouTubeApi = {
|
1298 |
+
isIframeStarted: false,
|
1299 |
+
isIframeLoaded: false,
|
1300 |
+
loadIframeApi: function() {
|
1301 |
+
if (!this.isIframeStarted) {
|
1302 |
+
var tag = document.createElement('script');
|
1303 |
+
tag.src = "http://www.youtube.com/player_api";
|
1304 |
+
var firstScriptTag = document.getElementsByTagName('script')[0];
|
1305 |
+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
1306 |
+
this.isIframeStarted = true;
|
1307 |
+
}
|
1308 |
+
},
|
1309 |
+
iframeQueue: [],
|
1310 |
+
enqueueIframe: function(yt) {
|
1311 |
+
|
1312 |
+
if (this.isLoaded) {
|
1313 |
+
this.createIframe(yt);
|
1314 |
+
} else {
|
1315 |
+
this.loadIframeApi();
|
1316 |
+
this.iframeQueue.push(yt);
|
1317 |
+
}
|
1318 |
+
},
|
1319 |
+
createIframe: function(settings) {
|
1320 |
+
|
1321 |
+
var
|
1322 |
+
pluginMediaElement = settings.pluginMediaElement,
|
1323 |
+
player = new YT.Player(settings.containerId, {
|
1324 |
+
height: settings.height,
|
1325 |
+
width: settings.width,
|
1326 |
+
videoId: settings.videoId,
|
1327 |
+
playerVars: {controls:0},
|
1328 |
+
events: {
|
1329 |
+
'onReady': function() {
|
1330 |
+
|
1331 |
+
// hook up iframe object to MEjs
|
1332 |
+
settings.pluginMediaElement.pluginApi = player;
|
1333 |
+
|
1334 |
+
// init mejs
|
1335 |
+
mejs.MediaPluginBridge.initPlugin(settings.pluginId);
|
1336 |
+
|
1337 |
+
// create timer
|
1338 |
+
setInterval(function() {
|
1339 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
|
1340 |
+
}, 250);
|
1341 |
+
},
|
1342 |
+
'onStateChange': function(e) {
|
1343 |
+
|
1344 |
+
mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement);
|
1345 |
+
|
1346 |
+
}
|
1347 |
+
}
|
1348 |
+
});
|
1349 |
+
},
|
1350 |
+
|
1351 |
+
createEvent: function (player, pluginMediaElement, eventName) {
|
1352 |
+
var obj = {
|
1353 |
+
type: eventName,
|
1354 |
+
target: pluginMediaElement
|
1355 |
+
};
|
1356 |
+
|
1357 |
+
if (player && player.getDuration) {
|
1358 |
+
|
1359 |
+
// time
|
1360 |
+
pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime();
|
1361 |
+
pluginMediaElement.duration = obj.duration = player.getDuration();
|
1362 |
+
|
1363 |
+
// state
|
1364 |
+
obj.paused = pluginMediaElement.paused;
|
1365 |
+
obj.ended = pluginMediaElement.ended;
|
1366 |
+
|
1367 |
+
// sound
|
1368 |
+
obj.muted = player.isMuted();
|
1369 |
+
obj.volume = player.getVolume() / 100;
|
1370 |
+
|
1371 |
+
// progress
|
1372 |
+
obj.bytesTotal = player.getVideoBytesTotal();
|
1373 |
+
obj.bufferedBytes = player.getVideoBytesLoaded();
|
1374 |
+
|
1375 |
+
// fake the W3C buffered TimeRange
|
1376 |
+
var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration;
|
1377 |
+
|
1378 |
+
obj.target.buffered = obj.buffered = {
|
1379 |
+
start: function(index) {
|
1380 |
+
return 0;
|
1381 |
+
},
|
1382 |
+
end: function (index) {
|
1383 |
+
return bufferedTime;
|
1384 |
+
},
|
1385 |
+
length: 1
|
1386 |
+
};
|
1387 |
+
|
1388 |
+
}
|
1389 |
+
|
1390 |
+
// send event up the chain
|
1391 |
+
pluginMediaElement.dispatchEvent(obj.type, obj);
|
1392 |
+
},
|
1393 |
+
|
1394 |
+
iFrameReady: function() {
|
1395 |
+
|
1396 |
+
this.isLoaded = true;
|
1397 |
+
this.isIframeLoaded = true;
|
1398 |
+
|
1399 |
+
while (this.iframeQueue.length > 0) {
|
1400 |
+
var settings = this.iframeQueue.pop();
|
1401 |
+
this.createIframe(settings);
|
1402 |
+
}
|
1403 |
+
},
|
1404 |
+
|
1405 |
+
// FLASH!
|
1406 |
+
flashPlayers: {},
|
1407 |
+
createFlash: function(settings) {
|
1408 |
+
|
1409 |
+
this.flashPlayers[settings.pluginId] = settings;
|
1410 |
+
|
1411 |
+
/*
|
1412 |
+
settings.container.innerHTML =
|
1413 |
+
'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0" ' +
|
1414 |
+
'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; ">' +
|
1415 |
+
'<param name="allowScriptAccess" value="always">' +
|
1416 |
+
'<param name="wmode" value="transparent">' +
|
1417 |
+
'</object>';
|
1418 |
+
*/
|
1419 |
+
|
1420 |
+
var specialIEContainer,
|
1421 |
+
youtubeUrl = 'http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0';
|
1422 |
+
|
1423 |
+
if (mejs.MediaFeatures.isIE) {
|
1424 |
+
|
1425 |
+
specialIEContainer = document.createElement('div');
|
1426 |
+
settings.container.appendChild(specialIEContainer);
|
1427 |
+
specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
|
1428 |
+
'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '">' +
|
1429 |
+
'<param name="movie" value="' + youtubeUrl + '" />' +
|
1430 |
+
'<param name="wmode" value="transparent" />' +
|
1431 |
+
'<param name="allowScriptAccess" value="always" />' +
|
1432 |
+
'<param name="allowFullScreen" value="true" />' +
|
1433 |
+
'</object>';
|
1434 |
+
} else {
|
1435 |
+
settings.container.innerHTML =
|
1436 |
+
'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' +
|
1437 |
+
'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; ">' +
|
1438 |
+
'<param name="allowScriptAccess" value="always">' +
|
1439 |
+
'<param name="wmode" value="transparent">' +
|
1440 |
+
'</object>';
|
1441 |
+
}
|
1442 |
+
|
1443 |
+
},
|
1444 |
+
|
1445 |
+
flashReady: function(id) {
|
1446 |
+
var
|
1447 |
+
settings = this.flashPlayers[id],
|
1448 |
+
player = document.getElementById(id),
|
1449 |
+
pluginMediaElement = settings.pluginMediaElement;
|
1450 |
+
|
1451 |
+
// hook up and return to MediaELementPlayer.success
|
1452 |
+
pluginMediaElement.pluginApi =
|
1453 |
+
pluginMediaElement.pluginElement = player;
|
1454 |
+
mejs.MediaPluginBridge.initPlugin(id);
|
1455 |
+
|
1456 |
+
// load the youtube video
|
1457 |
+
player.cueVideoById(settings.videoId);
|
1458 |
+
|
1459 |
+
var callbackName = settings.containerId + '_callback'
|
1460 |
+
|
1461 |
+
window[callbackName] = function(e) {
|
1462 |
+
mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement);
|
1463 |
+
}
|
1464 |
+
|
1465 |
+
player.addEventListener('onStateChange', callbackName);
|
1466 |
+
|
1467 |
+
setInterval(function() {
|
1468 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
|
1469 |
+
}, 250);
|
1470 |
+
},
|
1471 |
+
|
1472 |
+
handleStateChange: function(youTubeState, player, pluginMediaElement) {
|
1473 |
+
switch (youTubeState) {
|
1474 |
+
case -1: // not started
|
1475 |
+
pluginMediaElement.paused = true;
|
1476 |
+
pluginMediaElement.ended = true;
|
1477 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata');
|
1478 |
+
//createYouTubeEvent(player, pluginMediaElement, 'loadeddata');
|
1479 |
+
break;
|
1480 |
+
case 0:
|
1481 |
+
pluginMediaElement.paused = false;
|
1482 |
+
pluginMediaElement.ended = true;
|
1483 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended');
|
1484 |
+
break;
|
1485 |
+
case 1:
|
1486 |
+
pluginMediaElement.paused = false;
|
1487 |
+
pluginMediaElement.ended = false;
|
1488 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play');
|
1489 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing');
|
1490 |
+
break;
|
1491 |
+
case 2:
|
1492 |
+
pluginMediaElement.paused = true;
|
1493 |
+
pluginMediaElement.ended = false;
|
1494 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause');
|
1495 |
+
break;
|
1496 |
+
case 3: // buffering
|
1497 |
+
mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress');
|
1498 |
+
break;
|
1499 |
+
case 5:
|
1500 |
+
// cued?
|
1501 |
+
break;
|
1502 |
+
|
1503 |
+
}
|
1504 |
+
|
1505 |
+
}
|
1506 |
+
}
|
1507 |
+
// IFRAME
|
1508 |
+
function onYouTubePlayerAPIReady() {
|
1509 |
+
mejs.YouTubeApi.iFrameReady();
|
1510 |
+
}
|
1511 |
+
// FLASH
|
1512 |
+
function onYouTubePlayerReady(id) {
|
1513 |
+
mejs.YouTubeApi.flashReady(id);
|
1514 |
+
}
|
1515 |
+
|
1516 |
+
window.mejs = mejs;
|
1517 |
+
window.MediaElement = mejs.MediaElement;
|
includes/media-element/mediaelement.min.js
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* MediaElement.js
|
3 |
+
* HTML5 <video> and <audio> shim and player
|
4 |
+
* http://mediaelementjs.com/
|
5 |
+
*
|
6 |
+
* Creates a JavaScript object that mimics HTML5 MediaElement API
|
7 |
+
* for browsers that don't understand HTML5 or can't play the provided codec
|
8 |
+
* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
|
9 |
+
*
|
10 |
+
* Copyright 2010-2012, John Dyer (http://j.hn)
|
11 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
12 |
+
*
|
13 |
+
*/var mejs=mejs||{};mejs.version="2.9.1";mejs.meIndex=0;mejs.plugins={silverlight:[{version:[3,0],types:["video/mp4","video/m4v","video/mov","video/wmv","audio/wma","audio/m4a","audio/mp3","audio/wav","audio/mpeg"]}],flash:[{version:[9,0,124],types:["video/mp4","video/m4v","video/mov","video/flv","video/x-flv","audio/flv","audio/x-flv","audio/mp3","audio/m4a","audio/mpeg","video/youtube","video/x-youtube"]}],youtube:[{version:null,types:["video/youtube","video/x-youtube"]}],vimeo:[{version:null,types:["video/vimeo"]}]};
|
14 |
+
mejs.Utility={encodeUrl:function(a){return encodeURIComponent(a)},escapeHTML:function(a){return a.toString().split("&").join("&").split("<").join("<").split('"').join(""")},absolutizeUrl:function(a){var b=document.createElement("div");b.innerHTML='<a href="'+this.escapeHTML(a)+'">x</a>';return b.firstChild.href},getScriptPath:function(a){for(var b=0,c,d="",e="",g,f=document.getElementsByTagName("script"),j=f.length,h=a.length;b<j;b++){g=f[b].src;for(c=0;c<h;c++){e=a[c];if(g.indexOf(e)>
|
15 |
+
-1){d=g.substring(0,g.indexOf(e));break}}if(d!=="")break}return d},secondsToTimeCode:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;var e=Math.floor(a/3600)%24,g=Math.floor(a/60)%60,f=Math.floor(a%60);a=Math.floor((a%1*d).toFixed(3));return(b||e>0?(e<10?"0"+e:e)+":":"")+(g<10?"0"+g:g)+":"+(f<10?"0"+f:f)+(c?":"+(a<10?"0"+a:a):"")},timeCodeToSeconds:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;a=a.split(":");b=parseInt(a[0],
|
16 |
+
10);var e=parseInt(a[1],10),g=parseInt(a[2],10),f=0,j=0;if(c)f=parseInt(a[3])/d;return j=b*3600+e*60+g+f},removeSwf:function(a){var b=document.getElementById(a);if(b&&b.nodeName=="OBJECT")if(mejs.MediaFeatures.isIE){b.style.display="none";(function(){b.readyState==4?mejs.Utility.removeObjectInIE(a):setTimeout(arguments.callee,10)})()}else b.parentNode.removeChild(b)},removeObjectInIE:function(a){if(a=document.getElementById(a)){for(var b in a)if(typeof a[b]=="function")a[b]=null;a.parentNode.removeChild(a)}}};
|
17 |
+
mejs.PluginDetector={hasPluginVersion:function(a,b){var c=this.plugins[a];b[1]=b[1]||0;b[2]=b[2]||0;return c[0]>b[0]||c[0]==b[0]&&c[1]>b[1]||c[0]==b[0]&&c[1]==b[1]&&c[2]>=b[2]?true:false},nav:window.navigator,ua:window.navigator.userAgent.toLowerCase(),plugins:[],addPlugin:function(a,b,c,d,e){this.plugins[a]=this.detectPlugin(b,c,d,e)},detectPlugin:function(a,b,c,d){var e=[0,0,0],g;if(typeof this.nav.plugins!="undefined"&&typeof this.nav.plugins[a]=="object"){if((c=this.nav.plugins[a].description)&&
|
18 |
+
!(typeof this.nav.mimeTypes!="undefined"&&this.nav.mimeTypes[b]&&!this.nav.mimeTypes[b].enabledPlugin)){e=c.replace(a,"").replace(/^\s+/,"").replace(/\sr/gi,".").split(".");for(a=0;a<e.length;a++)e[a]=parseInt(e[a].match(/\d+/),10)}}else if(typeof window.ActiveXObject!="undefined")try{if(g=new ActiveXObject(c))e=d(g)}catch(f){}return e}};
|
19 |
+
mejs.PluginDetector.addPlugin("flash","Shockwave Flash","application/x-shockwave-flash","ShockwaveFlash.ShockwaveFlash",function(a){var b=[];if(a=a.GetVariable("$version")){a=a.split(" ")[1].split(",");b=[parseInt(a[0],10),parseInt(a[1],10),parseInt(a[2],10)]}return b});
|
20 |
+
mejs.PluginDetector.addPlugin("silverlight","Silverlight Plug-In","application/x-silverlight-2","AgControl.AgControl",function(a){var b=[0,0,0,0],c=function(d,e,g,f){for(;d.isVersionSupported(e[0]+"."+e[1]+"."+e[2]+"."+e[3]);)e[g]+=f;e[g]-=f};c(a,b,0,1);c(a,b,1,1);c(a,b,2,1E4);c(a,b,2,1E3);c(a,b,2,100);c(a,b,2,10);c(a,b,2,1);c(a,b,3,1);return b});
|
21 |
+
mejs.MediaFeatures={init:function(){var a=this,b=document,c=mejs.PluginDetector.nav,d=mejs.PluginDetector.ua.toLowerCase(),e,g=["source","track","audio","video"];a.isiPad=d.match(/ipad/i)!==null;a.isiPhone=d.match(/iphone/i)!==null;a.isiOS=a.isiPhone||a.isiPad;a.isAndroid=d.match(/android/i)!==null;a.isBustedAndroid=d.match(/android 2\.[12]/)!==null;a.isIE=c.appName.toLowerCase().indexOf("microsoft")!=-1;a.isChrome=d.match(/chrome/gi)!==null;a.isFirefox=d.match(/firefox/gi)!==null;a.isWebkit=d.match(/webkit/gi)!==
|
22 |
+
null;a.isGecko=d.match(/gecko/gi)!==null&&!a.isWebkit;a.isOpera=d.match(/opera/gi)!==null;a.hasTouch="ontouchstart"in window;for(c=0;c<g.length;c++)e=document.createElement(g[c]);a.supportsMediaTag=typeof e.canPlayType!=="undefined"||a.isBustedAndroid;a.hasSemiNativeFullScreen=typeof e.webkitEnterFullscreen!=="undefined";a.hasWebkitNativeFullScreen=typeof e.webkitRequestFullScreen!=="undefined";a.hasMozNativeFullScreen=typeof e.mozRequestFullScreen!=="undefined";a.hasTrueNativeFullScreen=a.hasWebkitNativeFullScreen||
|
23 |
+
a.hasMozNativeFullScreen;a.nativeFullScreenEnabled=a.hasTrueNativeFullScreen;if(a.hasMozNativeFullScreen)a.nativeFullScreenEnabled=e.mozFullScreenEnabled;if(this.isChrome)a.hasSemiNativeFullScreen=false;if(a.hasTrueNativeFullScreen){a.fullScreenEventName=a.hasWebkitNativeFullScreen?"webkitfullscreenchange":"mozfullscreenchange";a.isFullScreen=function(){if(e.mozRequestFullScreen)return b.mozFullScreen;else if(e.webkitRequestFullScreen)return b.webkitIsFullScreen};a.requestFullScreen=function(f){if(a.hasWebkitNativeFullScreen)f.webkitRequestFullScreen();
|
24 |
+
else a.hasMozNativeFullScreen&&f.mozRequestFullScreen()};a.cancelFullScreen=function(){if(a.hasWebkitNativeFullScreen)document.webkitCancelFullScreen();else a.hasMozNativeFullScreen&&document.mozCancelFullScreen()}}if(a.hasSemiNativeFullScreen&&d.match(/mac os x 10_5/i)){a.hasNativeFullScreen=false;a.hasSemiNativeFullScreen=false}}};mejs.MediaFeatures.init();
|
25 |
+
mejs.HtmlMediaElement={pluginType:"native",isFullScreen:false,setCurrentTime:function(a){this.currentTime=a},setMuted:function(a){this.muted=a},setVolume:function(a){this.volume=a},stop:function(){this.pause()},setSrc:function(a){for(var b=this.getElementsByTagName("source");b.length>0;)this.removeChild(b[0]);if(typeof a=="string")this.src=a;else{var c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type))this.src=c.src}}},setVideoSize:function(a,b){this.width=a;this.height=b}};
|
26 |
+
mejs.PluginMediaElement=function(a,b,c){this.id=a;this.pluginType=b;this.src=c;this.events={}};
|
27 |
+
mejs.PluginMediaElement.prototype={pluginElement:null,pluginType:"",isFullScreen:false,playbackRate:-1,defaultPlaybackRate:-1,seekable:[],played:[],paused:true,ended:false,seeking:false,duration:0,error:null,tagName:"",muted:false,volume:1,currentTime:0,play:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.playVideo():this.pluginApi.playMedia();this.paused=false}},load:function(){if(this.pluginApi!=null){this.pluginType!="youtube"&&this.pluginApi.loadMedia();this.paused=
|
28 |
+
false}},pause:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.pauseVideo():this.pluginApi.pauseMedia();this.paused=true}},stop:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.stopVideo():this.pluginApi.stopMedia();this.paused=true}},canPlayType:function(a){var b,c,d,e=mejs.plugins[this.pluginType];for(b=0;b<e.length;b++){d=e[b];if(mejs.PluginDetector.hasPluginVersion(this.pluginType,d.version))for(c=0;c<d.types.length;c++)if(a==d.types[c])return true}return false},
|
29 |
+
positionFullscreenButton:function(a,b,c){this.pluginApi!=null&&this.pluginApi.positionFullscreenButton&&this.pluginApi.positionFullscreenButton(a,b,c)},hideFullscreenButton:function(){this.pluginApi!=null&&this.pluginApi.hideFullscreenButton&&this.pluginApi.hideFullscreenButton()},setSrc:function(a){if(typeof a=="string"){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(a));this.src=mejs.Utility.absolutizeUrl(a)}else{var b,c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(c.src));
|
30 |
+
this.src=mejs.Utility.absolutizeUrl(a)}}}},setCurrentTime:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.seekTo(a):this.pluginApi.setCurrentTime(a);this.currentTime=a}},setVolume:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.setVolume(a*100):this.pluginApi.setVolume(a);this.volume=a}},setMuted:function(a){if(this.pluginApi!=null){if(this.pluginType=="youtube"){a?this.pluginApi.mute():this.pluginApi.unMute();this.muted=a;this.dispatchEvent("volumechange")}else this.pluginApi.setMuted(a);
|
31 |
+
this.muted=a}},setVideoSize:function(a,b){if(this.pluginElement.style){this.pluginElement.style.width=a+"px";this.pluginElement.style.height=b+"px"}this.pluginApi!=null&&this.pluginApi.setVideoSize&&this.pluginApi.setVideoSize(a,b)},setFullscreen:function(a){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.pluginApi.setFullscreen(a)},enterFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.setFullscreen(true)},exitFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&
|
32 |
+
this.setFullscreen(false)},addEventListener:function(a,b){this.events[a]=this.events[a]||[];this.events[a].push(b)},removeEventListener:function(a,b){if(!a){this.events={};return true}var c=this.events[a];if(!c)return true;if(!b){this.events[a]=[];return true}for(i=0;i<c.length;i++)if(c[i]===b){this.events[a].splice(i,1);return true}return false},dispatchEvent:function(a){var b,c,d=this.events[a];if(d){c=Array.prototype.slice.call(arguments,1);for(b=0;b<d.length;b++)d[b].apply(null,c)}},attributes:{},
|
33 |
+
hasAttribute:function(a){return a in this.attributes},removeAttribute:function(a){delete this.attributes[a]},getAttribute:function(a){if(this.hasAttribute(a))return this.attributes[a];return""},setAttribute:function(a,b){this.attributes[a]=b},remove:function(){mejs.Utility.removeSwf(this.pluginElement.id)}};
|
34 |
+
mejs.MediaPluginBridge={pluginMediaElements:{},htmlMediaElements:{},registerPluginElement:function(a,b,c){this.pluginMediaElements[a]=b;this.htmlMediaElements[a]=c},initPlugin:function(a){var b=this.pluginMediaElements[a],c=this.htmlMediaElements[a];if(b){switch(b.pluginType){case "flash":b.pluginElement=b.pluginApi=document.getElementById(a);break;case "silverlight":b.pluginElement=document.getElementById(b.id);b.pluginApi=b.pluginElement.Content.MediaElementJS}b.pluginApi!=null&&b.success&&b.success(b,
|
35 |
+
c)}},fireEvent:function(a,b,c){var d,e;a=this.pluginMediaElements[a];a.ended=false;a.paused=true;b={type:b,target:a};for(d in c){a[d]=c[d];b[d]=c[d]}e=c.bufferedTime||0;b.target.buffered=b.buffered={start:function(){return 0},end:function(){return e},length:1};a.dispatchEvent(b.type,b)}};
|
36 |
+
mejs.MediaElementDefaults={mode:"auto",plugins:["flash","silverlight","youtube","vimeo"],enablePluginDebug:false,type:"",pluginPath:mejs.Utility.getScriptPath(["mediaelement.js","mediaelement.min.js","mediaelement-and-player.js","mediaelement-and-player.min.js"]),flashName:"flashmediaelement.swf",enablePluginSmoothing:false,silverlightName:"silverlightmediaelement.xap",defaultVideoWidth:480,defaultVideoHeight:270,pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:0.8,success:function(){},
|
37 |
+
error:function(){}};mejs.MediaElement=function(a,b){return mejs.HtmlMediaElementShim.create(a,b)};
|
38 |
+
mejs.HtmlMediaElementShim={create:function(a,b){var c=mejs.MediaElementDefaults,d=typeof a=="string"?document.getElementById(a):a,e=d.tagName.toLowerCase(),g=e==="audio"||e==="video",f=g?d.getAttribute("src"):d.getAttribute("href");e=d.getAttribute("poster");var j=d.getAttribute("autoplay"),h=d.getAttribute("preload"),l=d.getAttribute("controls"),k;for(k in b)c[k]=b[k];f=typeof f=="undefined"||f===null||f==""?null:f;e=typeof e=="undefined"||e===null?"":e;h=typeof h=="undefined"||h===null||h==="false"?
|
39 |
+
"none":h;j=!(typeof j=="undefined"||j===null||j==="false");l=!(typeof l=="undefined"||l===null||l==="false");k=this.determinePlayback(d,c,mejs.MediaFeatures.supportsMediaTag,g,f);k.url=k.url!==null?mejs.Utility.absolutizeUrl(k.url):"";if(k.method=="native"){if(mejs.MediaFeatures.isBustedAndroid){d.src=k.url;d.addEventListener("click",function(){d.play()},false)}return this.updateNative(k,c,j,h)}else if(k.method!=="")return this.createPlugin(k,c,e,j,h,l);else{this.createErrorMessage(k,c,e);return this}},
|
40 |
+
determinePlayback:function(a,b,c,d,e){var g=[],f,j,h={method:"",url:"",htmlMediaElement:a,isVideo:a.tagName.toLowerCase()!="audio"},l,k;if(typeof b.type!="undefined"&&b.type!=="")if(typeof b.type=="string")g.push({type:b.type,url:e});else for(f=0;f<b.type.length;f++)g.push({type:b.type[f],url:e});else if(e!==null){j=this.formatType(e,a.getAttribute("type"));g.push({type:j,url:e})}else for(f=0;f<a.childNodes.length;f++){j=a.childNodes[f];if(j.nodeType==1&&j.tagName.toLowerCase()=="source"){e=j.getAttribute("src");
|
41 |
+
j=this.formatType(e,j.getAttribute("type"));g.push({type:j,url:e})}}if(!d&&g.length>0&&g[0].url!==null&&this.getTypeFromFile(g[0].url).indexOf("audio")>-1)h.isVideo=false;if(mejs.MediaFeatures.isBustedAndroid)a.canPlayType=function(m){return m.match(/video\/(mp4|m4v)/gi)!==null?"maybe":""};if(c&&(b.mode==="auto"||b.mode==="native")){if(!d){f=document.createElement(h.isVideo?"video":"audio");a.parentNode.insertBefore(f,a);a.style.display="none";h.htmlMediaElement=a=f}for(f=0;f<g.length;f++)if(a.canPlayType(g[f].type).replace(/no/,
|
42 |
+
"")!==""||a.canPlayType(g[f].type.replace(/mp3/,"mpeg")).replace(/no/,"")!==""){h.method="native";h.url=g[f].url;break}if(h.method==="native"){if(h.url!==null)a.src=h.url;return h}}if(b.mode==="auto"||b.mode==="shim")for(f=0;f<g.length;f++){j=g[f].type;for(a=0;a<b.plugins.length;a++){e=b.plugins[a];l=mejs.plugins[e];for(c=0;c<l.length;c++){k=l[c];if(k.version==null||mejs.PluginDetector.hasPluginVersion(e,k.version))for(d=0;d<k.types.length;d++)if(j==k.types[d]){h.method=e;h.url=g[f].url;return h}}}}if(h.method===
|
43 |
+
""&&g.length>0)h.url=g[0].url;return h},formatType:function(a,b){return a&&!b?this.getTypeFromFile(a):b&&~b.indexOf(";")?b.substr(0,b.indexOf(";")):b},getTypeFromFile:function(a){a=a.substring(a.lastIndexOf(".")+1);return(/(mp4|m4v|ogg|ogv|webm|flv|wmv|mpeg|mov)/gi.test(a)?"video":"audio")+"/"+a},createErrorMessage:function(a,b,c){var d=a.htmlMediaElement,e=document.createElement("div");e.className="me-cannotplay";try{e.style.width=d.width+"px";e.style.height=d.height+"px"}catch(g){}e.innerHTML=c!==
|
44 |
+
""?'<a href="'+a.url+'"><img src="'+c+'" width="100%" height="100%" /></a>':'<a href="'+a.url+'"><span>Download File</span></a>';d.parentNode.insertBefore(e,d);d.style.display="none";b.error(d)},createPlugin:function(a,b,c,d,e,g){c=a.htmlMediaElement;var f=1,j=1,h="me_"+a.method+"_"+mejs.meIndex++,l=new mejs.PluginMediaElement(h,a.method,a.url),k=document.createElement("div"),m;l.tagName=c.tagName;for(m=0;m<c.attributes.length;m++){var n=c.attributes[m];n.specified==true&&l.setAttribute(n.name,n.value)}for(m=
|
45 |
+
c.parentNode;m!==null&&m.tagName.toLowerCase()!="body";){if(m.parentNode.tagName.toLowerCase()=="p"){m.parentNode.parentNode.insertBefore(m,m.parentNode);break}m=m.parentNode}if(a.isVideo){f=b.videoWidth>0?b.videoWidth:c.getAttribute("width")!==null?c.getAttribute("width"):b.defaultVideoWidth;j=b.videoHeight>0?b.videoHeight:c.getAttribute("height")!==null?c.getAttribute("height"):b.defaultVideoHeight;f=mejs.Utility.encodeUrl(f);j=mejs.Utility.encodeUrl(j)}else if(b.enablePluginDebug){f=320;j=240}l.success=
|
46 |
+
b.success;mejs.MediaPluginBridge.registerPluginElement(h,l,c);k.className="me-plugin";k.id=h+"_container";a.isVideo?c.parentNode.insertBefore(k,c):document.body.insertBefore(k,document.body.childNodes[0]);d=["id="+h,"isvideo="+(a.isVideo?"true":"false"),"autoplay="+(d?"true":"false"),"preload="+e,"width="+f,"startvolume="+b.startVolume,"timerrate="+b.timerRate,"height="+j];if(a.url!==null)a.method=="flash"?d.push("file="+mejs.Utility.encodeUrl(a.url)):d.push("file="+a.url);b.enablePluginDebug&&d.push("debug=true");
|
47 |
+
b.enablePluginSmoothing&&d.push("smoothing=true");g&&d.push("controls=true");if(b.pluginVars)d=d.concat(b.pluginVars);switch(a.method){case "silverlight":k.innerHTML='<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="'+h+'" name="'+h+'" width="'+f+'" height="'+j+'"><param name="initParams" value="'+d.join(",")+'" /><param name="windowless" value="true" /><param name="background" value="black" /><param name="minRuntimeVersion" value="3.0.0.0" /><param name="autoUpgrade" value="true" /><param name="source" value="'+
|
48 |
+
b.pluginPath+b.silverlightName+'" /></object>';break;case "flash":if(mejs.MediaFeatures.isIE){a=document.createElement("div");k.appendChild(a);a.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+h+'" width="'+f+'" height="'+j+'"><param name="movie" value="'+b.pluginPath+b.flashName+"?x="+new Date+'" /><param name="flashvars" value="'+d.join("&")+'" /><param name="quality" value="high" /><param name="bgcolor" value="#000000" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else k.innerHTML=
|
49 |
+
'<embed id="'+h+'" name="'+h+'" play="true" loop="false" quality="high" bgcolor="#000000" wmode="transparent" allowScriptAccess="always" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" src="'+b.pluginPath+b.flashName+'" flashvars="'+d.join("&")+'" width="'+f+'" height="'+j+'"></embed>';break;case "youtube":b=a.url.substr(a.url.lastIndexOf("=")+1);youtubeSettings={container:k,containerId:k.id,pluginMediaElement:l,pluginId:h,videoId:b,
|
50 |
+
height:j,width:f};mejs.PluginDetector.hasPluginVersion("flash",[10,0,0])?mejs.YouTubeApi.createFlash(youtubeSettings):mejs.YouTubeApi.enqueueIframe(youtubeSettings);break;case "vimeo":console.log("vimeoid");l.vimeoid=a.url.substr(a.url.lastIndexOf("/")+1);k.innerHTML='<object width="'+f+'" height="'+j+'"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="flashvars" value="api=1" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id='+
|
51 |
+
l.vimeoid+'&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" /><embed src="//vimeo.com/moogaloop.swf?api=1&clip_id='+l.vimeoid+'&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="'+f+'" height="'+j+'"></embed></object>'}c.style.display=
|
52 |
+
"none";return l},updateNative:function(a,b){var c=a.htmlMediaElement,d;for(d in mejs.HtmlMediaElement)c[d]=mejs.HtmlMediaElement[d];b.success(c,c);return c}};
|
53 |
+
mejs.YouTubeApi={isIframeStarted:false,isIframeLoaded:false,loadIframeApi:function(){if(!this.isIframeStarted){var a=document.createElement("script");a.src="http://www.youtube.com/player_api";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b);this.isIframeStarted=true}},iframeQueue:[],enqueueIframe:function(a){if(this.isLoaded)this.createIframe(a);else{this.loadIframeApi();this.iframeQueue.push(a)}},createIframe:function(a){var b=a.pluginMediaElement,c=new YT.Player(a.containerId,
|
54 |
+
{height:a.height,width:a.width,videoId:a.videoId,playerVars:{controls:0},events:{onReady:function(){a.pluginMediaElement.pluginApi=c;mejs.MediaPluginBridge.initPlugin(a.pluginId);setInterval(function(){mejs.YouTubeApi.createEvent(c,b,"timeupdate")},250)},onStateChange:function(d){mejs.YouTubeApi.handleStateChange(d.data,c,b)}}})},createEvent:function(a,b,c){c={type:c,target:b};if(a&&a.getDuration){b.currentTime=c.currentTime=a.getCurrentTime();b.duration=c.duration=a.getDuration();c.paused=b.paused;
|
55 |
+
c.ended=b.ended;c.muted=a.isMuted();c.volume=a.getVolume()/100;c.bytesTotal=a.getVideoBytesTotal();c.bufferedBytes=a.getVideoBytesLoaded();var d=c.bufferedBytes/c.bytesTotal*c.duration;c.target.buffered=c.buffered={start:function(){return 0},end:function(){return d},length:1}}b.dispatchEvent(c.type,c)},iFrameReady:function(){for(this.isIframeLoaded=this.isLoaded=true;this.iframeQueue.length>0;)this.createIframe(this.iframeQueue.pop())},flashPlayers:{},createFlash:function(a){this.flashPlayers[a.pluginId]=
|
56 |
+
a;var b,c="http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid="+a.pluginId+"&version=3&autoplay=0&controls=0&modestbranding=1&loop=0";if(mejs.MediaFeatures.isIE){b=document.createElement("div");a.container.appendChild(b);b.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+a.pluginId+'" width="'+a.width+'" height="'+a.height+'"><param name="movie" value="'+c+'" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else a.container.innerHTML=
|
57 |
+
'<object type="application/x-shockwave-flash" id="'+a.pluginId+'" data="'+c+'" width="'+a.width+'" height="'+a.height+'" style="visibility: visible; "><param name="allowScriptAccess" value="always"><param name="wmode" value="transparent"></object>'},flashReady:function(a){var b=this.flashPlayers[a],c=document.getElementById(a),d=b.pluginMediaElement;d.pluginApi=d.pluginElement=c;mejs.MediaPluginBridge.initPlugin(a);c.cueVideoById(b.videoId);a=b.containerId+"_callback";window[a]=function(e){mejs.YouTubeApi.handleStateChange(e,
|
58 |
+
c,d)};c.addEventListener("onStateChange",a);setInterval(function(){mejs.YouTubeApi.createEvent(c,d,"timeupdate")},250)},handleStateChange:function(a,b,c){switch(a){case -1:c.paused=true;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"loadedmetadata");break;case 0:c.paused=false;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"ended");break;case 1:c.paused=false;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"play");mejs.YouTubeApi.createEvent(b,c,"playing");break;case 2:c.paused=true;c.ended=false;mejs.YouTubeApi.createEvent(b,
|
59 |
+
c,"pause");break;case 3:mejs.YouTubeApi.createEvent(b,c,"progress")}}};function onYouTubePlayerAPIReady(){mejs.YouTubeApi.iFrameReady()}function onYouTubePlayerReady(a){mejs.YouTubeApi.flashReady(a)}window.mejs=mejs;window.MediaElement=mejs.MediaElement;
|
includes/media-element/mediaelementplayer.css
ADDED
@@ -0,0 +1,801 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.mejs-container {
|
2 |
+
position: relative;
|
3 |
+
background: #000;
|
4 |
+
font-family: Helvetica, Arial;
|
5 |
+
text-align: left;
|
6 |
+
vertical-align: top;
|
7 |
+
}
|
8 |
+
|
9 |
+
.me-plugin {
|
10 |
+
position: absolute;
|
11 |
+
}
|
12 |
+
|
13 |
+
.mejs-embed, .mejs-embed body {
|
14 |
+
width: 100%;
|
15 |
+
height: 100%;
|
16 |
+
margin: 0;
|
17 |
+
padding: 0;
|
18 |
+
background: #000;
|
19 |
+
overflow: hidden;
|
20 |
+
}
|
21 |
+
|
22 |
+
.mejs-container-fullscreen {
|
23 |
+
position: fixed;
|
24 |
+
left: 0;
|
25 |
+
top: 0;
|
26 |
+
right: 0;
|
27 |
+
bottom: 0;
|
28 |
+
overflow: hidden;
|
29 |
+
z-index: 1000;
|
30 |
+
}
|
31 |
+
.mejs-container-fullscreen .mejs-mediaelement,
|
32 |
+
.mejs-container-fullscreen video {
|
33 |
+
width: 100%;
|
34 |
+
height: 100%;
|
35 |
+
}
|
36 |
+
|
37 |
+
/* Start: LAYERS */
|
38 |
+
.mejs-background {
|
39 |
+
position: absolute;
|
40 |
+
top: 0;
|
41 |
+
left: 0;
|
42 |
+
}
|
43 |
+
.mejs-mediaelement {
|
44 |
+
position: absolute;
|
45 |
+
top: 0;
|
46 |
+
left: 0;
|
47 |
+
width: 100%;
|
48 |
+
height: 100%;
|
49 |
+
}
|
50 |
+
.mejs-poster {
|
51 |
+
position: absolute;
|
52 |
+
top: 0;
|
53 |
+
left: 0;
|
54 |
+
}
|
55 |
+
.mejs-poster img {
|
56 |
+
border: 0;
|
57 |
+
padding: 0;
|
58 |
+
border: 0;
|
59 |
+
display: block;
|
60 |
+
}
|
61 |
+
.mejs-overlay {
|
62 |
+
position: absolute;
|
63 |
+
top: 0;
|
64 |
+
left: 0;
|
65 |
+
}
|
66 |
+
.mejs-overlay-play {
|
67 |
+
cursor: pointer;
|
68 |
+
}
|
69 |
+
.mejs-overlay-button {
|
70 |
+
position: absolute;
|
71 |
+
top: 50%;
|
72 |
+
left: 50%;
|
73 |
+
width: 100px;
|
74 |
+
height: 100px;
|
75 |
+
margin: -50px 0 0 -50px;
|
76 |
+
background: url(bigplay.png) no-repeat;
|
77 |
+
}
|
78 |
+
.mejs-overlay:hover .mejs-overlay-button{
|
79 |
+
background-position: 0 -100px ;
|
80 |
+
}
|
81 |
+
.mejs-overlay-loading {
|
82 |
+
position: absolute;
|
83 |
+
top: 50%;
|
84 |
+
left: 50%;
|
85 |
+
width: 80px;
|
86 |
+
height: 80px;
|
87 |
+
margin: -40px 0 0 -40px;
|
88 |
+
background: #333;
|
89 |
+
background: url(background.png);
|
90 |
+
background: rgba(0, 0, 0, 0.9);
|
91 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.9)), to(rgba(0,0,0,0.9)));
|
92 |
+
background: -webkit-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
93 |
+
background: -moz-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
94 |
+
background: -o-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
95 |
+
background: -ms-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
96 |
+
background: linear-gradient(rgba(50,50,50,0.9), rgba(0,0,0,0.9));
|
97 |
+
}
|
98 |
+
.mejs-overlay-loading span {
|
99 |
+
display:block;
|
100 |
+
width: 80px;
|
101 |
+
height: 80px;
|
102 |
+
background: transparent url(loading.gif) 50% 50% no-repeat;
|
103 |
+
}
|
104 |
+
|
105 |
+
/* End: LAYERS */
|
106 |
+
|
107 |
+
/* Start: CONTROL BAR */
|
108 |
+
.mejs-container .mejs-controls {
|
109 |
+
position: absolute;
|
110 |
+
background: none;
|
111 |
+
list-style-type: none;
|
112 |
+
margin: 0;
|
113 |
+
padding: 0;
|
114 |
+
bottom: 0;
|
115 |
+
left: 0;
|
116 |
+
background: url(background.png);
|
117 |
+
background: rgba(0, 0, 0, 0.7);
|
118 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7)));
|
119 |
+
background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
120 |
+
background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
121 |
+
background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
122 |
+
background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
123 |
+
background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
124 |
+
height: 30px;
|
125 |
+
width: 100%;
|
126 |
+
}
|
127 |
+
.mejs-container .mejs-controls div {
|
128 |
+
list-style-type: none;
|
129 |
+
background-image: none;
|
130 |
+
display: block;
|
131 |
+
float: left;
|
132 |
+
margin: 0;
|
133 |
+
padding: 0;
|
134 |
+
width: 26px;
|
135 |
+
height: 26px;
|
136 |
+
font-size: 11px;
|
137 |
+
line-height: 11px;
|
138 |
+
background: 0;
|
139 |
+
font-family: Helvetica, Arial;
|
140 |
+
border: 0;
|
141 |
+
}
|
142 |
+
|
143 |
+
.mejs-controls .mejs-button button {
|
144 |
+
cursor: pointer;
|
145 |
+
display: block;
|
146 |
+
font-size: 0;
|
147 |
+
line-height: 0;
|
148 |
+
text-decoration: none;
|
149 |
+
margin: 7px 5px;
|
150 |
+
padding: 0;
|
151 |
+
position: absolute;
|
152 |
+
height: 16px;
|
153 |
+
width: 16px;
|
154 |
+
border: 0;
|
155 |
+
background: transparent url(controls.png) no-repeat;
|
156 |
+
}
|
157 |
+
|
158 |
+
/* :focus for accessibility */
|
159 |
+
.mejs-controls .mejs-button button:focus {
|
160 |
+
outline: solid 1px yellow;
|
161 |
+
}
|
162 |
+
|
163 |
+
/* End: CONTROL BAR */
|
164 |
+
|
165 |
+
/* Start: Time (current / duration) */
|
166 |
+
.mejs-container .mejs-controls .mejs-time {
|
167 |
+
color: #fff;
|
168 |
+
display: block;
|
169 |
+
height: 17px;
|
170 |
+
width: auto;
|
171 |
+
padding: 8px 3px 0 3px ;
|
172 |
+
overflow: hidden;
|
173 |
+
text-align: center;
|
174 |
+
padding: auto 4px;
|
175 |
+
box-sizing: content-box;
|
176 |
+
-moz-box-sizing: content-box;
|
177 |
+
-webkit-box-sizing: content-box;
|
178 |
+
}
|
179 |
+
.mejs-container .mejs-controls .mejs-time span {
|
180 |
+
font-size: 11px;
|
181 |
+
color: #fff;
|
182 |
+
line-height: 12px;
|
183 |
+
display: block;
|
184 |
+
float: left;
|
185 |
+
margin: 1px 2px 0 0;
|
186 |
+
width: auto;
|
187 |
+
}
|
188 |
+
/* End: Time (current / duration) */
|
189 |
+
|
190 |
+
|
191 |
+
/* Start: Play/pause */
|
192 |
+
.mejs-controls .mejs-play button {
|
193 |
+
background-position:0 0;
|
194 |
+
}
|
195 |
+
.mejs-controls .mejs-pause button {
|
196 |
+
background-position:0 -16px;
|
197 |
+
}
|
198 |
+
/* End: Play/pause */
|
199 |
+
|
200 |
+
|
201 |
+
/* Stop */
|
202 |
+
.mejs-controls .mejs-stop button {
|
203 |
+
background-position: -112px 0;
|
204 |
+
}
|
205 |
+
/* End: Play/pause */
|
206 |
+
|
207 |
+
/* Start: Progress bar */
|
208 |
+
.mejs-controls div.mejs-time-rail {
|
209 |
+
width: 200px;
|
210 |
+
padding-top: 5px;
|
211 |
+
}
|
212 |
+
.mejs-controls .mejs-time-rail span {
|
213 |
+
display: block;
|
214 |
+
position: absolute;
|
215 |
+
width: 180px;
|
216 |
+
height: 10px;
|
217 |
+
-webkit-border-radius: 2px;
|
218 |
+
-moz-border-radius: 2px;
|
219 |
+
border-radius: 2px;
|
220 |
+
cursor: pointer;
|
221 |
+
}
|
222 |
+
.mejs-controls .mejs-time-rail .mejs-time-total {
|
223 |
+
margin: 5px;
|
224 |
+
background: #333;
|
225 |
+
background: rgba(50,50,50,0.8);
|
226 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8)));
|
227 |
+
background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
228 |
+
background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
229 |
+
background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
230 |
+
background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
231 |
+
background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
232 |
+
}
|
233 |
+
.mejs-controls .mejs-time-rail .mejs-time-buffering {
|
234 |
+
width:100%;
|
235 |
+
background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
236 |
+
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
|
237 |
+
background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
238 |
+
background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
239 |
+
background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
240 |
+
background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
241 |
+
-webkit-background-size: 15px 15px;
|
242 |
+
-moz-background-size: 15px 15px;
|
243 |
+
-o-background-size: 15px 15px;
|
244 |
+
background-size: 15px 15px;
|
245 |
+
-webkit-animation: buffering-stripes 2s linear infinite;
|
246 |
+
-moz-animation: buffering-stripes 2s linear infinite;
|
247 |
+
-ms-animation: buffering-stripes 2s linear infinite;
|
248 |
+
-o-animation: buffering-stripes 2s linear infinite;
|
249 |
+
animation: buffering-stripes 2s linear infinite;
|
250 |
+
}
|
251 |
+
|
252 |
+
@-webkit-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
253 |
+
@-moz-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
254 |
+
@-ms-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
255 |
+
@-o-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
256 |
+
@keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} }
|
257 |
+
|
258 |
+
.mejs-controls .mejs-time-rail .mejs-time-loaded {
|
259 |
+
background: #3caac8;
|
260 |
+
background: rgba(60,170,200,0.8);
|
261 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(44,124,145,0.8)), to(rgba(78,183,212,0.8)));
|
262 |
+
background: -webkit-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
263 |
+
background: -moz-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
264 |
+
background: -o-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
265 |
+
background: -ms-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
266 |
+
background: linear-gradient(rgba(44,124,145,0.8), rgba(78,183,212,0.8));
|
267 |
+
width: 0;
|
268 |
+
}
|
269 |
+
.mejs-controls .mejs-time-rail .mejs-time-current {
|
270 |
+
width: 0;
|
271 |
+
background: #fff;
|
272 |
+
background: rgba(255,255,255,0.8);
|
273 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8)));
|
274 |
+
background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
275 |
+
background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
276 |
+
background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
277 |
+
background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
278 |
+
background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
279 |
+
}
|
280 |
+
|
281 |
+
.mejs-controls .mejs-time-rail .mejs-time-handle {
|
282 |
+
display: none;
|
283 |
+
position: absolute;
|
284 |
+
margin: 0;
|
285 |
+
width: 10px;
|
286 |
+
background: #fff;
|
287 |
+
-webkit-border-radius: 5px;
|
288 |
+
-moz-border-radius: 5px;
|
289 |
+
border-radius: 5px;
|
290 |
+
cursor: pointer;
|
291 |
+
border: solid 2px #333;
|
292 |
+
top: -2px;
|
293 |
+
text-align: center;
|
294 |
+
}
|
295 |
+
|
296 |
+
.mejs-controls .mejs-time-rail .mejs-time-float {
|
297 |
+
position: absolute;
|
298 |
+
display: none;
|
299 |
+
background: #eee;
|
300 |
+
width: 36px;
|
301 |
+
height: 17px;
|
302 |
+
border: solid 1px #333;
|
303 |
+
top: -26px;
|
304 |
+
margin-left: -18px;
|
305 |
+
text-align: center;
|
306 |
+
color: #111;
|
307 |
+
}
|
308 |
+
|
309 |
+
.mejs-controls .mejs-time-rail .mejs-time-float-current {
|
310 |
+
margin: 2px;
|
311 |
+
width: 30px;
|
312 |
+
display: block;
|
313 |
+
text-align: center;
|
314 |
+
left: 0;
|
315 |
+
}
|
316 |
+
.mejs-controls .mejs-time-rail .mejs-time-float-corner {
|
317 |
+
position: absolute;
|
318 |
+
display: block;
|
319 |
+
width: 0;
|
320 |
+
height: 0;
|
321 |
+
line-height: 0;
|
322 |
+
border: solid 5px #eee;
|
323 |
+
border-color: #eee transparent transparent transparent;
|
324 |
+
-webkit-border-radius: 0;
|
325 |
+
-moz-border-radius: 0;
|
326 |
+
border-radius: 0;
|
327 |
+
top: 15px;
|
328 |
+
left: 13px;
|
329 |
+
|
330 |
+
}
|
331 |
+
|
332 |
+
|
333 |
+
|
334 |
+
|
335 |
+
/*
|
336 |
+
.mejs-controls .mejs-time-rail:hover .mejs-time-handle {
|
337 |
+
visibility:visible;
|
338 |
+
}
|
339 |
+
*/
|
340 |
+
/* End: Progress bar */
|
341 |
+
|
342 |
+
/* Start: Fullscreen */
|
343 |
+
.mejs-controls .mejs-fullscreen-button button {
|
344 |
+
background-position:-32px 0;
|
345 |
+
}
|
346 |
+
.mejs-controls .mejs-unfullscreen button {
|
347 |
+
background-position:-32px -16px;
|
348 |
+
}
|
349 |
+
/* End: Fullscreen */
|
350 |
+
|
351 |
+
|
352 |
+
/* Start: Mute/Volume */
|
353 |
+
.mejs-controls .mejs-volume-button {
|
354 |
+
}
|
355 |
+
|
356 |
+
.mejs-controls .mejs-mute button {
|
357 |
+
background-position:-16px -16px;
|
358 |
+
}
|
359 |
+
|
360 |
+
.mejs-controls .mejs-unmute button {
|
361 |
+
background-position:-16px 0;
|
362 |
+
}
|
363 |
+
|
364 |
+
.mejs-controls .mejs-volume-button {
|
365 |
+
position: relative;
|
366 |
+
}
|
367 |
+
|
368 |
+
.mejs-controls .mejs-volume-button .mejs-volume-slider {
|
369 |
+
display: none;
|
370 |
+
height: 115px;
|
371 |
+
width: 25px;
|
372 |
+
background: url(background.png);
|
373 |
+
background: rgba(50, 50, 50, 0.7);
|
374 |
+
-webkit-border-radius: 0;
|
375 |
+
-moz-border-radius: 0;
|
376 |
+
border-radius: 0;
|
377 |
+
top: -115px;
|
378 |
+
left: 0;
|
379 |
+
z-index: 1;
|
380 |
+
position: absolute;
|
381 |
+
margin: 0;
|
382 |
+
}
|
383 |
+
.mejs-controls .mejs-volume-button:hover {
|
384 |
+
-webkit-border-radius: 0 0 4px 4px;
|
385 |
+
-moz-border-radius: 0 0 4px 4px;
|
386 |
+
border-radius: 0 0 4px 4px;
|
387 |
+
}
|
388 |
+
/*
|
389 |
+
.mejs-controls .mejs-volume-button:hover .mejs-volume-slider {
|
390 |
+
display: block;
|
391 |
+
}
|
392 |
+
*/
|
393 |
+
|
394 |
+
.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total {
|
395 |
+
position: absolute;
|
396 |
+
left: 11px;
|
397 |
+
top: 8px;
|
398 |
+
width: 2px;
|
399 |
+
height: 100px;
|
400 |
+
background: #ddd;
|
401 |
+
background: rgba(255, 255, 255, 0.5);
|
402 |
+
margin: 0;
|
403 |
+
}
|
404 |
+
|
405 |
+
.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current {
|
406 |
+
position: absolute;
|
407 |
+
left: 11px;
|
408 |
+
top: 8px;
|
409 |
+
width: 2px;
|
410 |
+
height: 100px;
|
411 |
+
background: #ddd;
|
412 |
+
background: rgba(255, 255, 255, 0.9);
|
413 |
+
margin: 0;
|
414 |
+
}
|
415 |
+
|
416 |
+
.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle {
|
417 |
+
position: absolute;
|
418 |
+
left: 4px;
|
419 |
+
top: -3px;
|
420 |
+
width: 16px;
|
421 |
+
height: 6px;
|
422 |
+
background: #ddd;
|
423 |
+
background: rgba(255, 255, 255, 0.9);
|
424 |
+
cursor: N-resize;
|
425 |
+
-webkit-border-radius: 1px;
|
426 |
+
-moz-border-radius: 1px;
|
427 |
+
border-radius: 1px;
|
428 |
+
margin: 0;
|
429 |
+
}
|
430 |
+
|
431 |
+
|
432 |
+
/* horizontal version */
|
433 |
+
|
434 |
+
.mejs-controls div.mejs-horizontal-volume-slider {
|
435 |
+
height: 26px;
|
436 |
+
width: 60px;
|
437 |
+
position: relative;
|
438 |
+
}
|
439 |
+
|
440 |
+
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total {
|
441 |
+
position: absolute;
|
442 |
+
left: 0;
|
443 |
+
top: 11px;
|
444 |
+
width: 50px;
|
445 |
+
height: 8px;
|
446 |
+
margin: 0;
|
447 |
+
padding: 0;
|
448 |
+
font-size: 1px;
|
449 |
+
|
450 |
+
-webkit-border-radius: 2px;
|
451 |
+
-moz-border-radius: 2px;
|
452 |
+
border-radius: 2px;
|
453 |
+
|
454 |
+
background: #333;
|
455 |
+
background: rgba(50,50,50,0.8);
|
456 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8)));
|
457 |
+
background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
458 |
+
background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
459 |
+
background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
460 |
+
background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
461 |
+
background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8));
|
462 |
+
|
463 |
+
}
|
464 |
+
|
465 |
+
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current {
|
466 |
+
position: absolute;
|
467 |
+
left: 0;
|
468 |
+
top: 11px;
|
469 |
+
width: 50px;
|
470 |
+
height: 8px;
|
471 |
+
margin: 0;
|
472 |
+
padding: 0;
|
473 |
+
font-size: 1px;
|
474 |
+
|
475 |
+
-webkit-border-radius: 2px;
|
476 |
+
-moz-border-radius: 2px;
|
477 |
+
border-radius: 2px;
|
478 |
+
|
479 |
+
background: #fff;
|
480 |
+
background: rgba(255,255,255,0.8);
|
481 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8)));
|
482 |
+
background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
483 |
+
background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
484 |
+
background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
485 |
+
background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
486 |
+
background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8));
|
487 |
+
|
488 |
+
}
|
489 |
+
|
490 |
+
|
491 |
+
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle {
|
492 |
+
display: none;
|
493 |
+
}
|
494 |
+
|
495 |
+
/* End: Mute/Volume */
|
496 |
+
|
497 |
+
|
498 |
+
|
499 |
+
|
500 |
+
/* Start: TRACK (Captions and Chapters) */
|
501 |
+
.mejs-controls .mejs-captions-button {
|
502 |
+
position: relative;
|
503 |
+
}
|
504 |
+
|
505 |
+
.mejs-controls .mejs-captions-button button {
|
506 |
+
background-position:-48px 0;
|
507 |
+
}
|
508 |
+
.mejs-controls .mejs-captions-button .mejs-captions-selector {
|
509 |
+
visibility: hidden;
|
510 |
+
position: absolute;
|
511 |
+
bottom: 26px;
|
512 |
+
right: -10px;
|
513 |
+
width: 130px;
|
514 |
+
height: 100px;
|
515 |
+
background: url(background.png);
|
516 |
+
background: rgba(50,50,50,0.7);
|
517 |
+
border: solid 1px transparent;
|
518 |
+
padding: 10px;
|
519 |
+
overflow: hidden;
|
520 |
+
-webkit-border-radius: 0;
|
521 |
+
-moz-border-radius: 0;
|
522 |
+
border-radius: 0;
|
523 |
+
}
|
524 |
+
/*
|
525 |
+
.mejs-controls .mejs-captions-button:hover .mejs-captions-selector {
|
526 |
+
visibility: visible;
|
527 |
+
}
|
528 |
+
*/
|
529 |
+
|
530 |
+
.mejs-controls .mejs-captions-button .mejs-captions-selector ul {
|
531 |
+
margin: 0;
|
532 |
+
padding: 0;
|
533 |
+
display: block;
|
534 |
+
list-style-type: none !important;
|
535 |
+
overflow: hidden;
|
536 |
+
}
|
537 |
+
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li{
|
538 |
+
margin: 0 0 6px 0;
|
539 |
+
padding: 0;
|
540 |
+
list-style-type: none !important;
|
541 |
+
display:block;
|
542 |
+
color: #fff;
|
543 |
+
overflow: hidden;
|
544 |
+
}
|
545 |
+
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input{
|
546 |
+
clear: both;
|
547 |
+
float: left;
|
548 |
+
margin: 3px 3px 0 5px;
|
549 |
+
}
|
550 |
+
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label{
|
551 |
+
width: 100px;
|
552 |
+
float: left;
|
553 |
+
padding: 4px 0 0 0;
|
554 |
+
line-height: 15px;
|
555 |
+
font-family: helvetica, arial;
|
556 |
+
font-size: 10px;
|
557 |
+
}
|
558 |
+
|
559 |
+
.mejs-controls .mejs-captions-button .mejs-captions-translations {
|
560 |
+
font-size: 10px;
|
561 |
+
margin: 0 0 5px 0;
|
562 |
+
}
|
563 |
+
|
564 |
+
|
565 |
+
.mejs-chapters {
|
566 |
+
position: absolute;
|
567 |
+
top: 0;
|
568 |
+
left: 0;
|
569 |
+
-xborder-right: solid 1px #fff;
|
570 |
+
width: 10000px;
|
571 |
+
z-index: 1;
|
572 |
+
}
|
573 |
+
.mejs-chapters .mejs-chapter {
|
574 |
+
position: absolute;
|
575 |
+
float: left;
|
576 |
+
background: #222;
|
577 |
+
background: rgba(0, 0, 0, 0.7);
|
578 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7)));
|
579 |
+
background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
580 |
+
background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
581 |
+
background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
582 |
+
background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
583 |
+
background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7));
|
584 |
+
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#323232,endColorstr=#000000);
|
585 |
+
overflow: hidden;
|
586 |
+
border: 0;
|
587 |
+
}
|
588 |
+
.mejs-chapters .mejs-chapter .mejs-chapter-block {
|
589 |
+
font-size: 11px;
|
590 |
+
color: #fff;
|
591 |
+
padding: 5px;
|
592 |
+
display: block;
|
593 |
+
border-right: solid 1px #333;
|
594 |
+
border-bottom: solid 1px #333;
|
595 |
+
cursor: pointer;
|
596 |
+
}
|
597 |
+
.mejs-chapters .mejs-chapter .mejs-chapter-block-last {
|
598 |
+
border-right: none;
|
599 |
+
}
|
600 |
+
|
601 |
+
.mejs-chapters .mejs-chapter .mejs-chapter-block:hover {
|
602 |
+
/*background: #333;*/
|
603 |
+
background: #666;
|
604 |
+
background: rgba(102,102,102, 0.7);
|
605 |
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(102,102,102,0.7)), to(rgba(50,50,50,0.6)));
|
606 |
+
background: -webkit-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
607 |
+
background: -moz-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
608 |
+
background: -o-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
609 |
+
background: -ms-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
610 |
+
background: linear-gradient(rgba(102,102,102,0.7), rgba(50,50,50,0.6));
|
611 |
+
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#666666,endColorstr=#323232);
|
612 |
+
}
|
613 |
+
.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title{
|
614 |
+
font-size: 12px;
|
615 |
+
font-weight: bold;
|
616 |
+
display: block;
|
617 |
+
white-space:nowrap;
|
618 |
+
text-overflow: ellipsis;
|
619 |
+
margin: 0 0 3px 0;
|
620 |
+
line-height: 12px;
|
621 |
+
}
|
622 |
+
.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan{
|
623 |
+
font-size: 12px;
|
624 |
+
line-height: 12px;
|
625 |
+
margin: 3px 0 4px 0;
|
626 |
+
display: block;
|
627 |
+
white-space:nowrap;
|
628 |
+
text-overflow: ellipsis;
|
629 |
+
}
|
630 |
+
|
631 |
+
|
632 |
+
.mejs-captions-layer {
|
633 |
+
position: absolute;
|
634 |
+
bottom: 0;
|
635 |
+
left: 0;
|
636 |
+
text-align:center;
|
637 |
+
/*font-weight: bold;*/
|
638 |
+
line-height: 22px;
|
639 |
+
font-size: 12px;
|
640 |
+
color: #fff;
|
641 |
+
}
|
642 |
+
.mejs-captions-layer a {
|
643 |
+
color: #fff;
|
644 |
+
text-decoration: underline;
|
645 |
+
}
|
646 |
+
.mejs-captions-layer[lang=ar] {
|
647 |
+
font-size: 20px;
|
648 |
+
font-weight: normal;
|
649 |
+
}
|
650 |
+
|
651 |
+
.mejs-captions-position {
|
652 |
+
position: absolute;
|
653 |
+
width: 100%;
|
654 |
+
bottom: 15px;
|
655 |
+
left: 0;
|
656 |
+
}
|
657 |
+
|
658 |
+
.mejs-captions-position-hover {
|
659 |
+
bottom: 45px;
|
660 |
+
}
|
661 |
+
|
662 |
+
.mejs-captions-text {
|
663 |
+
padding: 3px 5px;
|
664 |
+
background: url(background.png);
|
665 |
+
background: rgba(20, 20, 20, 0.8);
|
666 |
+
|
667 |
+
}
|
668 |
+
/* End: TRACK (Captions and Chapters) */
|
669 |
+
|
670 |
+
|
671 |
+
|
672 |
+
.mejs-clear {
|
673 |
+
clear: both;
|
674 |
+
}
|
675 |
+
|
676 |
+
/* Start: ERROR */
|
677 |
+
.me-cannotplay {
|
678 |
+
}
|
679 |
+
.me-cannotplay a {
|
680 |
+
color: #fff;
|
681 |
+
font-weight: bold;
|
682 |
+
}
|
683 |
+
.me-cannotplay span {
|
684 |
+
padding: 15px;
|
685 |
+
display: block;
|
686 |
+
}
|
687 |
+
/* End: ERROR */
|
688 |
+
|
689 |
+
|
690 |
+
/* Start: Loop */
|
691 |
+
.mejs-controls .mejs-loop-off button{
|
692 |
+
background-position: -64px -16px;
|
693 |
+
}
|
694 |
+
.mejs-controls .mejs-loop-on button {
|
695 |
+
background-position: -64px 0;
|
696 |
+
}
|
697 |
+
/* End: Loop */
|
698 |
+
|
699 |
+
/* Start: backlight */
|
700 |
+
.mejs-controls .mejs-backlight-off button{
|
701 |
+
background-position: -80px -16px;
|
702 |
+
}
|
703 |
+
.mejs-controls .mejs-backlight-on button {
|
704 |
+
background-position: -80px 0;
|
705 |
+
}
|
706 |
+
/* End: backlight */
|
707 |
+
|
708 |
+
|
709 |
+
/* Start: picture controls */
|
710 |
+
.mejs-controls .mejs-picturecontrols-button{
|
711 |
+
background-position: -96px 0;
|
712 |
+
}
|
713 |
+
/* End: picture controls */
|
714 |
+
|
715 |
+
|
716 |
+
/* context menu */
|
717 |
+
.mejs-contextmenu {
|
718 |
+
position: absolute;
|
719 |
+
width: 150px;
|
720 |
+
padding: 10px;
|
721 |
+
border-radius: 4px;
|
722 |
+
top: 0;
|
723 |
+
left: 0;
|
724 |
+
background: #fff;
|
725 |
+
border: solid 1px #999;
|
726 |
+
z-index: 1001; /* make sure it shows on fullscreen */
|
727 |
+
}
|
728 |
+
.mejs-contextmenu .mejs-contextmenu-separator {
|
729 |
+
height: 1px;
|
730 |
+
font-size: 0;
|
731 |
+
margin: 5px 6px;
|
732 |
+
background: #333;
|
733 |
+
}
|
734 |
+
|
735 |
+
.mejs-contextmenu .mejs-contextmenu-item {
|
736 |
+
font-family: Helvetica, Arial;
|
737 |
+
font-size: 12px;
|
738 |
+
padding: 4px 6px;
|
739 |
+
cursor: pointer;
|
740 |
+
color: #333;
|
741 |
+
}
|
742 |
+
.mejs-contextmenu .mejs-contextmenu-item:hover {
|
743 |
+
background: #2C7C91;
|
744 |
+
color: #fff;
|
745 |
+
}
|
746 |
+
|
747 |
+
|
748 |
+
/* Start: SourceChooser */
|
749 |
+
.mejs-controls .mejs-sourcechooser-button {
|
750 |
+
position: relative;
|
751 |
+
}
|
752 |
+
|
753 |
+
.mejs-controls .mejs-sourcechooser-button button {
|
754 |
+
background-position: -128px 0;
|
755 |
+
}
|
756 |
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector {
|
757 |
+
visibility: hidden;
|
758 |
+
position: absolute;
|
759 |
+
bottom: 26px;
|
760 |
+
right: -10px;
|
761 |
+
width: 130px;
|
762 |
+
height: 100px;
|
763 |
+
background: url(background.png);
|
764 |
+
background: rgba(50,50,50,0.7);
|
765 |
+
border: solid 1px transparent;
|
766 |
+
padding: 10px;
|
767 |
+
overflow: hidden;
|
768 |
+
-webkit-border-radius: 0;
|
769 |
+
-moz-border-radius: 0;
|
770 |
+
border-radius: 0;
|
771 |
+
}
|
772 |
+
|
773 |
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul {
|
774 |
+
margin: 0;
|
775 |
+
padding: 0;
|
776 |
+
display: block;
|
777 |
+
list-style-type: none !important;
|
778 |
+
overflow: hidden;
|
779 |
+
}
|
780 |
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li{
|
781 |
+
margin: 0 0 6px 0;
|
782 |
+
padding: 0;
|
783 |
+
list-style-type: none !important;
|
784 |
+
display:block;
|
785 |
+
color: #fff;
|
786 |
+
overflow: hidden;
|
787 |
+
}
|
788 |
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input{
|
789 |
+
clear: both;
|
790 |
+
float: left;
|
791 |
+
margin: 3px 3px 0 5px;
|
792 |
+
}
|
793 |
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label{
|
794 |
+
width: 100px;
|
795 |
+
float: left;
|
796 |
+
padding: 4px 0 0 0;
|
797 |
+
line-height: 15px;
|
798 |
+
font-family: helvetica, arial;
|
799 |
+
font-size: 10px;
|
800 |
+
}
|
801 |
+
/* End: SourceChooser */
|
includes/media-element/mediaelementplayer.js
ADDED
@@ -0,0 +1,2743 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* MediaElementPlayer
|
3 |
+
* http://mediaelementjs.com/
|
4 |
+
*
|
5 |
+
* Creates a controller bar for HTML5 <video> add <audio> tags
|
6 |
+
* using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper)
|
7 |
+
*
|
8 |
+
* Copyright 2010-2012, John Dyer (http://j.hn/)
|
9 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
10 |
+
*
|
11 |
+
*/
|
12 |
+
if (typeof jQuery != 'undefined') {
|
13 |
+
mejs.$ = jQuery;
|
14 |
+
} else if (typeof ender != 'undefined') {
|
15 |
+
mejs.$ = ender;
|
16 |
+
}
|
17 |
+
(function ($) {
|
18 |
+
|
19 |
+
// default player values
|
20 |
+
mejs.MepDefaults = {
|
21 |
+
// url to poster (to fix iOS 3.x)
|
22 |
+
poster: '',
|
23 |
+
// default if the <video width> is not specified
|
24 |
+
defaultVideoWidth: 480,
|
25 |
+
// default if the <video height> is not specified
|
26 |
+
defaultVideoHeight: 270,
|
27 |
+
// if set, overrides <video width>
|
28 |
+
videoWidth: -1,
|
29 |
+
// if set, overrides <video height>
|
30 |
+
videoHeight: -1,
|
31 |
+
// default if the user doesn't specify
|
32 |
+
defaultAudioWidth: 400,
|
33 |
+
// default if the user doesn't specify
|
34 |
+
defaultAudioHeight: 30,
|
35 |
+
// width of audio player
|
36 |
+
audioWidth: -1,
|
37 |
+
// height of audio player
|
38 |
+
audioHeight: -1,
|
39 |
+
// initial volume when the player starts (overrided by user cookie)
|
40 |
+
startVolume: 0.8,
|
41 |
+
// useful for <audio> player loops
|
42 |
+
loop: false,
|
43 |
+
// resize to media dimensions
|
44 |
+
enableAutosize: true,
|
45 |
+
// forces the hour marker (##:00:00)
|
46 |
+
alwaysShowHours: false,
|
47 |
+
|
48 |
+
// show framecount in timecode (##:00:00:00)
|
49 |
+
showTimecodeFrameCount: false,
|
50 |
+
// used when showTimecodeFrameCount is set to true
|
51 |
+
framesPerSecond: 25,
|
52 |
+
|
53 |
+
// automatically calculate the width of the progress bar based on the sizes of other elements
|
54 |
+
autosizeProgress : true,
|
55 |
+
// Hide controls when playing and mouse is not over the video
|
56 |
+
alwaysShowControls: false,
|
57 |
+
// force iPad's native controls
|
58 |
+
iPadUseNativeControls: false,
|
59 |
+
// force iPhone's native controls
|
60 |
+
iPhoneUseNativeControls: false,
|
61 |
+
// force Android's native controls
|
62 |
+
AndroidUseNativeControls: false,
|
63 |
+
// features to show
|
64 |
+
features: ['playpause','current','progress','duration','tracks','volume','fullscreen'],
|
65 |
+
// only for dynamic
|
66 |
+
isVideo: true,
|
67 |
+
|
68 |
+
// turns keyboard support on and off for this instance
|
69 |
+
enableKeyboard: true,
|
70 |
+
|
71 |
+
// whenthis player starts, it will pause other players
|
72 |
+
pauseOtherPlayers: true,
|
73 |
+
|
74 |
+
// array of keyboard actions such as play pause
|
75 |
+
keyActions: [
|
76 |
+
{
|
77 |
+
keys: [
|
78 |
+
32, // SPACE
|
79 |
+
179 // GOOGLE play/pause button
|
80 |
+
],
|
81 |
+
action: function(player, media) {
|
82 |
+
if (media.paused || media.ended) {
|
83 |
+
media.play();
|
84 |
+
} else {
|
85 |
+
media.pause();
|
86 |
+
}
|
87 |
+
}
|
88 |
+
},
|
89 |
+
{
|
90 |
+
keys: [38], // UP
|
91 |
+
action: function(player, media) {
|
92 |
+
var newVolume = Math.min(media.volume + 0.1, 1);
|
93 |
+
media.setVolume(newVolume);
|
94 |
+
}
|
95 |
+
},
|
96 |
+
{
|
97 |
+
keys: [40], // DOWN
|
98 |
+
action: function(player, media) {
|
99 |
+
var newVolume = Math.max(media.volume - 0.1, 0);
|
100 |
+
media.setVolume(newVolume);
|
101 |
+
}
|
102 |
+
},
|
103 |
+
{
|
104 |
+
keys: [
|
105 |
+
37, // LEFT
|
106 |
+
227 // Google TV rewind
|
107 |
+
],
|
108 |
+
action: function(player, media) {
|
109 |
+
if (!isNaN(media.duration) && media.duration > 0) {
|
110 |
+
if (player.isVideo) {
|
111 |
+
player.showControls();
|
112 |
+
player.startControlsTimer();
|
113 |
+
}
|
114 |
+
|
115 |
+
// 5%
|
116 |
+
var newTime = Math.max(media.currentTime - (media.duration * 0.05), 0);
|
117 |
+
media.setCurrentTime(newTime);
|
118 |
+
}
|
119 |
+
}
|
120 |
+
},
|
121 |
+
{
|
122 |
+
keys: [
|
123 |
+
39, // RIGHT
|
124 |
+
228 // Google TV forward
|
125 |
+
],
|
126 |
+
action: function(player, media) {
|
127 |
+
if (!isNaN(media.duration) && media.duration > 0) {
|
128 |
+
if (player.isVideo) {
|
129 |
+
player.showControls();
|
130 |
+
player.startControlsTimer();
|
131 |
+
}
|
132 |
+
|
133 |
+
// 5%
|
134 |
+
var newTime = Math.min(media.currentTime + (media.duration * 0.05), media.duration);
|
135 |
+
media.setCurrentTime(newTime);
|
136 |
+
}
|
137 |
+
}
|
138 |
+
},
|
139 |
+
{
|
140 |
+
keys: [70], // f
|
141 |
+
action: function(player, media) {
|
142 |
+
if (typeof player.enterFullScreen != 'undefined') {
|
143 |
+
if (player.isFullScreen) {
|
144 |
+
player.exitFullScreen();
|
145 |
+
} else {
|
146 |
+
player.enterFullScreen();
|
147 |
+
}
|
148 |
+
}
|
149 |
+
}
|
150 |
+
}
|
151 |
+
]
|
152 |
+
};
|
153 |
+
|
154 |
+
mejs.mepIndex = 0;
|
155 |
+
|
156 |
+
mejs.players = [];
|
157 |
+
|
158 |
+
// wraps a MediaElement object in player controls
|
159 |
+
mejs.MediaElementPlayer = function(node, o) {
|
160 |
+
// enforce object, even without "new" (via John Resig)
|
161 |
+
if ( !(this instanceof mejs.MediaElementPlayer) ) {
|
162 |
+
return new mejs.MediaElementPlayer(node, o);
|
163 |
+
}
|
164 |
+
|
165 |
+
var t = this;
|
166 |
+
|
167 |
+
// these will be reset after the MediaElement.success fires
|
168 |
+
t.$media = t.$node = $(node);
|
169 |
+
t.node = t.media = t.$media[0];
|
170 |
+
|
171 |
+
// check for existing player
|
172 |
+
if (typeof t.node.player != 'undefined') {
|
173 |
+
return t.node.player;
|
174 |
+
} else {
|
175 |
+
// attach player to DOM node for reference
|
176 |
+
t.node.player = t;
|
177 |
+
}
|
178 |
+
|
179 |
+
|
180 |
+
// try to get options from data-mejsoptions
|
181 |
+
if (typeof o == 'undefined') {
|
182 |
+
o = t.$node.data('mejsoptions');
|
183 |
+
}
|
184 |
+
|
185 |
+
// extend default options
|
186 |
+
t.options = $.extend({},mejs.MepDefaults,o);
|
187 |
+
|
188 |
+
// add to player array (for focus events)
|
189 |
+
mejs.players.push(t);
|
190 |
+
|
191 |
+
// start up
|
192 |
+
t.init();
|
193 |
+
|
194 |
+
return t;
|
195 |
+
};
|
196 |
+
|
197 |
+
// actual player
|
198 |
+
mejs.MediaElementPlayer.prototype = {
|
199 |
+
|
200 |
+
hasFocus: false,
|
201 |
+
|
202 |
+
controlsAreVisible: true,
|
203 |
+
|
204 |
+
init: function() {
|
205 |
+
|
206 |
+
var
|
207 |
+
t = this,
|
208 |
+
mf = mejs.MediaFeatures,
|
209 |
+
// options for MediaElement (shim)
|
210 |
+
meOptions = $.extend(true, {}, t.options, {
|
211 |
+
success: function(media, domNode) { t.meReady(media, domNode); },
|
212 |
+
error: function(e) { t.handleError(e);}
|
213 |
+
}),
|
214 |
+
tagName = t.media.tagName.toLowerCase();
|
215 |
+
|
216 |
+
t.isDynamic = (tagName !== 'audio' && tagName !== 'video');
|
217 |
+
|
218 |
+
if (t.isDynamic) {
|
219 |
+
// get video from src or href?
|
220 |
+
t.isVideo = t.options.isVideo;
|
221 |
+
} else {
|
222 |
+
t.isVideo = (tagName !== 'audio' && t.options.isVideo);
|
223 |
+
}
|
224 |
+
|
225 |
+
// use native controls in iPad, iPhone, and Android
|
226 |
+
if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) {
|
227 |
+
|
228 |
+
// add controls and stop
|
229 |
+
t.$media.attr('controls', 'controls');
|
230 |
+
|
231 |
+
// attempt to fix iOS 3 bug
|
232 |
+
//t.$media.removeAttr('poster');
|
233 |
+
// no Issue found on iOS3 -ttroxell
|
234 |
+
|
235 |
+
// override Apple's autoplay override for iPads
|
236 |
+
if (mf.isiPad && t.media.getAttribute('autoplay') !== null) {
|
237 |
+
t.media.load();
|
238 |
+
t.media.play();
|
239 |
+
}
|
240 |
+
|
241 |
+
} else if (mf.isAndroid && t.AndroidUseNativeControls) {
|
242 |
+
|
243 |
+
// leave default player
|
244 |
+
|
245 |
+
} else {
|
246 |
+
|
247 |
+
// DESKTOP: use MediaElementPlayer controls
|
248 |
+
|
249 |
+
// remove native controls
|
250 |
+
t.$media.removeAttr('controls');
|
251 |
+
|
252 |
+
// unique ID
|
253 |
+
t.id = 'mep_' + mejs.mepIndex++;
|
254 |
+
|
255 |
+
// build container
|
256 |
+
t.container =
|
257 |
+
$('<div id="' + t.id + '" class="mejs-container">'+
|
258 |
+
'<div class="mejs-inner">'+
|
259 |
+
'<div class="mejs-mediaelement"></div>'+
|
260 |
+
'<div class="mejs-layers"></div>'+
|
261 |
+
'<div class="mejs-controls"></div>'+
|
262 |
+
'<div class="mejs-clear"></div>'+
|
263 |
+
'</div>' +
|
264 |
+
'</div>')
|
265 |
+
.addClass(t.$media[0].className)
|
266 |
+
.insertBefore(t.$media);
|
267 |
+
|
268 |
+
// add classes for user and content
|
269 |
+
t.container.addClass(
|
270 |
+
(mf.isAndroid ? 'mejs-android ' : '') +
|
271 |
+
(mf.isiOS ? 'mejs-ios ' : '') +
|
272 |
+
(mf.isiPad ? 'mejs-ipad ' : '') +
|
273 |
+
(mf.isiPhone ? 'mejs-iphone ' : '') +
|
274 |
+
(t.isVideo ? 'mejs-video ' : 'mejs-audio ')
|
275 |
+
);
|
276 |
+
|
277 |
+
|
278 |
+
// move the <video/video> tag into the right spot
|
279 |
+
if (mf.isiOS) {
|
280 |
+
|
281 |
+
// sadly, you can't move nodes in iOS, so we have to destroy and recreate it!
|
282 |
+
var $newMedia = t.$media.clone();
|
283 |
+
|
284 |
+
t.container.find('.mejs-mediaelement').append($newMedia);
|
285 |
+
|
286 |
+
t.$media.remove();
|
287 |
+
t.$node = t.$media = $newMedia;
|
288 |
+
t.node = t.media = $newMedia[0]
|
289 |
+
|
290 |
+
} else {
|
291 |
+
|
292 |
+
// normal way of moving it into place (doesn't work on iOS)
|
293 |
+
t.container.find('.mejs-mediaelement').append(t.$media);
|
294 |
+
}
|
295 |
+
|
296 |
+
// find parts
|
297 |
+
t.controls = t.container.find('.mejs-controls');
|
298 |
+
t.layers = t.container.find('.mejs-layers');
|
299 |
+
|
300 |
+
// determine the size
|
301 |
+
|
302 |
+
/* size priority:
|
303 |
+
(1) videoWidth (forced),
|
304 |
+
(2) style="width;height;"
|
305 |
+
(3) width attribute,
|
306 |
+
(4) defaultVideoWidth (for unspecified cases)
|
307 |
+
*/
|
308 |
+
|
309 |
+
var capsTagName = tagName.substring(0,1).toUpperCase() + tagName.substring(1);
|
310 |
+
|
311 |
+
if (t.options[tagName + 'Width'] > 0 || t.options[tagName + 'Width'].toString().indexOf('%') > -1) {
|
312 |
+
t.width = t.options[tagName + 'Width'];
|
313 |
+
} else if (t.media.style.width !== '' && t.media.style.width !== null) {
|
314 |
+
t.width = t.media.style.width;
|
315 |
+
} else if (t.media.getAttribute('width') !== null) {
|
316 |
+
t.width = t.$media.attr('width');
|
317 |
+
} else {
|
318 |
+
t.width = t.options['default' + capsTagName + 'Width'];
|
319 |
+
}
|
320 |
+
|
321 |
+
if (t.options[tagName + 'Height'] > 0 || t.options[tagName + 'Height'].toString().indexOf('%') > -1) {
|
322 |
+
t.height = t.options[tagName + 'Height'];
|
323 |
+
} else if (t.media.style.height !== '' && t.media.style.height !== null) {
|
324 |
+
t.height = t.media.style.height;
|
325 |
+
} else if (t.$media[0].getAttribute('height') !== null) {
|
326 |
+
t.height = t.$media.attr('height');
|
327 |
+
} else {
|
328 |
+
t.height = t.options['default' + capsTagName + 'Height'];
|
329 |
+
}
|
330 |
+
|
331 |
+
// set the size, while we wait for the plugins to load below
|
332 |
+
t.setPlayerSize(t.width, t.height);
|
333 |
+
|
334 |
+
// create MediaElementShim
|
335 |
+
meOptions.pluginWidth = t.height;
|
336 |
+
meOptions.pluginHeight = t.width;
|
337 |
+
}
|
338 |
+
|
339 |
+
|
340 |
+
|
341 |
+
// create MediaElement shim
|
342 |
+
mejs.MediaElement(t.$media[0], meOptions);
|
343 |
+
},
|
344 |
+
|
345 |
+
showControls: function(doAnimation) {
|
346 |
+
var t = this;
|
347 |
+
|
348 |
+
doAnimation = typeof doAnimation == 'undefined' || doAnimation;
|
349 |
+
|
350 |
+
if (t.controlsAreVisible)
|
351 |
+
return;
|
352 |
+
|
353 |
+
if (doAnimation) {
|
354 |
+
t.controls
|
355 |
+
.css('visibility','visible')
|
356 |
+
.stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
|
357 |
+
|
358 |
+
// any additional controls people might add and want to hide
|
359 |
+
t.container.find('.mejs-control')
|
360 |
+
.css('visibility','visible')
|
361 |
+
.stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
|
362 |
+
|
363 |
+
} else {
|
364 |
+
t.controls
|
365 |
+
.css('visibility','visible')
|
366 |
+
.css('display','block');
|
367 |
+
|
368 |
+
// any additional controls people might add and want to hide
|
369 |
+
t.container.find('.mejs-control')
|
370 |
+
.css('visibility','visible')
|
371 |
+
.css('display','block');
|
372 |
+
|
373 |
+
t.controlsAreVisible = true;
|
374 |
+
}
|
375 |
+
|
376 |
+
t.setControlsSize();
|
377 |
+
|
378 |
+
},
|
379 |
+
|
380 |
+
hideControls: function(doAnimation) {
|
381 |
+
var t = this;
|
382 |
+
|
383 |
+
doAnimation = typeof doAnimation == 'undefined' || doAnimation;
|
384 |
+
|
385 |
+
if (!t.controlsAreVisible)
|
386 |
+
return;
|
387 |
+
|
388 |
+
if (doAnimation) {
|
389 |
+
// fade out main controls
|
390 |
+
t.controls.stop(true, true).fadeOut(200, function() {
|
391 |
+
$(this)
|
392 |
+
.css('visibility','hidden')
|
393 |
+
.css('display','block');
|
394 |
+
|
395 |
+
t.controlsAreVisible = false;
|
396 |
+
});
|
397 |
+
|
398 |
+
// any additional controls people might add and want to hide
|
399 |
+
t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() {
|
400 |
+
$(this)
|
401 |
+
.css('visibility','hidden')
|
402 |
+
.css('display','block');
|
403 |
+
});
|
404 |
+
} else {
|
405 |
+
|
406 |
+
// hide main controls
|
407 |
+
t.controls
|
408 |
+
.css('visibility','hidden')
|
409 |
+
.css('display','block');
|
410 |
+
|
411 |
+
// hide others
|
412 |
+
t.container.find('.mejs-control')
|
413 |
+
.css('visibility','hidden')
|
414 |
+
.css('display','block');
|
415 |
+
|
416 |
+
t.controlsAreVisible = false;
|
417 |
+
}
|
418 |
+
},
|
419 |
+
|
420 |
+
controlsTimer: null,
|
421 |
+
|
422 |
+
startControlsTimer: function(timeout) {
|
423 |
+
|
424 |
+
var t = this;
|
425 |
+
|
426 |
+
timeout = typeof timeout != 'undefined' ? timeout : 1500;
|
427 |
+
|
428 |
+
t.killControlsTimer('start');
|
429 |
+
|
430 |
+
t.controlsTimer = setTimeout(function() {
|
431 |
+
//console.log('timer fired');
|
432 |
+
t.hideControls();
|
433 |
+
t.killControlsTimer('hide');
|
434 |
+
}, timeout);
|
435 |
+
},
|
436 |
+
|
437 |
+
killControlsTimer: function(src) {
|
438 |
+
|
439 |
+
var t = this;
|
440 |
+
|
441 |
+
if (t.controlsTimer !== null) {
|
442 |
+
clearTimeout(t.controlsTimer);
|
443 |
+
delete t.controlsTimer;
|
444 |
+
t.controlsTimer = null;
|
445 |
+
}
|
446 |
+
},
|
447 |
+
|
448 |
+
controlsEnabled: true,
|
449 |
+
|
450 |
+
disableControls: function() {
|
451 |
+
var t= this;
|
452 |
+
|
453 |
+
t.killControlsTimer();
|
454 |
+
t.hideControls(false);
|
455 |
+
this.controlsEnabled = false;
|
456 |
+
},
|
457 |
+
|
458 |
+
enableControls: function() {
|
459 |
+
var t= this;
|
460 |
+
|
461 |
+
t.showControls(false);
|
462 |
+
|
463 |
+
t.controlsEnabled = true;
|
464 |
+
},
|
465 |
+
|
466 |
+
|
467 |
+
// Sets up all controls and events
|
468 |
+
meReady: function(media, domNode) {
|
469 |
+
|
470 |
+
|
471 |
+
var t = this,
|
472 |
+
mf = mejs.MediaFeatures,
|
473 |
+
autoplayAttr = domNode.getAttribute('autoplay'),
|
474 |
+
autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'),
|
475 |
+
featureIndex,
|
476 |
+
feature;
|
477 |
+
|
478 |
+
// make sure it can't create itself again if a plugin reloads
|
479 |
+
if (t.created)
|
480 |
+
return;
|
481 |
+
else
|
482 |
+
t.created = true;
|
483 |
+
|
484 |
+
t.media = media;
|
485 |
+
t.domNode = domNode;
|
486 |
+
|
487 |
+
if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) {
|
488 |
+
|
489 |
+
// two built in features
|
490 |
+
t.buildposter(t, t.controls, t.layers, t.media);
|
491 |
+
t.buildkeyboard(t, t.controls, t.layers, t.media);
|
492 |
+
t.buildoverlays(t, t.controls, t.layers, t.media);
|
493 |
+
|
494 |
+
// grab for use by features
|
495 |
+
t.findTracks();
|
496 |
+
|
497 |
+
// add user-defined features/controls
|
498 |
+
for (featureIndex in t.options.features) {
|
499 |
+
feature = t.options.features[featureIndex];
|
500 |
+
if (t['build' + feature]) {
|
501 |
+
try {
|
502 |
+
t['build' + feature](t, t.controls, t.layers, t.media);
|
503 |
+
} catch (e) {
|
504 |
+
// TODO: report control error
|
505 |
+
//throw e;
|
506 |
+
//console.log('error building ' + feature);
|
507 |
+
//console.log(e);
|
508 |
+
}
|
509 |
+
}
|
510 |
+
}
|
511 |
+
|
512 |
+
t.container.trigger('controlsready');
|
513 |
+
|
514 |
+
// reset all layers and controls
|
515 |
+
t.setPlayerSize(t.width, t.height);
|
516 |
+
t.setControlsSize();
|
517 |
+
|
518 |
+
|
519 |
+
// controls fade
|
520 |
+
if (t.isVideo) {
|
521 |
+
|
522 |
+
if (mejs.MediaFeatures.hasTouch) {
|
523 |
+
|
524 |
+
// for touch devices (iOS, Android)
|
525 |
+
// show/hide without animation on touch
|
526 |
+
|
527 |
+
t.$media.bind('touchstart', function() {
|
528 |
+
|
529 |
+
|
530 |
+
// toggle controls
|
531 |
+
if (t.controlsAreVisible) {
|
532 |
+
t.hideControls(false);
|
533 |
+
} else {
|
534 |
+
if (t.controlsEnabled) {
|
535 |
+
t.showControls(false);
|
536 |
+
}
|
537 |
+
}
|
538 |
+
});
|
539 |
+
|
540 |
+
} else {
|
541 |
+
// click controls
|
542 |
+
var clickElement = (t.media.pluginType == 'native') ? t.$media : $(t.media.pluginElement);
|
543 |
+
|
544 |
+
// click to play/pause
|
545 |
+
clickElement.click(function() {
|
546 |
+
if (media.paused) {
|
547 |
+
media.play();
|
548 |
+
} else {
|
549 |
+
media.pause();
|
550 |
+
}
|
551 |
+
});
|
552 |
+
|
553 |
+
|
554 |
+
// show/hide controls
|
555 |
+
t.container
|
556 |
+
.bind('mouseenter mouseover', function () {
|
557 |
+
if (t.controlsEnabled) {
|
558 |
+
if (!t.options.alwaysShowControls) {
|
559 |
+
t.killControlsTimer('enter');
|
560 |
+
t.showControls();
|
561 |
+
t.startControlsTimer(2500);
|
562 |
+
}
|
563 |
+
}
|
564 |
+
})
|
565 |
+
.bind('mousemove', function() {
|
566 |
+
if (t.controlsEnabled) {
|
567 |
+
if (!t.controlsAreVisible) {
|
568 |
+
t.showControls();
|
569 |
+
}
|
570 |
+
//t.killControlsTimer('move');
|
571 |
+
if (!t.options.alwaysShowControls) {
|
572 |
+
t.startControlsTimer(2500);
|
573 |
+
}
|
574 |
+
}
|
575 |
+
})
|
576 |
+
.bind('mouseleave', function () {
|
577 |
+
if (t.controlsEnabled) {
|
578 |
+
if (!t.media.paused && !t.options.alwaysShowControls) {
|
579 |
+
t.startControlsTimer(1000);
|
580 |
+
}
|
581 |
+
}
|
582 |
+
});
|
583 |
+
}
|
584 |
+
|
585 |
+
// check for autoplay
|
586 |
+
if (autoplay && !t.options.alwaysShowControls) {
|
587 |
+
t.hideControls();
|
588 |
+
}
|
589 |
+
|
590 |
+
// resizer
|
591 |
+
if (t.options.enableAutosize) {
|
592 |
+
t.media.addEventListener('loadedmetadata', function(e) {
|
593 |
+
// if the <video height> was not set and the options.videoHeight was not set
|
594 |
+
// then resize to the real dimensions
|
595 |
+
if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) {
|
596 |
+
t.setPlayerSize(e.target.videoWidth, e.target.videoHeight);
|
597 |
+
t.setControlsSize();
|
598 |
+
t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight);
|
599 |
+
}
|
600 |
+
}, false);
|
601 |
+
}
|
602 |
+
}
|
603 |
+
|
604 |
+
// EVENTS
|
605 |
+
|
606 |
+
// FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them)
|
607 |
+
media.addEventListener('play', function() {
|
608 |
+
|
609 |
+
// go through all other players
|
610 |
+
for (var i=0, il=mejs.players.length; i<il; i++) {
|
611 |
+
var p = mejs.players[i];
|
612 |
+
if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) {
|
613 |
+
p.pause();
|
614 |
+
}
|
615 |
+
p.hasFocus = false;
|
616 |
+
}
|
617 |
+
|
618 |
+
t.hasFocus = true;
|
619 |
+
},false);
|
620 |
+
|
621 |
+
|
622 |
+
// ended for all
|
623 |
+
t.media.addEventListener('ended', function (e) {
|
624 |
+
try{
|
625 |
+
t.media.setCurrentTime(0);
|
626 |
+
} catch (exp) {
|
627 |
+
|
628 |
+
}
|
629 |
+
t.media.pause();
|
630 |
+
|
631 |
+
if (t.setProgressRail)
|
632 |
+
t.setProgressRail();
|
633 |
+
if (t.setCurrentRail)
|
634 |
+
t.setCurrentRail();
|
635 |
+
|
636 |
+
if (t.options.loop) {
|
637 |
+
t.media.play();
|
638 |
+
} else if (!t.options.alwaysShowControls && t.controlsEnabled) {
|
639 |
+
t.showControls();
|
640 |
+
}
|
641 |
+
}, false);
|
642 |
+
|
643 |
+
// resize on the first play
|
644 |
+
t.media.addEventListener('loadedmetadata', function(e) {
|
645 |
+
if (t.updateDuration) {
|
646 |
+
t.updateDuration();
|
647 |
+
}
|
648 |
+
if (t.updateCurrent) {
|
649 |
+
t.updateCurrent();
|
650 |
+
}
|
651 |
+
|
652 |
+
if (!t.isFullScreen) {
|
653 |
+
t.setPlayerSize(t.width, t.height);
|
654 |
+
t.setControlsSize();
|
655 |
+
}
|
656 |
+
}, false);
|
657 |
+
|
658 |
+
|
659 |
+
// webkit has trouble doing this without a delay
|
660 |
+
setTimeout(function () {
|
661 |
+
t.setPlayerSize(t.width, t.height);
|
662 |
+
t.setControlsSize();
|
663 |
+
}, 50);
|
664 |
+
|
665 |
+
// adjust controls whenever window sizes (used to be in fullscreen only)
|
666 |
+
$(window).resize(function() {
|
667 |
+
|
668 |
+
// don't resize for fullscreen mode
|
669 |
+
if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) {
|
670 |
+
t.setPlayerSize(t.width, t.height);
|
671 |
+
}
|
672 |
+
|
673 |
+
// always adjust controls
|
674 |
+
t.setControlsSize();
|
675 |
+
});
|
676 |
+
|
677 |
+
// TEMP: needs to be moved somewhere else
|
678 |
+
if (t.media.pluginType == 'youtube') {
|
679 |
+
t.container.find('.mejs-overlay-play').hide();
|
680 |
+
}
|
681 |
+
}
|
682 |
+
|
683 |
+
// force autoplay for HTML5
|
684 |
+
if (autoplay && media.pluginType == 'native') {
|
685 |
+
media.load();
|
686 |
+
media.play();
|
687 |
+
}
|
688 |
+
|
689 |
+
|
690 |
+
if (t.options.success) {
|
691 |
+
|
692 |
+
if (typeof t.options.success == 'string') {
|
693 |
+
window[t.options.success](t.media, t.domNode, t);
|
694 |
+
} else {
|
695 |
+
t.options.success(t.media, t.domNode, t);
|
696 |
+
}
|
697 |
+
}
|
698 |
+
},
|
699 |
+
|
700 |
+
handleError: function(e) {
|
701 |
+
var t = this;
|
702 |
+
|
703 |
+
t.controls.hide();
|
704 |
+
|
705 |
+
// Tell user that the file cannot be played
|
706 |
+
if (t.options.error) {
|
707 |
+
t.options.error(e);
|
708 |
+
}
|
709 |
+
},
|
710 |
+
|
711 |
+
setPlayerSize: function(width,height) {
|
712 |
+
var t = this;
|
713 |
+
|
714 |
+
if (typeof width != 'undefined')
|
715 |
+
t.width = width;
|
716 |
+
|
717 |
+
if (typeof height != 'undefined')
|
718 |
+
t.height = height;
|
719 |
+
|
720 |
+
// detect 100% mode
|
721 |
+
if (t.height.toString().indexOf('%') > 0) {
|
722 |
+
|
723 |
+
// do we have the native dimensions yet?
|
724 |
+
var
|
725 |
+
nativeWidth = (t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth,
|
726 |
+
nativeHeight = (t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight,
|
727 |
+
parentWidth = t.container.parent().width(),
|
728 |
+
newHeight = parseInt(parentWidth * nativeHeight/nativeWidth, 10);
|
729 |
+
|
730 |
+
if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) {
|
731 |
+
parentWidth = $(window).width();
|
732 |
+
newHeight = $(window).height();
|
733 |
+
}
|
734 |
+
|
735 |
+
|
736 |
+
// set outer container size
|
737 |
+
t.container
|
738 |
+
.width(parentWidth)
|
739 |
+
.height(newHeight);
|
740 |
+
|
741 |
+
// set native <video>
|
742 |
+
t.$media
|
743 |
+
.width('100%')
|
744 |
+
.height('100%');
|
745 |
+
|
746 |
+
// set shims
|
747 |
+
t.container.find('object, embed, iframe')
|
748 |
+
.width('100%')
|
749 |
+
.height('100%');
|
750 |
+
|
751 |
+
// if shim is ready, send the size to the embeded plugin
|
752 |
+
if (t.media.setVideoSize)
|
753 |
+
t.media.setVideoSize(parentWidth, newHeight);
|
754 |
+
|
755 |
+
// set the layers
|
756 |
+
t.layers.children('.mejs-layer')
|
757 |
+
.width('100%')
|
758 |
+
.height('100%');
|
759 |
+
|
760 |
+
|
761 |
+
} else {
|
762 |
+
|
763 |
+
t.container
|
764 |
+
.width(t.width)
|
765 |
+
.height(t.height);
|
766 |
+
|
767 |
+
t.layers.children('.mejs-layer')
|
768 |
+
.width(t.width)
|
769 |
+
.height(t.height);
|
770 |
+
|
771 |
+
}
|
772 |
+
},
|
773 |
+
|
774 |
+
setControlsSize: function() {
|
775 |
+
var t = this,
|
776 |
+
usedWidth = 0,
|
777 |
+
railWidth = 0,
|
778 |
+
rail = t.controls.find('.mejs-time-rail'),
|
779 |
+
total = t.controls.find('.mejs-time-total'),
|
780 |
+
current = t.controls.find('.mejs-time-current'),
|
781 |
+
loaded = t.controls.find('.mejs-time-loaded'),
|
782 |
+
others = rail.siblings();
|
783 |
+
|
784 |
+
|
785 |
+
// allow the size to come from custom CSS
|
786 |
+
if (t.options && !t.options.autosizeProgress) {
|
787 |
+
// Also, frontends devs can be more flexible
|
788 |
+
// due the opportunity of absolute positioning.
|
789 |
+
railWidth = parseInt(rail.css('width'));
|
790 |
+
}
|
791 |
+
|
792 |
+
// attempt to autosize
|
793 |
+
if (railWidth === 0 || !railWidth) {
|
794 |
+
|
795 |
+
// find the size of all the other controls besides the rail
|
796 |
+
others.each(function() {
|
797 |
+
if ($(this).css('position') != 'absolute') {
|
798 |
+
usedWidth += $(this).outerWidth(true);
|
799 |
+
}
|
800 |
+
});
|
801 |
+
|
802 |
+
// fit the rail into the remaining space
|
803 |
+
railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.width());
|
804 |
+
}
|
805 |
+
|
806 |
+
// outer area
|
807 |
+
rail.width(railWidth);
|
808 |
+
// dark space
|
809 |
+
total.width(railWidth - (total.outerWidth(true) - total.width()));
|
810 |
+
|
811 |
+
if (t.setProgressRail)
|
812 |
+
t.setProgressRail();
|
813 |
+
if (t.setCurrentRail)
|
814 |
+
t.setCurrentRail();
|
815 |
+
},
|
816 |
+
|
817 |
+
|
818 |
+
buildposter: function(player, controls, layers, media) {
|
819 |
+
var t = this,
|
820 |
+
poster =
|
821 |
+
$('<div class="mejs-poster mejs-layer">' +
|
822 |
+
'</div>')
|
823 |
+
.appendTo(layers),
|
824 |
+
posterUrl = player.$media.attr('poster');
|
825 |
+
|
826 |
+
// prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster)
|
827 |
+
if (player.options.poster !== '') {
|
828 |
+
posterUrl = player.options.poster;
|
829 |
+
}
|
830 |
+
|
831 |
+
// second, try the real poster
|
832 |
+
if (posterUrl !== '' && posterUrl != null) {
|
833 |
+
t.setPoster(posterUrl);
|
834 |
+
} else {
|
835 |
+
poster.hide();
|
836 |
+
}
|
837 |
+
|
838 |
+
media.addEventListener('play',function() {
|
839 |
+
poster.hide();
|
840 |
+
}, false);
|
841 |
+
},
|
842 |
+
|
843 |
+
setPoster: function(url) {
|
844 |
+
var t = this,
|
845 |
+
posterDiv = t.container.find('.mejs-poster'),
|
846 |
+
posterImg = posterDiv.find('img');
|
847 |
+
|
848 |
+
if (posterImg.length == 0) {
|
849 |
+
posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv);
|
850 |
+
}
|
851 |
+
|
852 |
+
posterImg.attr('src', url);
|
853 |
+
},
|
854 |
+
|
855 |
+
buildoverlays: function(player, controls, layers, media) {
|
856 |
+
if (!player.isVideo)
|
857 |
+
return;
|
858 |
+
|
859 |
+
var
|
860 |
+
loading =
|
861 |
+
$('<div class="mejs-overlay mejs-layer">'+
|
862 |
+
'<div class="mejs-overlay-loading"><span></span></div>'+
|
863 |
+
'</div>')
|
864 |
+
.hide() // start out hidden
|
865 |
+
.appendTo(layers),
|
866 |
+
error =
|
867 |
+
$('<div class="mejs-overlay mejs-layer">'+
|
868 |
+
'<div class="mejs-overlay-error"></div>'+
|
869 |
+
'</div>')
|
870 |
+
.hide() // start out hidden
|
871 |
+
.appendTo(layers),
|
872 |
+
// this needs to come last so it's on top
|
873 |
+
bigPlay =
|
874 |
+
$('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+
|
875 |
+
'<div class="mejs-overlay-button"></div>'+
|
876 |
+
'</div>')
|
877 |
+
.appendTo(layers)
|
878 |
+
.click(function() {
|
879 |
+
if (media.paused) {
|
880 |
+
media.play();
|
881 |
+
} else {
|
882 |
+
media.pause();
|
883 |
+
}
|
884 |
+
});
|
885 |
+
|
886 |
+
/*
|
887 |
+
if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) {
|
888 |
+
bigPlay.remove();
|
889 |
+
loading.remove();
|
890 |
+
}
|
891 |
+
*/
|
892 |
+
|
893 |
+
|
894 |
+
// show/hide big play button
|
895 |
+
media.addEventListener('play',function() {
|
896 |
+
bigPlay.hide();
|
897 |
+
loading.hide();
|
898 |
+
controls.find('.mejs-time-buffering').hide();
|
899 |
+
error.hide();
|
900 |
+
}, false);
|
901 |
+
|
902 |
+
media.addEventListener('playing', function() {
|
903 |
+
bigPlay.hide();
|
904 |
+
loading.hide();
|
905 |
+
controls.find('.mejs-time-buffering').hide();
|
906 |
+
error.hide();
|
907 |
+
}, false);
|
908 |
+
|
909 |
+
media.addEventListener('seeking', function() {
|
910 |
+
loading.show();
|
911 |
+
controls.find('.mejs-time-buffering').show();
|
912 |
+
}, false);
|
913 |
+
|
914 |
+
media.addEventListener('seeked', function() {
|
915 |
+
loading.hide();
|
916 |
+
controls.find('.mejs-time-buffering').hide();
|
917 |
+
}, false);
|
918 |
+
|
919 |
+
media.addEventListener('pause',function() {
|
920 |
+
if (!mejs.MediaFeatures.isiPhone) {
|
921 |
+
bigPlay.show();
|
922 |
+
}
|
923 |
+
}, false);
|
924 |
+
|
925 |
+
media.addEventListener('waiting', function() {
|
926 |
+
loading.show();
|
927 |
+
controls.find('.mejs-time-buffering').show();
|
928 |
+
}, false);
|
929 |
+
|
930 |
+
|
931 |
+
// show/hide loading
|
932 |
+
media.addEventListener('loadeddata',function() {
|
933 |
+
// for some reason Chrome is firing this event
|
934 |
+
//if (mejs.MediaFeatures.isChrome && media.getAttribute && media.getAttribute('preload') === 'none')
|
935 |
+
// return;
|
936 |
+
|
937 |
+
loading.show();
|
938 |
+
controls.find('.mejs-time-buffering').show();
|
939 |
+
}, false);
|
940 |
+
media.addEventListener('canplay',function() {
|
941 |
+
loading.hide();
|
942 |
+
controls.find('.mejs-time-buffering').hide();
|
943 |
+
}, false);
|
944 |
+
|
945 |
+
// error handling
|
946 |
+
media.addEventListener('error',function() {
|
947 |
+
loading.hide();
|
948 |
+
controls.find('.mejs-time-buffering').hide();
|
949 |
+
error.show();
|
950 |
+
error.find('mejs-overlay-error').html("Error loading this resource");
|
951 |
+
}, false);
|
952 |
+
},
|
953 |
+
|
954 |
+
buildkeyboard: function(player, controls, layers, media) {
|
955 |
+
|
956 |
+
var t = this;
|
957 |
+
|
958 |
+
// listen for key presses
|
959 |
+
$(document).keydown(function(e) {
|
960 |
+
|
961 |
+
if (player.hasFocus && player.options.enableKeyboard) {
|
962 |
+
|
963 |
+
// find a matching key
|
964 |
+
for (var i=0, il=player.options.keyActions.length; i<il; i++) {
|
965 |
+
var keyAction = player.options.keyActions[i];
|
966 |
+
|
967 |
+
for (var j=0, jl=keyAction.keys.length; j<jl; j++) {
|
968 |
+
if (e.keyCode == keyAction.keys[j]) {
|
969 |
+
e.preventDefault();
|
970 |
+
keyAction.action(player, media);
|
971 |
+
return false;
|
972 |
+
}
|
973 |
+
}
|
974 |
+
}
|
975 |
+
}
|
976 |
+
|
977 |
+
return true;
|
978 |
+
});
|
979 |
+
|
980 |
+
// check if someone clicked outside a player region, then kill its focus
|
981 |
+
$(document).click(function(event) {
|
982 |
+
if ($(event.target).closest('.mejs-container').length == 0) {
|
983 |
+
player.hasFocus = false;
|
984 |
+
}
|
985 |
+
});
|
986 |
+
|
987 |
+
},
|
988 |
+
|
989 |
+
findTracks: function() {
|
990 |
+
var t = this,
|
991 |
+
tracktags = t.$media.find('track');
|
992 |
+
|
993 |
+
// store for use by plugins
|
994 |
+
t.tracks = [];
|
995 |
+
tracktags.each(function(index, track) {
|
996 |
+
|
997 |
+
track = $(track);
|
998 |
+
|
999 |
+
t.tracks.push({
|
1000 |
+
srclang: track.attr('srclang').toLowerCase(),
|
1001 |
+
src: track.attr('src'),
|
1002 |
+
kind: track.attr('kind'),
|
1003 |
+
label: track.attr('label') || '',
|
1004 |
+
entries: [],
|
1005 |
+
isLoaded: false
|
1006 |
+
});
|
1007 |
+
});
|
1008 |
+
},
|
1009 |
+
changeSkin: function(className) {
|
1010 |
+
this.container[0].className = 'mejs-container ' + className;
|
1011 |
+
this.setPlayerSize(this.width, this.height);
|
1012 |
+
this.setControlsSize();
|
1013 |
+
},
|
1014 |
+
play: function() {
|
1015 |
+
this.media.play();
|
1016 |
+
},
|
1017 |
+
pause: function() {
|
1018 |
+
this.media.pause();
|
1019 |
+
},
|
1020 |
+
load: function() {
|
1021 |
+
this.media.load();
|
1022 |
+
},
|
1023 |
+
setMuted: function(muted) {
|
1024 |
+
this.media.setMuted(muted);
|
1025 |
+
},
|
1026 |
+
setCurrentTime: function(time) {
|
1027 |
+
this.media.setCurrentTime(time);
|
1028 |
+
},
|
1029 |
+
getCurrentTime: function() {
|
1030 |
+
return this.media.currentTime;
|
1031 |
+
},
|
1032 |
+
setVolume: function(volume) {
|
1033 |
+
this.media.setVolume(volume);
|
1034 |
+
},
|
1035 |
+
getVolume: function() {
|
1036 |
+
return this.media.volume;
|
1037 |
+
},
|
1038 |
+
setSrc: function(src) {
|
1039 |
+
this.media.setSrc(src);
|
1040 |
+
},
|
1041 |
+
remove: function() {
|
1042 |
+
var t = this;
|
1043 |
+
|
1044 |
+
if (t.media.pluginType == 'flash') {
|
1045 |
+
t.media.remove();
|
1046 |
+
} else if (t.media.pluginType == 'native') {
|
1047 |
+
t.media.prop('controls', true);
|
1048 |
+
}
|
1049 |
+
|
1050 |
+
// grab video and put it back in place
|
1051 |
+
if (!t.isDynamic) {
|
1052 |
+
t.$node.insertBefore(t.container)
|
1053 |
+
}
|
1054 |
+
|
1055 |
+
t.container.remove();
|
1056 |
+
}
|
1057 |
+
};
|
1058 |
+
|
1059 |
+
// turn into jQuery plugin
|
1060 |
+
if (typeof jQuery != 'undefined') {
|
1061 |
+
jQuery.fn.mediaelementplayer = function (options) {
|
1062 |
+
return this.each(function () {
|
1063 |
+
new mejs.MediaElementPlayer(this, options);
|
1064 |
+
});
|
1065 |
+
};
|
1066 |
+
}
|
1067 |
+
|
1068 |
+
$(document).ready(function() {
|
1069 |
+
// auto enable using JSON attribute
|
1070 |
+
$('.mejs-player').mediaelementplayer();
|
1071 |
+
});
|
1072 |
+
|
1073 |
+
// push out to window
|
1074 |
+
window.MediaElementPlayer = mejs.MediaElementPlayer;
|
1075 |
+
|
1076 |
+
})(mejs.$);
|
1077 |
+
|
1078 |
+
(function($) {
|
1079 |
+
|
1080 |
+
$.extend(mejs.MepDefaults, {
|
1081 |
+
playpauseText: 'Play/Pause'
|
1082 |
+
});
|
1083 |
+
|
1084 |
+
// PLAY/pause BUTTON
|
1085 |
+
$.extend(MediaElementPlayer.prototype, {
|
1086 |
+
buildplaypause: function(player, controls, layers, media) {
|
1087 |
+
var
|
1088 |
+
t = this,
|
1089 |
+
play =
|
1090 |
+
$('<div class="mejs-button mejs-playpause-button mejs-play" >' +
|
1091 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.playpauseText + '"></button>' +
|
1092 |
+
'</div>')
|
1093 |
+
.appendTo(controls)
|
1094 |
+
.click(function(e) {
|
1095 |
+
e.preventDefault();
|
1096 |
+
|
1097 |
+
if (media.paused) {
|
1098 |
+
media.play();
|
1099 |
+
} else {
|
1100 |
+
media.pause();
|
1101 |
+
}
|
1102 |
+
|
1103 |
+
return false;
|
1104 |
+
});
|
1105 |
+
|
1106 |
+
media.addEventListener('play',function() {
|
1107 |
+
play.removeClass('mejs-play').addClass('mejs-pause');
|
1108 |
+
}, false);
|
1109 |
+
media.addEventListener('playing',function() {
|
1110 |
+
play.removeClass('mejs-play').addClass('mejs-pause');
|
1111 |
+
}, false);
|
1112 |
+
|
1113 |
+
|
1114 |
+
media.addEventListener('pause',function() {
|
1115 |
+
play.removeClass('mejs-pause').addClass('mejs-play');
|
1116 |
+
}, false);
|
1117 |
+
media.addEventListener('paused',function() {
|
1118 |
+
play.removeClass('mejs-pause').addClass('mejs-play');
|
1119 |
+
}, false);
|
1120 |
+
}
|
1121 |
+
});
|
1122 |
+
|
1123 |
+
})(mejs.$);
|
1124 |
+
(function($) {
|
1125 |
+
|
1126 |
+
$.extend(mejs.MepDefaults, {
|
1127 |
+
stopText: 'Stop'
|
1128 |
+
});
|
1129 |
+
|
1130 |
+
// STOP BUTTON
|
1131 |
+
$.extend(MediaElementPlayer.prototype, {
|
1132 |
+
buildstop: function(player, controls, layers, media) {
|
1133 |
+
var t = this,
|
1134 |
+
stop =
|
1135 |
+
$('<div class="mejs-button mejs-stop-button mejs-stop">' +
|
1136 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.stopText + '"></button>' +
|
1137 |
+
'</div>')
|
1138 |
+
.appendTo(controls)
|
1139 |
+
.click(function() {
|
1140 |
+
if (!media.paused) {
|
1141 |
+
media.pause();
|
1142 |
+
}
|
1143 |
+
if (media.currentTime > 0) {
|
1144 |
+
media.setCurrentTime(0);
|
1145 |
+
controls.find('.mejs-time-current').width('0px');
|
1146 |
+
controls.find('.mejs-time-handle').css('left', '0px');
|
1147 |
+
controls.find('.mejs-time-float-current').html( mejs.Utility.secondsToTimeCode(0) );
|
1148 |
+
controls.find('.mejs-currenttime').html( mejs.Utility.secondsToTimeCode(0) );
|
1149 |
+
layers.find('.mejs-poster').show();
|
1150 |
+
}
|
1151 |
+
});
|
1152 |
+
}
|
1153 |
+
});
|
1154 |
+
|
1155 |
+
})(mejs.$);
|
1156 |
+
(function($) {
|
1157 |
+
// progress/loaded bar
|
1158 |
+
$.extend(MediaElementPlayer.prototype, {
|
1159 |
+
buildprogress: function(player, controls, layers, media) {
|
1160 |
+
|
1161 |
+
$('<div class="mejs-time-rail">'+
|
1162 |
+
'<span class="mejs-time-total">'+
|
1163 |
+
'<span class="mejs-time-buffering"></span>'+
|
1164 |
+
'<span class="mejs-time-loaded"></span>'+
|
1165 |
+
'<span class="mejs-time-current"></span>'+
|
1166 |
+
'<span class="mejs-time-handle"></span>'+
|
1167 |
+
'<span class="mejs-time-float">' +
|
1168 |
+
'<span class="mejs-time-float-current">00:00</span>' +
|
1169 |
+
'<span class="mejs-time-float-corner"></span>' +
|
1170 |
+
'</span>'+
|
1171 |
+
'</span>'+
|
1172 |
+
'</div>')
|
1173 |
+
.appendTo(controls);
|
1174 |
+
controls.find('.mejs-time-buffering').hide();
|
1175 |
+
|
1176 |
+
var
|
1177 |
+
t = this,
|
1178 |
+
total = controls.find('.mejs-time-total'),
|
1179 |
+
loaded = controls.find('.mejs-time-loaded'),
|
1180 |
+
current = controls.find('.mejs-time-current'),
|
1181 |
+
handle = controls.find('.mejs-time-handle'),
|
1182 |
+
timefloat = controls.find('.mejs-time-float'),
|
1183 |
+
timefloatcurrent = controls.find('.mejs-time-float-current'),
|
1184 |
+
handleMouseMove = function (e) {
|
1185 |
+
// mouse position relative to the object
|
1186 |
+
var x = e.pageX,
|
1187 |
+
offset = total.offset(),
|
1188 |
+
width = total.outerWidth(),
|
1189 |
+
percentage = 0,
|
1190 |
+
newTime = 0,
|
1191 |
+
pos = x - offset.left;
|
1192 |
+
|
1193 |
+
|
1194 |
+
if (x > offset.left && x <= width + offset.left && media.duration) {
|
1195 |
+
percentage = ((x - offset.left) / width);
|
1196 |
+
newTime = (percentage <= 0.02) ? 0 : percentage * media.duration;
|
1197 |
+
|
1198 |
+
// seek to where the mouse is
|
1199 |
+
if (mouseIsDown) {
|
1200 |
+
media.setCurrentTime(newTime);
|
1201 |
+
}
|
1202 |
+
|
1203 |
+
// position floating time box
|
1204 |
+
if (!mejs.MediaFeatures.hasTouch) {
|
1205 |
+
timefloat.css('left', pos);
|
1206 |
+
timefloatcurrent.html( mejs.Utility.secondsToTimeCode(newTime) );
|
1207 |
+
timefloat.show();
|
1208 |
+
}
|
1209 |
+
}
|
1210 |
+
},
|
1211 |
+
mouseIsDown = false,
|
1212 |
+
mouseIsOver = false;
|
1213 |
+
|
1214 |
+
// handle clicks
|
1215 |
+
//controls.find('.mejs-time-rail').delegate('span', 'click', handleMouseMove);
|
1216 |
+
total
|
1217 |
+
.bind('mousedown', function (e) {
|
1218 |
+
// only handle left clicks
|
1219 |
+
if (e.which === 1) {
|
1220 |
+
mouseIsDown = true;
|
1221 |
+
handleMouseMove(e);
|
1222 |
+
$(document)
|
1223 |
+
.bind('mousemove.dur', function(e) {
|
1224 |
+
handleMouseMove(e);
|
1225 |
+
})
|
1226 |
+
.bind('mouseup.dur', function (e) {
|
1227 |
+
mouseIsDown = false;
|
1228 |
+
timefloat.hide();
|
1229 |
+
$(document).unbind('.dur');
|
1230 |
+
});
|
1231 |
+
return false;
|
1232 |
+
}
|
1233 |
+
})
|
1234 |
+
.bind('mouseenter', function(e) {
|
1235 |
+
mouseIsOver = true;
|
1236 |
+
$(document).bind('mousemove.dur', function(e) {
|
1237 |
+
handleMouseMove(e);
|
1238 |
+
});
|
1239 |
+
if (!mejs.MediaFeatures.hasTouch) {
|
1240 |
+
timefloat.show();
|
1241 |
+
}
|
1242 |
+
})
|
1243 |
+
.bind('mouseleave',function(e) {
|
1244 |
+
mouseIsOver = false;
|
1245 |
+
if (!mouseIsDown) {
|
1246 |
+
$(document).unbind('.dur');
|
1247 |
+
timefloat.hide();
|
1248 |
+
}
|
1249 |
+
});
|
1250 |
+
|
1251 |
+
// loading
|
1252 |
+
media.addEventListener('progress', function (e) {
|
1253 |
+
player.setProgressRail(e);
|
1254 |
+
player.setCurrentRail(e);
|
1255 |
+
}, false);
|
1256 |
+
|
1257 |
+
// current time
|
1258 |
+
media.addEventListener('timeupdate', function(e) {
|
1259 |
+
player.setProgressRail(e);
|
1260 |
+
player.setCurrentRail(e);
|
1261 |
+
}, false);
|
1262 |
+
|
1263 |
+
|
1264 |
+
// store for later use
|
1265 |
+
t.loaded = loaded;
|
1266 |
+
t.total = total;
|
1267 |
+
t.current = current;
|
1268 |
+
t.handle = handle;
|
1269 |
+
},
|
1270 |
+
setProgressRail: function(e) {
|
1271 |
+
|
1272 |
+
var
|
1273 |
+
t = this,
|
1274 |
+
target = (e != undefined) ? e.target : t.media,
|
1275 |
+
percent = null;
|
1276 |
+
|
1277 |
+
// newest HTML5 spec has buffered array (FF4, Webkit)
|
1278 |
+
if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) {
|
1279 |
+
// TODO: account for a real array with multiple values (only Firefox 4 has this so far)
|
1280 |
+
percent = target.buffered.end(0) / target.duration;
|
1281 |
+
}
|
1282 |
+
// Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
|
1283 |
+
// to be anything other than 0. If the byte count is available we use this instead.
|
1284 |
+
// Browsers that support the else if do not seem to have the bufferedBytes value and
|
1285 |
+
// should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8.
|
1286 |
+
else if (target && target.bytesTotal != undefined && target.bytesTotal > 0 && target.bufferedBytes != undefined) {
|
1287 |
+
percent = target.bufferedBytes / target.bytesTotal;
|
1288 |
+
}
|
1289 |
+
// Firefox 3 with an Ogg file seems to go this way
|
1290 |
+
else if (e && e.lengthComputable && e.total != 0) {
|
1291 |
+
percent = e.loaded/e.total;
|
1292 |
+
}
|
1293 |
+
|
1294 |
+
// finally update the progress bar
|
1295 |
+
if (percent !== null) {
|
1296 |
+
percent = Math.min(1, Math.max(0, percent));
|
1297 |
+
// update loaded bar
|
1298 |
+
if (t.loaded && t.total) {
|
1299 |
+
t.loaded.width(t.total.width() * percent);
|
1300 |
+
}
|
1301 |
+
}
|
1302 |
+
},
|
1303 |
+
setCurrentRail: function() {
|
1304 |
+
|
1305 |
+
var t = this;
|
1306 |
+
|
1307 |
+
if (t.media.currentTime != undefined && t.media.duration) {
|
1308 |
+
|
1309 |
+
// update bar and handle
|
1310 |
+
if (t.total && t.handle) {
|
1311 |
+
var
|
1312 |
+
newWidth = t.total.width() * t.media.currentTime / t.media.duration,
|
1313 |
+
handlePos = newWidth - (t.handle.outerWidth(true) / 2);
|
1314 |
+
|
1315 |
+
t.current.width(newWidth);
|
1316 |
+
t.handle.css('left', handlePos);
|
1317 |
+
}
|
1318 |
+
}
|
1319 |
+
|
1320 |
+
}
|
1321 |
+
});
|
1322 |
+
})(mejs.$);
|
1323 |
+
(function($) {
|
1324 |
+
|
1325 |
+
// options
|
1326 |
+
$.extend(mejs.MepDefaults, {
|
1327 |
+
duration: -1,
|
1328 |
+
timeAndDurationSeparator: ' <span> | </span> '
|
1329 |
+
});
|
1330 |
+
|
1331 |
+
|
1332 |
+
// current and duration 00:00 / 00:00
|
1333 |
+
$.extend(MediaElementPlayer.prototype, {
|
1334 |
+
buildcurrent: function(player, controls, layers, media) {
|
1335 |
+
var t = this;
|
1336 |
+
|
1337 |
+
$('<div class="mejs-time">'+
|
1338 |
+
'<span class="mejs-currenttime">' + (player.options.alwaysShowHours ? '00:' : '')
|
1339 |
+
+ (player.options.showTimecodeFrameCount? '00:00:00':'00:00')+ '</span>'+
|
1340 |
+
'</div>')
|
1341 |
+
.appendTo(controls);
|
1342 |
+
|
1343 |
+
t.currenttime = t.controls.find('.mejs-currenttime');
|
1344 |
+
|
1345 |
+
media.addEventListener('timeupdate',function() {
|
1346 |
+
player.updateCurrent();
|
1347 |
+
}, false);
|
1348 |
+
},
|
1349 |
+
|
1350 |
+
|
1351 |
+
buildduration: function(player, controls, layers, media) {
|
1352 |
+
var t = this;
|
1353 |
+
|
1354 |
+
if (controls.children().last().find('.mejs-currenttime').length > 0) {
|
1355 |
+
$(t.options.timeAndDurationSeparator +
|
1356 |
+
'<span class="mejs-duration">' +
|
1357 |
+
(t.options.duration > 0 ?
|
1358 |
+
mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) :
|
1359 |
+
((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00'))
|
1360 |
+
) +
|
1361 |
+
'</span>')
|
1362 |
+
.appendTo(controls.find('.mejs-time'));
|
1363 |
+
} else {
|
1364 |
+
|
1365 |
+
// add class to current time
|
1366 |
+
controls.find('.mejs-currenttime').parent().addClass('mejs-currenttime-container');
|
1367 |
+
|
1368 |
+
$('<div class="mejs-time mejs-duration-container">'+
|
1369 |
+
'<span class="mejs-duration">' +
|
1370 |
+
(t.options.duration > 0 ?
|
1371 |
+
mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) :
|
1372 |
+
((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00'))
|
1373 |
+
) +
|
1374 |
+
'</span>' +
|
1375 |
+
'</div>')
|
1376 |
+
.appendTo(controls);
|
1377 |
+
}
|
1378 |
+
|
1379 |
+
t.durationD = t.controls.find('.mejs-duration');
|
1380 |
+
|
1381 |
+
media.addEventListener('timeupdate',function() {
|
1382 |
+
player.updateDuration();
|
1383 |
+
}, false);
|
1384 |
+
},
|
1385 |
+
|
1386 |
+
updateCurrent: function() {
|
1387 |
+
var t = this;
|
1388 |
+
|
1389 |
+
if (t.currenttime) {
|
1390 |
+
t.currenttime.html(mejs.Utility.secondsToTimeCode(t.media.currentTime, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25));
|
1391 |
+
}
|
1392 |
+
},
|
1393 |
+
|
1394 |
+
updateDuration: function() {
|
1395 |
+
var t = this;
|
1396 |
+
|
1397 |
+
if (t.media.duration && t.durationD) {
|
1398 |
+
t.durationD.html(mejs.Utility.secondsToTimeCode(t.media.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25));
|
1399 |
+
}
|
1400 |
+
}
|
1401 |
+
});
|
1402 |
+
|
1403 |
+
})(mejs.$);
|
1404 |
+
(function($) {
|
1405 |
+
|
1406 |
+
$.extend(mejs.MepDefaults, {
|
1407 |
+
muteText: 'Mute Toggle',
|
1408 |
+
hideVolumeOnTouchDevices: true,
|
1409 |
+
|
1410 |
+
audioVolume: 'horizontal',
|
1411 |
+
videoVolume: 'vertical'
|
1412 |
+
});
|
1413 |
+
|
1414 |
+
$.extend(MediaElementPlayer.prototype, {
|
1415 |
+
buildvolume: function(player, controls, layers, media) {
|
1416 |
+
|
1417 |
+
// Android and iOS don't support volume controls
|
1418 |
+
if (mejs.MediaFeatures.hasTouch && this.options.hideVolumeOnTouchDevices)
|
1419 |
+
return;
|
1420 |
+
|
1421 |
+
var t = this,
|
1422 |
+
mode = (t.isVideo) ? t.options.videoVolume : t.options.audioVolume,
|
1423 |
+
mute = (mode == 'horizontal') ?
|
1424 |
+
|
1425 |
+
// horizontal version
|
1426 |
+
$('<div class="mejs-button mejs-volume-button mejs-mute">'+
|
1427 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
|
1428 |
+
'</div>' +
|
1429 |
+
'<div class="mejs-horizontal-volume-slider">'+ // outer background
|
1430 |
+
'<div class="mejs-horizontal-volume-total"></div>'+ // line background
|
1431 |
+
'<div class="mejs-horizontal-volume-current"></div>'+ // current volume
|
1432 |
+
'<div class="mejs-horizontal-volume-handle"></div>'+ // handle
|
1433 |
+
'</div>'
|
1434 |
+
)
|
1435 |
+
.appendTo(controls) :
|
1436 |
+
|
1437 |
+
// vertical version
|
1438 |
+
$('<div class="mejs-button mejs-volume-button mejs-mute">'+
|
1439 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
|
1440 |
+
'<div class="mejs-volume-slider">'+ // outer background
|
1441 |
+
'<div class="mejs-volume-total"></div>'+ // line background
|
1442 |
+
'<div class="mejs-volume-current"></div>'+ // current volume
|
1443 |
+
'<div class="mejs-volume-handle"></div>'+ // handle
|
1444 |
+
'</div>'+
|
1445 |
+
'</div>')
|
1446 |
+
.appendTo(controls),
|
1447 |
+
volumeSlider = t.container.find('.mejs-volume-slider, .mejs-horizontal-volume-slider'),
|
1448 |
+
volumeTotal = t.container.find('.mejs-volume-total, .mejs-horizontal-volume-total'),
|
1449 |
+
volumeCurrent = t.container.find('.mejs-volume-current, .mejs-horizontal-volume-current'),
|
1450 |
+
volumeHandle = t.container.find('.mejs-volume-handle, .mejs-horizontal-volume-handle'),
|
1451 |
+
|
1452 |
+
positionVolumeHandle = function(volume, secondTry) {
|
1453 |
+
|
1454 |
+
if (!volumeSlider.is(':visible') && typeof secondTry != 'undefined') {
|
1455 |
+
volumeSlider.show();
|
1456 |
+
positionVolumeHandle(volume, true);
|
1457 |
+
volumeSlider.hide()
|
1458 |
+
return;
|
1459 |
+
}
|
1460 |
+
|
1461 |
+
// correct to 0-1
|
1462 |
+
volume = Math.max(0,volume);
|
1463 |
+
volume = Math.min(volume,1);
|
1464 |
+
|
1465 |
+
// ajust mute button style
|
1466 |
+
if (volume == 0) {
|
1467 |
+
mute.removeClass('mejs-mute').addClass('mejs-unmute');
|
1468 |
+
} else {
|
1469 |
+
mute.removeClass('mejs-unmute').addClass('mejs-mute');
|
1470 |
+
}
|
1471 |
+
|
1472 |
+
// position slider
|
1473 |
+
if (mode == 'vertical') {
|
1474 |
+
var
|
1475 |
+
|
1476 |
+
// height of the full size volume slider background
|
1477 |
+
totalHeight = volumeTotal.height(),
|
1478 |
+
|
1479 |
+
// top/left of full size volume slider background
|
1480 |
+
totalPosition = volumeTotal.position(),
|
1481 |
+
|
1482 |
+
// the new top position based on the current volume
|
1483 |
+
// 70% volume on 100px height == top:30px
|
1484 |
+
newTop = totalHeight - (totalHeight * volume);
|
1485 |
+
|
1486 |
+
// handle
|
1487 |
+
volumeHandle.css('top', totalPosition.top + newTop - (volumeHandle.height() / 2));
|
1488 |
+
|
1489 |
+
// show the current visibility
|
1490 |
+
volumeCurrent.height(totalHeight - newTop );
|
1491 |
+
volumeCurrent.css('top', totalPosition.top + newTop);
|
1492 |
+
} else {
|
1493 |
+
var
|
1494 |
+
|
1495 |
+
// height of the full size volume slider background
|
1496 |
+
totalWidth = volumeTotal.width(),
|
1497 |
+
|
1498 |
+
// top/left of full size volume slider background
|
1499 |
+
totalPosition = volumeTotal.position(),
|
1500 |
+
|
1501 |
+
// the new left position based on the current volume
|
1502 |
+
newLeft = totalWidth * volume;
|
1503 |
+
|
1504 |
+
// handle
|
1505 |
+
volumeHandle.css('left', totalPosition.left + newLeft - (volumeHandle.width() / 2));
|
1506 |
+
|
1507 |
+
// rezize the current part of the volume bar
|
1508 |
+
volumeCurrent.width( newLeft );
|
1509 |
+
}
|
1510 |
+
},
|
1511 |
+
handleVolumeMove = function(e) {
|
1512 |
+
|
1513 |
+
var volume = null,
|
1514 |
+
totalOffset = volumeTotal.offset();
|
1515 |
+
|
1516 |
+
// calculate the new volume based on the moust position
|
1517 |
+
if (mode == 'vertical') {
|
1518 |
+
|
1519 |
+
var
|
1520 |
+
railHeight = volumeTotal.height(),
|
1521 |
+
totalTop = parseInt(volumeTotal.css('top').replace(/px/,''),10),
|
1522 |
+
newY = e.pageY - totalOffset.top;
|
1523 |
+
|
1524 |
+
volume = (railHeight - newY) / railHeight;
|
1525 |
+
|
1526 |
+
// the controls just hide themselves (usually when mouse moves too far up)
|
1527 |
+
if (totalOffset.top == 0 || totalOffset.left == 0)
|
1528 |
+
return;
|
1529 |
+
|
1530 |
+
} else {
|
1531 |
+
var
|
1532 |
+
railWidth = volumeTotal.width(),
|
1533 |
+
newX = e.pageX - totalOffset.left;
|
1534 |
+
|
1535 |
+
volume = newX / railWidth;
|
1536 |
+
}
|
1537 |
+
|
1538 |
+
// ensure the volume isn't outside 0-1
|
1539 |
+
volume = Math.max(0,volume);
|
1540 |
+
volume = Math.min(volume,1);
|
1541 |
+
|
1542 |
+
// position the slider and handle
|
1543 |
+
positionVolumeHandle(volume);
|
1544 |
+
|
1545 |
+
// set the media object (this will trigger the volumechanged event)
|
1546 |
+
if (volume == 0) {
|
1547 |
+
media.setMuted(true);
|
1548 |
+
} else {
|
1549 |
+
media.setMuted(false);
|
1550 |
+
}
|
1551 |
+
media.setVolume(volume);
|
1552 |
+
},
|
1553 |
+
mouseIsDown = false,
|
1554 |
+
mouseIsOver = false;
|
1555 |
+
|
1556 |
+
// SLIDER
|
1557 |
+
|
1558 |
+
mute
|
1559 |
+
.hover(function() {
|
1560 |
+
volumeSlider.show();
|
1561 |
+
mouseIsOver = true;
|
1562 |
+
}, function() {
|
1563 |
+
mouseIsOver = false;
|
1564 |
+
|
1565 |
+
if (!mouseIsDown && mode == 'vertical') {
|
1566 |
+
volumeSlider.hide();
|
1567 |
+
}
|
1568 |
+
});
|
1569 |
+
|
1570 |
+
volumeSlider
|
1571 |
+
.bind('mouseover', function() {
|
1572 |
+
mouseIsOver = true;
|
1573 |
+
})
|
1574 |
+
.bind('mousedown', function (e) {
|
1575 |
+
handleVolumeMove(e);
|
1576 |
+
$(document)
|
1577 |
+
.bind('mousemove.vol', function(e) {
|
1578 |
+
handleVolumeMove(e);
|
1579 |
+
})
|
1580 |
+
.bind('mouseup.vol', function () {
|
1581 |
+
mouseIsDown = false;
|
1582 |
+
$(document).unbind('.vol');
|
1583 |
+
|
1584 |
+
if (!mouseIsOver && mode == 'vertical') {
|
1585 |
+
volumeSlider.hide();
|
1586 |
+
}
|
1587 |
+
});
|
1588 |
+
mouseIsDown = true;
|
1589 |
+
|
1590 |
+
return false;
|
1591 |
+
});
|
1592 |
+
|
1593 |
+
|
1594 |
+
// MUTE button
|
1595 |
+
mute.find('button').click(function() {
|
1596 |
+
media.setMuted( !media.muted );
|
1597 |
+
});
|
1598 |
+
|
1599 |
+
// listen for volume change events from other sources
|
1600 |
+
media.addEventListener('volumechange', function(e) {
|
1601 |
+
if (!mouseIsDown) {
|
1602 |
+
if (media.muted) {
|
1603 |
+
positionVolumeHandle(0);
|
1604 |
+
mute.removeClass('mejs-mute').addClass('mejs-unmute');
|
1605 |
+
} else {
|
1606 |
+
positionVolumeHandle(media.volume);
|
1607 |
+
mute.removeClass('mejs-unmute').addClass('mejs-mute');
|
1608 |
+
}
|
1609 |
+
}
|
1610 |
+
}, false);
|
1611 |
+
|
1612 |
+
if (t.container.is(':visible')) {
|
1613 |
+
// set initial volume
|
1614 |
+
positionVolumeHandle(player.options.startVolume);
|
1615 |
+
|
1616 |
+
// shim gets the startvolume as a parameter, but we have to set it on the native <video> and <audio> elements
|
1617 |
+
if (media.pluginType === 'native') {
|
1618 |
+
media.setVolume(player.options.startVolume);
|
1619 |
+
}
|
1620 |
+
}
|
1621 |
+
}
|
1622 |
+
});
|
1623 |
+
|
1624 |
+
})(mejs.$);
|
1625 |
+
|
1626 |
+
(function($) {
|
1627 |
+
|
1628 |
+
$.extend(mejs.MepDefaults, {
|
1629 |
+
usePluginFullScreen: true,
|
1630 |
+
newWindowCallback: function() { return '';},
|
1631 |
+
fullscreenText: 'Fullscreen'
|
1632 |
+
});
|
1633 |
+
|
1634 |
+
$.extend(MediaElementPlayer.prototype, {
|
1635 |
+
|
1636 |
+
isFullScreen: false,
|
1637 |
+
|
1638 |
+
isNativeFullScreen: false,
|
1639 |
+
|
1640 |
+
docStyleOverflow: null,
|
1641 |
+
|
1642 |
+
isInIframe: false,
|
1643 |
+
|
1644 |
+
buildfullscreen: function(player, controls, layers, media) {
|
1645 |
+
|
1646 |
+
if (!player.isVideo)
|
1647 |
+
return;
|
1648 |
+
|
1649 |
+
player.isInIframe = (window.location != window.parent.location);
|
1650 |
+
|
1651 |
+
// native events
|
1652 |
+
if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
1653 |
+
|
1654 |
+
// chrome doesn't alays fire this in an iframe
|
1655 |
+
var target = null;
|
1656 |
+
|
1657 |
+
if (mejs.MediaFeatures.hasMozNativeFullScreen) {
|
1658 |
+
target = $(document);
|
1659 |
+
} else {
|
1660 |
+
target = player.container;
|
1661 |
+
}
|
1662 |
+
|
1663 |
+
target.bind(mejs.MediaFeatures.fullScreenEventName, function(e) {
|
1664 |
+
//player.container.bind('webkitfullscreenchange', function(e) {
|
1665 |
+
|
1666 |
+
|
1667 |
+
if (mejs.MediaFeatures.isFullScreen()) {
|
1668 |
+
player.isNativeFullScreen = true;
|
1669 |
+
// reset the controls once we are fully in full screen
|
1670 |
+
player.setControlsSize();
|
1671 |
+
} else {
|
1672 |
+
player.isNativeFullScreen = false;
|
1673 |
+
// when a user presses ESC
|
1674 |
+
// make sure to put the player back into place
|
1675 |
+
player.exitFullScreen();
|
1676 |
+
}
|
1677 |
+
});
|
1678 |
+
}
|
1679 |
+
|
1680 |
+
var t = this,
|
1681 |
+
normalHeight = 0,
|
1682 |
+
normalWidth = 0,
|
1683 |
+
container = player.container,
|
1684 |
+
fullscreenBtn =
|
1685 |
+
$('<div class="mejs-button mejs-fullscreen-button">' +
|
1686 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.fullscreenText + '"></button>' +
|
1687 |
+
'</div>')
|
1688 |
+
.appendTo(controls);
|
1689 |
+
|
1690 |
+
if (t.media.pluginType === 'native' || (!t.options.usePluginFullScreen && !mejs.MediaFeatures.isFirefox)) {
|
1691 |
+
|
1692 |
+
fullscreenBtn.click(function() {
|
1693 |
+
var isFullScreen = (mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || player.isFullScreen;
|
1694 |
+
|
1695 |
+
if (isFullScreen) {
|
1696 |
+
player.exitFullScreen();
|
1697 |
+
} else {
|
1698 |
+
player.enterFullScreen();
|
1699 |
+
}
|
1700 |
+
});
|
1701 |
+
|
1702 |
+
} else {
|
1703 |
+
|
1704 |
+
var hideTimeout = null,
|
1705 |
+
supportsPointerEvents = (function() {
|
1706 |
+
// TAKEN FROM MODERNIZR
|
1707 |
+
var element = document.createElement('x'),
|
1708 |
+
documentElement = document.documentElement,
|
1709 |
+
getComputedStyle = window.getComputedStyle,
|
1710 |
+
supports;
|
1711 |
+
if(!('pointerEvents' in element.style)){
|
1712 |
+
return false;
|
1713 |
+
}
|
1714 |
+
element.style.pointerEvents = 'auto';
|
1715 |
+
element.style.pointerEvents = 'x';
|
1716 |
+
documentElement.appendChild(element);
|
1717 |
+
supports = getComputedStyle &&
|
1718 |
+
getComputedStyle(element, '').pointerEvents === 'auto';
|
1719 |
+
documentElement.removeChild(element);
|
1720 |
+
return !!supports;
|
1721 |
+
})();
|
1722 |
+
|
1723 |
+
console.log('supportsPointerEvents', supportsPointerEvents);
|
1724 |
+
|
1725 |
+
if (supportsPointerEvents && !mejs.MediaFeatures.isOpera) { // opera doesn't allow this :(
|
1726 |
+
|
1727 |
+
// allows clicking through the fullscreen button and controls down directly to Flash
|
1728 |
+
|
1729 |
+
/*
|
1730 |
+
When a user puts his mouse over the fullscreen button, the controls are disabled
|
1731 |
+
So we put a div over the video and another one on iether side of the fullscreen button
|
1732 |
+
that caputre mouse movement
|
1733 |
+
and restore the controls once the mouse moves outside of the fullscreen button
|
1734 |
+
*/
|
1735 |
+
|
1736 |
+
var fullscreenIsDisabled = false,
|
1737 |
+
restoreControls = function() {
|
1738 |
+
if (fullscreenIsDisabled) {
|
1739 |
+
// hide the hovers
|
1740 |
+
videoHoverDiv.hide();
|
1741 |
+
controlsLeftHoverDiv.hide();
|
1742 |
+
controlsRightHoverDiv.hide();
|
1743 |
+
|
1744 |
+
// restore the control bar
|
1745 |
+
fullscreenBtn.css('pointer-events', '');
|
1746 |
+
t.controls.css('pointer-events', '');
|
1747 |
+
|
1748 |
+
// store for later
|
1749 |
+
fullscreenIsDisabled = false;
|
1750 |
+
}
|
1751 |
+
},
|
1752 |
+
videoHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
|
1753 |
+
controlsLeftHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
|
1754 |
+
controlsRightHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
|
1755 |
+
positionHoverDivs = function() {
|
1756 |
+
var style = {position: 'absolute', top: 0, left: 0}; //, backgroundColor: '#f00'};
|
1757 |
+
videoHoverDiv.css(style);
|
1758 |
+
controlsLeftHoverDiv.css(style);
|
1759 |
+
controlsRightHoverDiv.css(style);
|
1760 |
+
|
1761 |
+
// over video, but not controls
|
1762 |
+
videoHoverDiv
|
1763 |
+
.width( t.container.width() )
|
1764 |
+
.height( t.container.height() - t.controls.height() );
|
1765 |
+
|
1766 |
+
// over controls, but not the fullscreen button
|
1767 |
+
var fullScreenBtnOffset = fullscreenBtn.offset().left - t.container.offset().left;
|
1768 |
+
fullScreenBtnWidth = fullscreenBtn.outerWidth(true);
|
1769 |
+
|
1770 |
+
controlsLeftHoverDiv
|
1771 |
+
.width( fullScreenBtnOffset )
|
1772 |
+
.height( t.controls.height() )
|
1773 |
+
.css({top: t.container.height() - t.controls.height()});
|
1774 |
+
|
1775 |
+
// after the fullscreen button
|
1776 |
+
controlsRightHoverDiv
|
1777 |
+
.width( t.container.width() - fullScreenBtnOffset - fullScreenBtnWidth )
|
1778 |
+
.height( t.controls.height() )
|
1779 |
+
.css({top: t.container.height() - t.controls.height(),
|
1780 |
+
left: fullScreenBtnOffset + fullScreenBtnWidth});
|
1781 |
+
};
|
1782 |
+
|
1783 |
+
$(document).resize(function() {
|
1784 |
+
positionHoverDivs();
|
1785 |
+
});
|
1786 |
+
|
1787 |
+
// on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash
|
1788 |
+
fullscreenBtn
|
1789 |
+
.mouseover(function() {
|
1790 |
+
|
1791 |
+
if (!t.isFullScreen) {
|
1792 |
+
|
1793 |
+
var buttonPos = fullscreenBtn.offset(),
|
1794 |
+
containerPos = player.container.offset();
|
1795 |
+
|
1796 |
+
// move the button in Flash into place
|
1797 |
+
media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, false);
|
1798 |
+
|
1799 |
+
// allows click through
|
1800 |
+
fullscreenBtn.css('pointer-events', 'none');
|
1801 |
+
t.controls.css('pointer-events', 'none');
|
1802 |
+
|
1803 |
+
// show the divs that will restore things
|
1804 |
+
videoHoverDiv.show();
|
1805 |
+
controlsRightHoverDiv.show();
|
1806 |
+
controlsLeftHoverDiv.show();
|
1807 |
+
positionHoverDivs();
|
1808 |
+
|
1809 |
+
fullscreenIsDisabled = true;
|
1810 |
+
}
|
1811 |
+
|
1812 |
+
});
|
1813 |
+
|
1814 |
+
// restore controls anytime the user enters or leaves fullscreen
|
1815 |
+
media.addEventListener('fullscreenchange', function(e) {
|
1816 |
+
restoreControls();
|
1817 |
+
});
|
1818 |
+
|
1819 |
+
|
1820 |
+
// the mouseout event doesn't work on the fullscren button, because we already killed the pointer-events
|
1821 |
+
// so we use the document.mousemove event to restore controls when the mouse moves outside the fullscreen button
|
1822 |
+
/*
|
1823 |
+
$(document).mousemove(function(e) {
|
1824 |
+
|
1825 |
+
// if the mouse is anywhere but the fullsceen button, then restore it all
|
1826 |
+
if (fullscreenIsDisabled) {
|
1827 |
+
|
1828 |
+
var fullscreenBtnPos = fullscreenBtn.offset();
|
1829 |
+
|
1830 |
+
|
1831 |
+
if (e.pageY < fullscreenBtnPos.top || e.pageY > fullscreenBtnPos.top + fullscreenBtn.outerHeight(true) ||
|
1832 |
+
e.pageX < fullscreenBtnPos.left || e.pageX > fullscreenBtnPos.left + fullscreenBtn.outerWidth(true)
|
1833 |
+
) {
|
1834 |
+
|
1835 |
+
fullscreenBtn.css('pointer-events', '');
|
1836 |
+
t.controls.css('pointer-events', '');
|
1837 |
+
|
1838 |
+
fullscreenIsDisabled = false;
|
1839 |
+
}
|
1840 |
+
}
|
1841 |
+
});
|
1842 |
+
*/
|
1843 |
+
|
1844 |
+
|
1845 |
+
} else {
|
1846 |
+
|
1847 |
+
// the hover state will show the fullscreen button in Flash to hover up and click
|
1848 |
+
|
1849 |
+
fullscreenBtn
|
1850 |
+
.mouseover(function() {
|
1851 |
+
|
1852 |
+
if (hideTimeout !== null) {
|
1853 |
+
clearTimeout(hideTimeout);
|
1854 |
+
delete hideTimeout;
|
1855 |
+
}
|
1856 |
+
|
1857 |
+
var buttonPos = fullscreenBtn.offset(),
|
1858 |
+
containerPos = player.container.offset();
|
1859 |
+
|
1860 |
+
media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, true);
|
1861 |
+
|
1862 |
+
})
|
1863 |
+
.mouseout(function() {
|
1864 |
+
|
1865 |
+
if (hideTimeout !== null) {
|
1866 |
+
clearTimeout(hideTimeout);
|
1867 |
+
delete hideTimeout;
|
1868 |
+
}
|
1869 |
+
|
1870 |
+
hideTimeout = setTimeout(function() {
|
1871 |
+
media.hideFullscreenButton();
|
1872 |
+
}, 1500);
|
1873 |
+
|
1874 |
+
|
1875 |
+
});
|
1876 |
+
}
|
1877 |
+
}
|
1878 |
+
|
1879 |
+
player.fullscreenBtn = fullscreenBtn;
|
1880 |
+
|
1881 |
+
$(document).bind('keydown',function (e) {
|
1882 |
+
if (((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen) && e.keyCode == 27) {
|
1883 |
+
player.exitFullScreen();
|
1884 |
+
}
|
1885 |
+
});
|
1886 |
+
|
1887 |
+
},
|
1888 |
+
enterFullScreen: function() {
|
1889 |
+
|
1890 |
+
var t = this;
|
1891 |
+
|
1892 |
+
// firefox+flash can't adjust plugin sizes without resetting :(
|
1893 |
+
if (t.media.pluginType !== 'native' && (mejs.MediaFeatures.isFirefox || t.options.usePluginFullScreen)) {
|
1894 |
+
//t.media.setFullscreen(true);
|
1895 |
+
//player.isFullScreen = true;
|
1896 |
+
return;
|
1897 |
+
}
|
1898 |
+
|
1899 |
+
// store overflow
|
1900 |
+
docStyleOverflow = document.documentElement.style.overflow;
|
1901 |
+
// set it to not show scroll bars so 100% will work
|
1902 |
+
document.documentElement.style.overflow = 'hidden';
|
1903 |
+
|
1904 |
+
// store sizing
|
1905 |
+
normalHeight = t.container.height();
|
1906 |
+
normalWidth = t.container.width();
|
1907 |
+
|
1908 |
+
// attempt to do true fullscreen (Safari 5.1 and Firefox Nightly only for now)
|
1909 |
+
if (t.media.pluginType === 'native') {
|
1910 |
+
if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
1911 |
+
|
1912 |
+
mejs.MediaFeatures.requestFullScreen(t.container[0]);
|
1913 |
+
//return;
|
1914 |
+
|
1915 |
+
if (t.isInIframe) {
|
1916 |
+
// sometimes exiting from fullscreen doesn't work
|
1917 |
+
// notably in Chrome <iframe>. Fixed in version 17
|
1918 |
+
setTimeout(function checkFullscreen() {
|
1919 |
+
|
1920 |
+
if (t.isNativeFullScreen) {
|
1921 |
+
|
1922 |
+
// check if the video is suddenly not really fullscreen
|
1923 |
+
if ($(window).width() !== screen.width) {
|
1924 |
+
// manually exit
|
1925 |
+
t.exitFullScreen();
|
1926 |
+
} else {
|
1927 |
+
// test again
|
1928 |
+
setTimeout(checkFullscreen, 500);
|
1929 |
+
}
|
1930 |
+
}
|
1931 |
+
|
1932 |
+
|
1933 |
+
}, 500);
|
1934 |
+
}
|
1935 |
+
|
1936 |
+
} else if (mejs.MediaFeatures.hasSemiNativeFullScreen) {
|
1937 |
+
t.media.webkitEnterFullscreen();
|
1938 |
+
return;
|
1939 |
+
}
|
1940 |
+
}
|
1941 |
+
|
1942 |
+
// check for iframe launch
|
1943 |
+
if (t.isInIframe) {
|
1944 |
+
var url = t.options.newWindowCallback(this);
|
1945 |
+
|
1946 |
+
|
1947 |
+
if (url !== '') {
|
1948 |
+
|
1949 |
+
// launch immediately
|
1950 |
+
if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
1951 |
+
t.pause();
|
1952 |
+
window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');
|
1953 |
+
return;
|
1954 |
+
} else {
|
1955 |
+
setTimeout(function() {
|
1956 |
+
if (!t.isNativeFullScreen) {
|
1957 |
+
t.pause();
|
1958 |
+
window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');
|
1959 |
+
}
|
1960 |
+
}, 250);
|
1961 |
+
}
|
1962 |
+
}
|
1963 |
+
|
1964 |
+
}
|
1965 |
+
|
1966 |
+
// full window code
|
1967 |
+
|
1968 |
+
|
1969 |
+
|
1970 |
+
// make full size
|
1971 |
+
t.container
|
1972 |
+
.addClass('mejs-container-fullscreen')
|
1973 |
+
.width('100%')
|
1974 |
+
.height('100%');
|
1975 |
+
//.css({position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, overflow: 'hidden', width: '100%', height: '100%', 'z-index': 1000});
|
1976 |
+
|
1977 |
+
// Only needed for safari 5.1 native full screen, can cause display issues elsewhere
|
1978 |
+
// Actually, it seems to be needed for IE8, too
|
1979 |
+
//if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
1980 |
+
setTimeout(function() {
|
1981 |
+
t.container.css({width: '100%', height: '100%'});
|
1982 |
+
t.setControlsSize();
|
1983 |
+
}, 500);
|
1984 |
+
//}
|
1985 |
+
|
1986 |
+
if (t.pluginType === 'native') {
|
1987 |
+
t.$media
|
1988 |
+
.width('100%')
|
1989 |
+
.height('100%');
|
1990 |
+
} else {
|
1991 |
+
t.container.find('object, embed, iframe')
|
1992 |
+
.width('100%')
|
1993 |
+
.height('100%');
|
1994 |
+
|
1995 |
+
//if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
|
1996 |
+
t.media.setVideoSize($(window).width(),$(window).height());
|
1997 |
+
//}
|
1998 |
+
}
|
1999 |
+
|
2000 |
+
t.layers.children('div')
|
2001 |
+
.width('100%')
|
2002 |
+
.height('100%');
|
2003 |
+
|
2004 |
+
if (t.fullscreenBtn) {
|
2005 |
+
t.fullscreenBtn
|
2006 |
+
.removeClass('mejs-fullscreen')
|
2007 |
+
.addClass('mejs-unfullscreen');
|
2008 |
+
}
|
2009 |
+
|
2010 |
+
t.setControlsSize();
|
2011 |
+
t.isFullScreen = true;
|
2012 |
+
},
|
2013 |
+
|
2014 |
+
exitFullScreen: function() {
|
2015 |
+
|
2016 |
+
var t = this;
|
2017 |
+
|
2018 |
+
// firefox can't adjust plugins
|
2019 |
+
if (t.media.pluginType !== 'native' && mejs.MediaFeatures.isFirefox) {
|
2020 |
+
t.media.setFullscreen(false);
|
2021 |
+
//player.isFullScreen = false;
|
2022 |
+
return;
|
2023 |
+
}
|
2024 |
+
|
2025 |
+
// come outo of native fullscreen
|
2026 |
+
if (mejs.MediaFeatures.hasTrueNativeFullScreen && (mejs.MediaFeatures.isFullScreen() || t.isFullScreen)) {
|
2027 |
+
mejs.MediaFeatures.cancelFullScreen();
|
2028 |
+
}
|
2029 |
+
|
2030 |
+
// restore scroll bars to document
|
2031 |
+
document.documentElement.style.overflow = docStyleOverflow;
|
2032 |
+
|
2033 |
+
t.container
|
2034 |
+
.removeClass('mejs-container-fullscreen')
|
2035 |
+
.width(normalWidth)
|
2036 |
+
.height(normalHeight);
|
2037 |
+
//.css({position: '', left: '', top: '', right: '', bottom: '', overflow: 'inherit', width: normalWidth + 'px', height: normalHeight + 'px', 'z-index': 1});
|
2038 |
+
|
2039 |
+
if (t.pluginType === 'native') {
|
2040 |
+
t.$media
|
2041 |
+
.width(normalWidth)
|
2042 |
+
.height(normalHeight);
|
2043 |
+
} else {
|
2044 |
+
t.container.find('object embed')
|
2045 |
+
.width(normalWidth)
|
2046 |
+
.height(normalHeight);
|
2047 |
+
|
2048 |
+
t.media.setVideoSize(normalWidth, normalHeight);
|
2049 |
+
}
|
2050 |
+
|
2051 |
+
t.layers.children('div')
|
2052 |
+
.width(normalWidth)
|
2053 |
+
.height(normalHeight);
|
2054 |
+
|
2055 |
+
t.fullscreenBtn
|
2056 |
+
.removeClass('mejs-unfullscreen')
|
2057 |
+
.addClass('mejs-fullscreen');
|
2058 |
+
|
2059 |
+
t.setControlsSize();
|
2060 |
+
t.isFullScreen = false;
|
2061 |
+
}
|
2062 |
+
});
|
2063 |
+
|
2064 |
+
})(mejs.$);
|
2065 |
+
|
2066 |
+
(function($) {
|
2067 |
+
|
2068 |
+
// add extra default options
|
2069 |
+
$.extend(mejs.MepDefaults, {
|
2070 |
+
// this will automatically turn on a <track>
|
2071 |
+
startLanguage: '',
|
2072 |
+
|
2073 |
+
tracksText: 'Captions/Subtitles'
|
2074 |
+
});
|
2075 |
+
|
2076 |
+
$.extend(MediaElementPlayer.prototype, {
|
2077 |
+
|
2078 |
+
hasChapters: false,
|
2079 |
+
|
2080 |
+
buildtracks: function(player, controls, layers, media) {
|
2081 |
+
if (!player.isVideo)
|
2082 |
+
return;
|
2083 |
+
|
2084 |
+
if (player.tracks.length == 0)
|
2085 |
+
return;
|
2086 |
+
|
2087 |
+
var t= this, i, options = '';
|
2088 |
+
|
2089 |
+
player.chapters =
|
2090 |
+
$('<div class="mejs-chapters mejs-layer"></div>')
|
2091 |
+
.prependTo(layers).hide();
|
2092 |
+
player.captions =
|
2093 |
+
$('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position"><span class="mejs-captions-text"></span></div></div>')
|
2094 |
+
.prependTo(layers).hide();
|
2095 |
+
player.captionsText = player.captions.find('.mejs-captions-text');
|
2096 |
+
player.captionsButton =
|
2097 |
+
$('<div class="mejs-button mejs-captions-button">'+
|
2098 |
+
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.tracksText + '"></button>'+
|
2099 |
+
'<div class="mejs-captions-selector">'+
|
2100 |
+
'<ul>'+
|
2101 |
+
'<li>'+
|
2102 |
+
'<input type="radio" name="' + player.id + '_captions" id="' + player.id + '_captions_none" value="none" checked="checked" />' +
|
2103 |
+
'<label for="' + player.id + '_captions_none">None</label>'+
|
2104 |
+
'</li>' +
|
2105 |
+
'</ul>'+
|
2106 |
+
'</div>'+
|
2107 |
+
'</div>')
|
2108 |
+
.appendTo(controls)
|
2109 |
+
|
2110 |
+
// hover
|
2111 |
+
.hover(function() {
|
2112 |
+
$(this).find('.mejs-captions-selector').css('visibility','visible');
|
2113 |
+
}, function() {
|
2114 |
+
$(this).find('.mejs-captions-selector').css('visibility','hidden');
|
2115 |
+
})
|
2116 |
+
|
2117 |
+
// handle clicks to the language radio buttons
|
2118 |
+
.delegate('input[type=radio]','click',function() {
|
2119 |
+
lang = this.value;
|
2120 |
+
|
2121 |
+
if (lang == 'none') {
|
2122 |
+
player.selectedTrack = null;
|
2123 |
+
} else {
|
2124 |
+
for (i=0; i<player.tracks.length; i++) {
|
2125 |
+
if (player.tracks[i].srclang == lang) {
|
2126 |
+
player.selectedTrack = player.tracks[i];
|
2127 |
+
player.captions.attr('lang', player.selectedTrack.srclang);
|
2128 |
+
player.displayCaptions();
|
2129 |
+
break;
|
2130 |
+
}
|
2131 |
+
}
|
2132 |
+
}
|
2133 |
+
});
|
2134 |
+
//.bind('mouseenter', function() {
|
2135 |
+
// player.captionsButton.find('.mejs-captions-selector').css('visibility','visible')
|
2136 |
+
//});
|
2137 |
+
|
2138 |
+
if (!player.options.alwaysShowControls) {
|
2139 |
+
// move with controls
|
2140 |
+
player.container
|
2141 |
+
.bind('mouseenter', function () {
|
2142 |
+
// push captions above controls
|
2143 |
+
player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
|
2144 |
+
|
2145 |
+
})
|
2146 |
+
.bind('mouseleave', function () {
|
2147 |
+
if (!media.paused) {
|
2148 |
+
// move back to normal place
|
2149 |
+
player.container.find('.mejs-captions-position').removeClass('mejs-captions-position-hover');
|
2150 |
+
}
|
2151 |
+
});
|
2152 |
+
} else {
|
2153 |
+
player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
|
2154 |
+
}
|
2155 |
+
|
2156 |
+
player.trackToLoad = -1;
|
2157 |
+
player.selectedTrack = null;
|
2158 |
+
player.isLoadingTrack = false;
|
2159 |
+
|
2160 |
+
|
2161 |
+
|
2162 |
+
// add to list
|
2163 |
+
for (i=0; i<player.tracks.length; i++) {
|
2164 |
+
if (player.tracks[i].kind == 'subtitles') {
|
2165 |
+
player.addTrackButton(player.tracks[i].srclang, player.tracks[i].label);
|
2166 |
+
}
|
2167 |
+
}
|
2168 |
+
|
2169 |
+
player.loadNextTrack();
|
2170 |
+
|
2171 |
+
|
2172 |
+
media.addEventListener('timeupdate',function(e) {
|
2173 |
+
player.displayCaptions();
|
2174 |
+
}, false);
|
2175 |
+
|
2176 |
+
media.addEventListener('loadedmetadata', function(e) {
|
2177 |
+
player.displayChapters();
|
2178 |
+
}, false);
|
2179 |
+
|
2180 |
+
player.container.hover(
|
2181 |
+
function () {
|
2182 |
+
// chapters
|
2183 |
+
if (player.hasChapters) {
|
2184 |
+
player.chapters.css('visibility','visible');
|
2185 |
+
player.chapters.fadeIn(200).height(player.chapters.find('.mejs-chapter').outerHeight());
|
2186 |
+
}
|
2187 |
+
},
|
2188 |
+
function () {
|
2189 |
+
if (player.hasChapters && !media.paused) {
|
2190 |
+
player.chapters.fadeOut(200, function() {
|
2191 |
+
$(this).css('visibility','hidden');
|
2192 |
+
$(this).css('display','block');
|
2193 |
+
});
|
2194 |
+
}
|
2195 |
+
});
|
2196 |
+
|
2197 |
+
// check for autoplay
|
2198 |
+
if (player.node.getAttribute('autoplay') !== null) {
|
2199 |
+
player.chapters.css('visibility','hidden');
|
2200 |
+
}
|
2201 |
+
},
|
2202 |
+
|
2203 |
+
loadNextTrack: function() {
|
2204 |
+
var t = this;
|
2205 |
+
|
2206 |
+
t.trackToLoad++;
|
2207 |
+
if (t.trackToLoad < t.tracks.length) {
|
2208 |
+
t.isLoadingTrack = true;
|
2209 |
+
t.loadTrack(t.trackToLoad);
|
2210 |
+
} else {
|
2211 |
+
// add done?
|
2212 |
+
t.isLoadingTrack = false;
|
2213 |
+
}
|
2214 |
+
},
|
2215 |
+
|
2216 |
+
loadTrack: function(index){
|
2217 |
+
var
|
2218 |
+
t = this,
|
2219 |
+
track = t.tracks[index],
|
2220 |
+
after = function() {
|
2221 |
+
|
2222 |
+
track.isLoaded = true;
|
2223 |
+
|
2224 |
+
// create button
|
2225 |
+
//t.addTrackButton(track.srclang);
|
2226 |
+
t.enableTrackButton(track.srclang, track.label);
|
2227 |
+
|
2228 |
+
t.loadNextTrack();
|
2229 |
+
|
2230 |
+
};
|
2231 |
+
|
2232 |
+
if (track.isTranslation) {
|
2233 |
+
|
2234 |
+
// translate the first track
|
2235 |
+
mejs.TrackFormatParser.translateTrackText(t.tracks[0].entries, t.tracks[0].srclang, track.srclang, t.options.googleApiKey, function(newOne) {
|
2236 |
+
|
2237 |
+
// store the new translation
|
2238 |
+
track.entries = newOne;
|
2239 |
+
|
2240 |
+
after();
|
2241 |
+
});
|
2242 |
+
|
2243 |
+
} else {
|
2244 |
+
$.ajax({
|
2245 |
+
url: track.src,
|
2246 |
+
success: function(d) {
|
2247 |
+
|
2248 |
+
// parse the loaded file
|
2249 |
+
track.entries = mejs.TrackFormatParser.parse(d);
|
2250 |
+
after();
|
2251 |
+
|
2252 |
+
if (track.kind == 'chapters' && t.media.duration > 0) {
|
2253 |
+
t.drawChapters(track);
|
2254 |
+
}
|
2255 |
+
},
|
2256 |
+
error: function() {
|
2257 |
+
t.loadNextTrack();
|
2258 |
+
}
|
2259 |
+
});
|
2260 |
+
}
|
2261 |
+
},
|
2262 |
+
|
2263 |
+
enableTrackButton: function(lang, label) {
|
2264 |
+
var t = this;
|
2265 |
+
|
2266 |
+
if (label === '') {
|
2267 |
+
label = mejs.language.codes[lang] || lang;
|
2268 |
+
}
|
2269 |
+
|
2270 |
+
t.captionsButton
|
2271 |
+
.find('input[value=' + lang + ']')
|
2272 |
+
.prop('disabled',false)
|
2273 |
+
.siblings('label')
|
2274 |
+
.html( label );
|
2275 |
+
|
2276 |
+
// auto select
|
2277 |
+
if (t.options.startLanguage == lang) {
|
2278 |
+
$('#' + t.id + '_captions_' + lang).click();
|
2279 |
+
}
|
2280 |
+
|
2281 |
+
t.adjustLanguageBox();
|
2282 |
+
},
|
2283 |
+
|
2284 |
+
addTrackButton: function(lang, label) {
|
2285 |
+
var t = this;
|
2286 |
+
if (label === '') {
|
2287 |
+
label = mejs.language.codes[lang] || lang;
|
2288 |
+
}
|
2289 |
+
|
2290 |
+
t.captionsButton.find('ul').append(
|
2291 |
+
$('<li>'+
|
2292 |
+
'<input type="radio" name="' + t.id + '_captions" id="' + t.id + '_captions_' + lang + '" value="' + lang + '" disabled="disabled" />' +
|
2293 |
+
'<label for="' + t.id + '_captions_' + lang + '">' + label + ' (loading)' + '</label>'+
|
2294 |
+
'</li>')
|
2295 |
+
);
|
2296 |
+
|
2297 |
+
t.adjustLanguageBox();
|
2298 |
+
|
2299 |
+
// remove this from the dropdownlist (if it exists)
|
2300 |
+
t.container.find('.mejs-captions-translations option[value=' + lang + ']').remove();
|
2301 |
+
},
|
2302 |
+
|
2303 |
+
adjustLanguageBox:function() {
|
2304 |
+
var t = this;
|
2305 |
+
// adjust the size of the outer box
|
2306 |
+
t.captionsButton.find('.mejs-captions-selector').height(
|
2307 |
+
t.captionsButton.find('.mejs-captions-selector ul').outerHeight(true) +
|
2308 |
+
t.captionsButton.find('.mejs-captions-translations').outerHeight(true)
|
2309 |
+
);
|
2310 |
+
},
|
2311 |
+
|
2312 |
+
displayCaptions: function() {
|
2313 |
+
|
2314 |
+
if (typeof this.tracks == 'undefined')
|
2315 |
+
return;
|
2316 |
+
|
2317 |
+
var
|
2318 |
+
t = this,
|
2319 |
+
i,
|
2320 |
+
track = t.selectedTrack;
|
2321 |
+
|
2322 |
+
if (track != null && track.isLoaded) {
|
2323 |
+
for (i=0; i<track.entries.times.length; i++) {
|
2324 |
+
if (t.media.currentTime >= track.entries.times[i].start && t.media.currentTime <= track.entries.times[i].stop){
|
2325 |
+
t.captionsText.html(track.entries.text[i]);
|
2326 |
+
t.captions.show().height(0);
|
2327 |
+
return; // exit out if one is visible;
|
2328 |
+
}
|
2329 |
+
}
|
2330 |
+
t.captions.hide();
|
2331 |
+
} else {
|
2332 |
+
t.captions.hide();
|
2333 |
+
}
|
2334 |
+
},
|
2335 |
+
|
2336 |
+
displayChapters: function() {
|
2337 |
+
var
|
2338 |
+
t = this,
|
2339 |
+
i;
|
2340 |
+
|
2341 |
+
for (i=0; i<t.tracks.length; i++) {
|
2342 |
+
if (t.tracks[i].kind == 'chapters' && t.tracks[i].isLoaded) {
|
2343 |
+
t.drawChapters(t.tracks[i]);
|
2344 |
+
t.hasChapters = true;
|
2345 |
+
break;
|
2346 |
+
}
|
2347 |
+
}
|
2348 |
+
},
|
2349 |
+
|
2350 |
+
drawChapters: function(chapters) {
|
2351 |
+
var
|
2352 |
+
t = this,
|
2353 |
+
i,
|
2354 |
+
dur,
|
2355 |
+
//width,
|
2356 |
+
//left,
|
2357 |
+
percent = 0,
|
2358 |
+
usedPercent = 0;
|
2359 |
+
|
2360 |
+
t.chapters.empty();
|
2361 |
+
|
2362 |
+
for (i=0; i<chapters.entries.times.length; i++) {
|
2363 |
+
dur = chapters.entries.times[i].stop - chapters.entries.times[i].start;
|
2364 |
+
percent = Math.floor(dur / t.media.duration * 100);
|
2365 |
+
if (percent + usedPercent > 100 || // too large
|
2366 |
+
i == chapters.entries.times.length-1 && percent + usedPercent < 100) // not going to fill it in
|
2367 |
+
{
|
2368 |
+
percent = 100 - usedPercent;
|
2369 |
+
}
|
2370 |
+
//width = Math.floor(t.width * dur / t.media.duration);
|
2371 |
+
//left = Math.floor(t.width * chapters.entries.times[i].start / t.media.duration);
|
2372 |
+
//if (left + width > t.width) {
|
2373 |
+
// width = t.width - left;
|
2374 |
+
//}
|
2375 |
+
|
2376 |
+
t.chapters.append( $(
|
2377 |
+
'<div class="mejs-chapter" rel="' + chapters.entries.times[i].start + '" style="left: ' + usedPercent.toString() + '%;width: ' + percent.toString() + '%;">' +
|
2378 |
+
'<div class="mejs-chapter-block' + ((i==chapters.entries.times.length-1) ? ' mejs-chapter-block-last' : '') + '">' +
|
2379 |
+
'<span class="ch-title">' + chapters.entries.text[i] + '</span>' +
|
2380 |
+
'<span class="ch-time">' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].start) + '–' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' +
|
2381 |
+
'</div>' +
|
2382 |
+
'</div>'));
|
2383 |
+
usedPercent += percent;
|
2384 |
+
}
|
2385 |
+
|
2386 |
+
t.chapters.find('div.mejs-chapter').click(function() {
|
2387 |
+
t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) );
|
2388 |
+
if (t.media.paused) {
|
2389 |
+
t.media.play();
|
2390 |
+
}
|
2391 |
+
});
|
2392 |
+
|
2393 |
+
t.chapters.show();
|
2394 |
+
}
|
2395 |
+
});
|
2396 |
+
|
2397 |
+
|
2398 |
+
|
2399 |
+
mejs.language = {
|
2400 |
+
codes: {
|
2401 |
+
af:'Afrikaans',
|
2402 |
+
sq:'Albanian',
|
2403 |
+
ar:'Arabic',
|
2404 |
+
be:'Belarusian',
|
2405 |
+
bg:'Bulgarian',
|
2406 |
+
ca:'Catalan',
|
2407 |
+
zh:'Chinese',
|
2408 |
+
'zh-cn':'Chinese Simplified',
|
2409 |
+
'zh-tw':'Chinese Traditional',
|
2410 |
+
hr:'Croatian',
|
2411 |
+
cs:'Czech',
|
2412 |
+
da:'Danish',
|
2413 |
+
nl:'Dutch',
|
2414 |
+
en:'English',
|
2415 |
+
et:'Estonian',
|
2416 |
+
tl:'Filipino',
|
2417 |
+
fi:'Finnish',
|
2418 |
+
fr:'French',
|
2419 |
+
gl:'Galician',
|
2420 |
+
de:'German',
|
2421 |
+
el:'Greek',
|
2422 |
+
ht:'Haitian Creole',
|
2423 |
+
iw:'Hebrew',
|
2424 |
+
hi:'Hindi',
|
2425 |
+
hu:'Hungarian',
|
2426 |
+
is:'Icelandic',
|
2427 |
+
id:'Indonesian',
|
2428 |
+
ga:'Irish',
|
2429 |
+
it:'Italian',
|
2430 |
+
ja:'Japanese',
|
2431 |
+
ko:'Korean',
|
2432 |
+
lv:'Latvian',
|
2433 |
+
lt:'Lithuanian',
|
2434 |
+
mk:'Macedonian',
|
2435 |
+
ms:'Malay',
|
2436 |
+
mt:'Maltese',
|
2437 |
+
no:'Norwegian',
|
2438 |
+
fa:'Persian',
|
2439 |
+
pl:'Polish',
|
2440 |
+
pt:'Portuguese',
|
2441 |
+
//'pt-pt':'Portuguese (Portugal)',
|
2442 |
+
ro:'Romanian',
|
2443 |
+
ru:'Russian',
|
2444 |
+
sr:'Serbian',
|
2445 |
+
sk:'Slovak',
|
2446 |
+
sl:'Slovenian',
|
2447 |
+
es:'Spanish',
|
2448 |
+
sw:'Swahili',
|
2449 |
+
sv:'Swedish',
|
2450 |
+
tl:'Tagalog',
|
2451 |
+
th:'Thai',
|
2452 |
+
tr:'Turkish',
|
2453 |
+
uk:'Ukrainian',
|
2454 |
+
vi:'Vietnamese',
|
2455 |
+
cy:'Welsh',
|
2456 |
+
yi:'Yiddish'
|
2457 |
+
}
|
2458 |
+
};
|
2459 |
+
|
2460 |
+
/*
|
2461 |
+
Parses WebVVT format which should be formatted as
|
2462 |
+
================================
|
2463 |
+
WEBVTT
|
2464 |
+
|
2465 |
+
1
|
2466 |
+
00:00:01,1 --> 00:00:05,000
|
2467 |
+
A line of text
|
2468 |
+
|
2469 |
+
2
|
2470 |
+
00:01:15,1 --> 00:02:05,000
|
2471 |
+
A second line of text
|
2472 |
+
|
2473 |
+
===============================
|
2474 |
+
|
2475 |
+
Adapted from: http://www.delphiki.com/html5/playr
|
2476 |
+
*/
|
2477 |
+
mejs.TrackFormatParser = {
|
2478 |
+
// match start "chapter-" (or anythingelse)
|
2479 |
+
pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/,
|
2480 |
+
pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/,
|
2481 |
+
|
2482 |
+
split2: function (text, regex) {
|
2483 |
+
// normal version for compliant browsers
|
2484 |
+
// see below for IE fix
|
2485 |
+
return text.split(regex);
|
2486 |
+
},
|
2487 |
+
parse: function(trackText) {
|
2488 |
+
var
|
2489 |
+
i = 0,
|
2490 |
+
lines = this.split2(trackText, /\r?\n/),
|
2491 |
+
entries = {text:[], times:[]},
|
2492 |
+
timecode,
|
2493 |
+
text;
|
2494 |
+
|
2495 |
+
for(; i<lines.length; i++) {
|
2496 |
+
// check for the line number
|
2497 |
+
if (this.pattern_identifier.exec(lines[i])){
|
2498 |
+
// skip to the next line where the start --> end time code should be
|
2499 |
+
i++;
|
2500 |
+
timecode = this.pattern_timecode.exec(lines[i]);
|
2501 |
+
|
2502 |
+
if (timecode && i<lines.length){
|
2503 |
+
i++;
|
2504 |
+
// grab all the (possibly multi-line) text that follows
|
2505 |
+
text = lines[i];
|
2506 |
+
i++;
|
2507 |
+
while(lines[i] !== '' && i<lines.length){
|
2508 |
+
text = text + '\n' + lines[i];
|
2509 |
+
i++;
|
2510 |
+
}
|
2511 |
+
|
2512 |
+
// Text is in a different array so I can use .join
|
2513 |
+
entries.text.push(text);
|
2514 |
+
entries.times.push(
|
2515 |
+
{
|
2516 |
+
start: mejs.Utility.timeCodeToSeconds(timecode[1]),
|
2517 |
+
stop: mejs.Utility.timeCodeToSeconds(timecode[3]),
|
2518 |
+
settings: timecode[5]
|
2519 |
+
});
|
2520 |
+
}
|
2521 |
+
}
|
2522 |
+
}
|
2523 |
+
|
2524 |
+
return entries;
|
2525 |
+
}
|
2526 |
+
};
|
2527 |
+
|
2528 |
+
// test for browsers with bad String.split method.
|
2529 |
+
if ('x\n\ny'.split(/\n/gi).length != 3) {
|
2530 |
+
// add super slow IE8 and below version
|
2531 |
+
mejs.TrackFormatParser.split2 = function(text, regex) {
|
2532 |
+
var
|
2533 |
+
parts = [],
|
2534 |
+
chunk = '',
|
2535 |
+
i;
|
2536 |
+
|
2537 |
+
for (i=0; i<text.length; i++) {
|
2538 |
+
chunk += text.substring(i,i+1);
|
2539 |
+
if (regex.test(chunk)) {
|
2540 |
+
parts.push(chunk.replace(regex, ''));
|
2541 |
+
chunk = '';
|
2542 |
+
}
|
2543 |
+
}
|
2544 |
+
parts.push(chunk);
|
2545 |
+
return parts;
|
2546 |
+
}
|
2547 |
+
}
|
2548 |
+
|
2549 |
+
})(mejs.$);
|
2550 |
+
|
2551 |
+
/*
|
2552 |
+
* ContextMenu Plugin
|
2553 |
+
*
|
2554 |
+
*
|
2555 |
+
*/
|
2556 |
+
|
2557 |
+
(function($) {
|
2558 |
+
|
2559 |
+
$.extend(mejs.MepDefaults,
|
2560 |
+
{ 'contextMenuItems': [
|
2561 |
+
// demo of a fullscreen option
|
2562 |
+
{
|
2563 |
+
render: function(player) {
|
2564 |
+
|
2565 |
+
// check for fullscreen plugin
|
2566 |
+
if (typeof player.enterFullScreen == 'undefined')
|
2567 |
+
return null;
|
2568 |
+
|
2569 |
+
if (player.isFullScreen) {
|
2570 |
+
return "Turn off Fullscreen";
|
2571 |
+
} else {
|
2572 |
+
return "Go Fullscreen";
|
2573 |
+
}
|
2574 |
+
},
|
2575 |
+
click: function(player) {
|
2576 |
+
if (player.isFullScreen) {
|
2577 |
+
player.exitFullScreen();
|
2578 |
+
} else {
|
2579 |
+
player.enterFullScreen();
|
2580 |
+
}
|
2581 |
+
}
|
2582 |
+
}
|
2583 |
+
,
|
2584 |
+
// demo of a mute/unmute button
|
2585 |
+
{
|
2586 |
+
render: function(player) {
|
2587 |
+
if (player.media.muted) {
|
2588 |
+
return "Unmute";
|
2589 |
+
} else {
|
2590 |
+
return "Mute";
|
2591 |
+
}
|
2592 |
+
},
|
2593 |
+
click: function(player) {
|
2594 |
+
if (player.media.muted) {
|
2595 |
+
player.setMuted(false);
|
2596 |
+
} else {
|
2597 |
+
player.setMuted(true);
|
2598 |
+
}
|
2599 |
+
}
|
2600 |
+
},
|
2601 |
+
// separator
|
2602 |
+
{
|
2603 |
+
isSeparator: true
|
2604 |
+
}
|
2605 |
+
,
|
2606 |
+
// demo of simple download video
|
2607 |
+
{
|
2608 |
+
render: function(player) {
|
2609 |
+
return "Download Video";
|
2610 |
+
},
|
2611 |
+
click: function(player) {
|
2612 |
+
window.location.href = player.media.currentSrc;
|
2613 |
+
}
|
2614 |
+
}
|
2615 |
+
]}
|
2616 |
+
);
|
2617 |
+
|
2618 |
+
|
2619 |
+
$.extend(MediaElementPlayer.prototype, {
|
2620 |
+
buildcontextmenu: function(player, controls, layers, media) {
|
2621 |
+
|
2622 |
+
// create context menu
|
2623 |
+
player.contextMenu = $('<div class="mejs-contextmenu"></div>')
|
2624 |
+
.appendTo($('body'))
|
2625 |
+
.hide();
|
2626 |
+
|
2627 |
+
// create events for showing context menu
|
2628 |
+
player.container.bind('contextmenu', function(e) {
|
2629 |
+
if (player.isContextMenuEnabled) {
|
2630 |
+
e.preventDefault();
|
2631 |
+
player.renderContextMenu(e.clientX-1, e.clientY-1);
|
2632 |
+
return false;
|
2633 |
+
}
|
2634 |
+
});
|
2635 |
+
player.container.bind('click', function() {
|
2636 |
+
player.contextMenu.hide();
|
2637 |
+
});
|
2638 |
+
player.contextMenu.bind('mouseleave', function() {
|
2639 |
+
|
2640 |
+
//console.log('context hover out');
|
2641 |
+
player.startContextMenuTimer();
|
2642 |
+
|
2643 |
+
});
|
2644 |
+
},
|
2645 |
+
|
2646 |
+
isContextMenuEnabled: true,
|
2647 |
+
enableContextMenu: function() {
|
2648 |
+
this.isContextMenuEnabled = true;
|
2649 |
+
},
|
2650 |
+
disableContextMenu: function() {
|
2651 |
+
this.isContextMenuEnabled = false;
|
2652 |
+
},
|
2653 |
+
|
2654 |
+
contextMenuTimeout: null,
|
2655 |
+
startContextMenuTimer: function() {
|
2656 |
+
//console.log('startContextMenuTimer');
|
2657 |
+
|
2658 |
+
var t = this;
|
2659 |
+
|
2660 |
+
t.killContextMenuTimer();
|
2661 |
+
|
2662 |
+
t.contextMenuTimer = setTimeout(function() {
|
2663 |
+
t.hideContextMenu();
|
2664 |
+
t.killContextMenuTimer();
|
2665 |
+
}, 750);
|
2666 |
+
},
|
2667 |
+
killContextMenuTimer: function() {
|
2668 |
+
var timer = this.contextMenuTimer;
|
2669 |
+
|
2670 |
+
//console.log('killContextMenuTimer', timer);
|
2671 |
+
|
2672 |
+
if (timer != null) {
|
2673 |
+
clearTimeout(timer);
|
2674 |
+
delete timer;
|
2675 |
+
timer = null;
|
2676 |
+
}
|
2677 |
+
},
|
2678 |
+
|
2679 |
+
hideContextMenu: function() {
|
2680 |
+
this.contextMenu.hide();
|
2681 |
+
},
|
2682 |
+
|
2683 |
+
renderContextMenu: function(x,y) {
|
2684 |
+
|
2685 |
+
// alway re-render the items so that things like "turn fullscreen on" and "turn fullscreen off" are always written correctly
|
2686 |
+
var t = this,
|
2687 |
+
html = '',
|
2688 |
+
items = t.options.contextMenuItems;
|
2689 |
+
|
2690 |
+
for (var i=0, il=items.length; i<il; i++) {
|
2691 |
+
|
2692 |
+
if (items[i].isSeparator) {
|
2693 |
+
html += '<div class="mejs-contextmenu-separator"></div>';
|
2694 |
+
} else {
|
2695 |
+
|
2696 |
+
var rendered = items[i].render(t);
|
2697 |
+
|
2698 |
+
// render can return null if the item doesn't need to be used at the moment
|
2699 |
+
if (rendered != null) {
|
2700 |
+
html += '<div class="mejs-contextmenu-item" data-itemindex="' + i + '" id="element-' + (Math.random()*1000000) + '">' + rendered + '</div>';
|
2701 |
+
}
|
2702 |
+
}
|
2703 |
+
}
|
2704 |
+
|
2705 |
+
// position and show the context menu
|
2706 |
+
t.contextMenu
|
2707 |
+
.empty()
|
2708 |
+
.append($(html))
|
2709 |
+
.css({top:y, left:x})
|
2710 |
+
.show();
|
2711 |
+
|
2712 |
+
// bind events
|
2713 |
+
t.contextMenu.find('.mejs-contextmenu-item').each(function() {
|
2714 |
+
|
2715 |
+
// which one is this?
|
2716 |
+
var $dom = $(this),
|
2717 |
+
itemIndex = parseInt( $dom.data('itemindex'), 10 ),
|
2718 |
+
item = t.options.contextMenuItems[itemIndex];
|
2719 |
+
|
2720 |
+
// bind extra functionality?
|
2721 |
+
if (typeof item.show != 'undefined')
|
2722 |
+
item.show( $dom , t);
|
2723 |
+
|
2724 |
+
// bind click action
|
2725 |
+
$dom.click(function() {
|
2726 |
+
// perform click action
|
2727 |
+
if (typeof item.click != 'undefined')
|
2728 |
+
item.click(t);
|
2729 |
+
|
2730 |
+
// close
|
2731 |
+
t.contextMenu.hide();
|
2732 |
+
});
|
2733 |
+
});
|
2734 |
+
|
2735 |
+
// stop the controls from hiding
|
2736 |
+
setTimeout(function() {
|
2737 |
+
t.killControlsTimer('rev3');
|
2738 |
+
}, 100);
|
2739 |
+
|
2740 |
+
}
|
2741 |
+
});
|
2742 |
+
|
2743 |
+
})(mejs.$);
|
includes/media-element/mediaelementplayer.min.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
.mejs-container{position:relative;background:#000;font-family:Helvetica,Arial;text-align:left;vertical-align:top;}.me-plugin{position:absolute;}.mejs-embed,.mejs-embed body{width:100%;height:100%;margin:0;padding:0;background:#000;overflow:hidden;}.mejs-container-fullscreen{position:fixed;left:0;top:0;right:0;bottom:0;overflow:hidden;z-index:1000;}.mejs-container-fullscreen .mejs-mediaelement,.mejs-container-fullscreen video{width:100%;height:100%;}.mejs-background{position:absolute;top:0;left:0;}.mejs-mediaelement{position:absolute;top:0;left:0;width:100%;height:100%;}.mejs-poster{position:absolute;top:0;left:0;}.mejs-poster img{border:0;padding:0;border:0;display:block;}.mejs-overlay{position:absolute;top:0;left:0;}.mejs-overlay-play{cursor:pointer;}.mejs-overlay-button{position:absolute;top:50%;left:50%;width:100px;height:100px;margin:-50px 0 0 -50px;background:url(bigplay.png) no-repeat;}.mejs-overlay:hover .mejs-overlay-button{background-position:0 -100px;}.mejs-overlay-loading{position:absolute;top:50%;left:50%;width:80px;height:80px;margin:-40px 0 0 -40px;background:#333;background:url(background.png);background:rgba(0,0,0,0.9);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.9)),to(rgba(0,0,0,0.9)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-moz-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-o-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-ms-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:linear-gradient(rgba(50,50,50,0.9),rgba(0,0,0,0.9));}.mejs-overlay-loading span{display:block;width:80px;height:80px;background:transparent url(loading.gif) 50% 50% no-repeat;}.mejs-container .mejs-controls{position:absolute;background:none;list-style-type:none;margin:0;padding:0;bottom:0;left:0;background:url(background.png);background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));height:30px;width:100%;}.mejs-container .mejs-controls div{list-style-type:none;background-image:none;display:block;float:left;margin:0;padding:0;width:26px;height:26px;font-size:11px;line-height:11px;background:0;font-family:Helvetica,Arial;border:0;}.mejs-controls .mejs-button button{cursor:pointer;display:block;font-size:0;line-height:0;text-decoration:none;margin:7px 5px;padding:0;position:absolute;height:16px;width:16px;border:0;background:transparent url(controls.png) no-repeat;}.mejs-controls .mejs-button button:focus{outline:solid 1px yellow;}.mejs-container .mejs-controls .mejs-time{color:#fff;display:block;height:17px;width:auto;padding:8px 3px 0 3px;overflow:hidden;text-align:center;padding:auto 4px;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;}.mejs-container .mejs-controls .mejs-time span{font-size:11px;color:#fff;line-height:12px;display:block;float:left;margin:1px 2px 0 0;width:auto;}.mejs-controls .mejs-play button{background-position:0 0;}.mejs-controls .mejs-pause button{background-position:0 -16px;}.mejs-controls .mejs-stop button{background-position:-112px 0;}.mejs-controls div.mejs-time-rail{width:200px;padding-top:5px;}.mejs-controls .mejs-time-rail span{display:block;position:absolute;width:180px;height:10px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;cursor:pointer;}.mejs-controls .mejs-time-rail .mejs-time-total{margin:5px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-time-rail .mejs-time-buffering{width:100%;background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:15px 15px;-moz-background-size:15px 15px;-o-background-size:15px 15px;background-size:15px 15px;-webkit-animation:buffering-stripes 2s linear infinite;-moz-animation:buffering-stripes 2s linear infinite;-ms-animation:buffering-stripes 2s linear infinite;-o-animation:buffering-stripes 2s linear infinite;animation:buffering-stripes 2s linear infinite;}@-webkit-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-moz-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-ms-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-o-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}.mejs-controls .mejs-time-rail .mejs-time-loaded{background:#3caac8;background:rgba(60,170,200,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(44,124,145,0.8)),to(rgba(78,183,212,0.8)));background:-webkit-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-moz-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-o-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-ms-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:linear-gradient(rgba(44,124,145,0.8),rgba(78,183,212,0.8));width:0;}.mejs-controls .mejs-time-rail .mejs-time-current{width:0;background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));}.mejs-controls .mejs-time-rail .mejs-time-handle{display:none;position:absolute;margin:0;width:10px;background:#fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;cursor:pointer;border:solid 2px #333;top:-2px;text-align:center;}.mejs-controls .mejs-time-rail .mejs-time-float{position:absolute;display:none;background:#eee;width:36px;height:17px;border:solid 1px #333;top:-26px;margin-left:-18px;text-align:center;color:#111;}.mejs-controls .mejs-time-rail .mejs-time-float-current{margin:2px;width:30px;display:block;text-align:center;left:0;}.mejs-controls .mejs-time-rail .mejs-time-float-corner{position:absolute;display:block;width:0;height:0;line-height:0;border:solid 5px #eee;border-color:#eee transparent transparent transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:15px;left:13px;}.mejs-controls .mejs-fullscreen-button button{background-position:-32px 0;}.mejs-controls .mejs-unfullscreen button{background-position:-32px -16px;}.mejs-controls .mejs-mute button{background-position:-16px -16px;}.mejs-controls .mejs-unmute button{background-position:-16px 0;}.mejs-controls .mejs-volume-button{position:relative;}.mejs-controls .mejs-volume-button .mejs-volume-slider{display:none;height:115px;width:25px;background:url(background.png);background:rgba(50,50,50,0.7);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:-115px;left:0;z-index:1;position:absolute;margin:0;}.mejs-controls .mejs-volume-button:hover{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.5);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.9);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle{position:absolute;left:4px;top:-3px;width:16px;height:6px;background:#ddd;background:rgba(255,255,255,0.9);cursor:N-resize;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;margin:0;}.mejs-controls div.mejs-horizontal-volume-slider{height:26px;width:60px;position:relative;}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle{display:none;}.mejs-controls .mejs-captions-button{position:relative;}.mejs-controls .mejs-captions-button button{background-position:-48px 0;}.mejs-controls .mejs-captions-button .mejs-captions-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}.mejs-controls .mejs-captions-button .mejs-captions-translations{font-size:10px;margin:0 0 5px 0;}.mejs-chapters{position:absolute;top:0;left:0;-xborder-right:solid 1px #fff;width:10000px;z-index:1;}.mejs-chapters .mejs-chapter{position:absolute;float:left;background:#222;background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#323232,endColorstr=#000000);overflow:hidden;border:0;}.mejs-chapters .mejs-chapter .mejs-chapter-block{font-size:11px;color:#fff;padding:5px;display:block;border-right:solid 1px #333;border-bottom:solid 1px #333;cursor:pointer;}.mejs-chapters .mejs-chapter .mejs-chapter-block-last{border-right:none;}.mejs-chapters .mejs-chapter .mejs-chapter-block:hover{background:#666;background:rgba(102,102,102,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(102,102,102,0.7)),to(rgba(50,50,50,0.6)));background:-webkit-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-moz-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-o-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-ms-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:linear-gradient(rgba(102,102,102,0.7),rgba(50,50,50,0.6));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#666666,endColorstr=#323232);}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title{font-size:12px;font-weight:bold;display:block;white-space:nowrap;text-overflow:ellipsis;margin:0 0 3px 0;line-height:12px;}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan{font-size:12px;line-height:12px;margin:3px 0 4px 0;display:block;white-space:nowrap;text-overflow:ellipsis;}.mejs-captions-layer{position:absolute;bottom:0;left:0;text-align:center;line-height:22px;font-size:12px;color:#fff;}.mejs-captions-layer a{color:#fff;text-decoration:underline;}.mejs-captions-layer[lang=ar]{font-size:20px;font-weight:normal;}.mejs-captions-position{position:absolute;width:100%;bottom:15px;left:0;}.mejs-captions-position-hover{bottom:45px;}.mejs-captions-text{padding:3px 5px;background:url(background.png);background:rgba(20,20,20,0.8);}.mejs-clear{clear:both;}.me-cannotplay a{color:#fff;font-weight:bold;}.me-cannotplay span{padding:15px;display:block;}.mejs-controls .mejs-loop-off button{background-position:-64px -16px;}.mejs-controls .mejs-loop-on button{background-position:-64px 0;}.mejs-controls .mejs-backlight-off button{background-position:-80px -16px;}.mejs-controls .mejs-backlight-on button{background-position:-80px 0;}.mejs-controls .mejs-picturecontrols-button{background-position:-96px 0;}.mejs-contextmenu{position:absolute;width:150px;padding:10px;border-radius:4px;top:0;left:0;background:#fff;border:solid 1px #999;z-index:1001;}.mejs-contextmenu .mejs-contextmenu-separator{height:1px;font-size:0;margin:5px 6px;background:#333;}.mejs-contextmenu .mejs-contextmenu-item{font-family:Helvetica,Arial;font-size:12px;padding:4px 6px;cursor:pointer;color:#333;}.mejs-contextmenu .mejs-contextmenu-item:hover{background:#2C7C91;color:#fff;}.mejs-controls .mejs-sourcechooser-button{position:relative;}.mejs-controls .mejs-sourcechooser-button button{background-position:-128px 0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}
|
includes/media-element/mediaelementplayer.min.js
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* MediaElementPlayer
|
3 |
+
* http://mediaelementjs.com/
|
4 |
+
*
|
5 |
+
* Creates a controller bar for HTML5 <video> add <audio> tags
|
6 |
+
* using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper)
|
7 |
+
*
|
8 |
+
* Copyright 2010-2012, John Dyer (http://j.hn/)
|
9 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
10 |
+
*
|
11 |
+
*/if(typeof jQuery!="undefined")mejs.$=jQuery;else if(typeof ender!="undefined")mejs.$=ender;
|
12 |
+
(function(f){mejs.MepDefaults={poster:"",defaultVideoWidth:480,defaultVideoHeight:270,videoWidth:-1,videoHeight:-1,defaultAudioWidth:400,defaultAudioHeight:30,audioWidth:-1,audioHeight:-1,startVolume:0.8,loop:false,enableAutosize:true,alwaysShowHours:false,showTimecodeFrameCount:false,framesPerSecond:25,autosizeProgress:true,alwaysShowControls:false,iPadUseNativeControls:false,iPhoneUseNativeControls:false,AndroidUseNativeControls:false,features:["playpause","current","progress","duration","tracks",
|
13 |
+
"volume","fullscreen"],isVideo:true,enableKeyboard:true,pauseOtherPlayers:true,keyActions:[{keys:[32,179],action:function(a,b){b.paused||b.ended?b.play():b.pause()}},{keys:[38],action:function(a,b){b.setVolume(Math.min(b.volume+0.1,1))}},{keys:[40],action:function(a,b){b.setVolume(Math.max(b.volume-0.1,0))}},{keys:[37,227],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}b.setCurrentTime(Math.max(b.currentTime-b.duration*0.05,0))}}},{keys:[39,
|
14 |
+
228],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}b.setCurrentTime(Math.min(b.currentTime+b.duration*0.05,b.duration))}}},{keys:[70],action:function(a){if(typeof a.enterFullScreen!="undefined")a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}}]};mejs.mepIndex=0;mejs.players=[];mejs.MediaElementPlayer=function(a,b){if(!(this instanceof mejs.MediaElementPlayer))return new mejs.MediaElementPlayer(a,b);this.$media=this.$node=f(a);
|
15 |
+
this.node=this.media=this.$media[0];if(typeof this.node.player!="undefined")return this.node.player;else this.node.player=this;if(typeof b=="undefined")b=this.$node.data("mejsoptions");this.options=f.extend({},mejs.MepDefaults,b);mejs.players.push(this);this.init();return this};mejs.MediaElementPlayer.prototype={hasFocus:false,controlsAreVisible:true,init:function(){var a=this,b=mejs.MediaFeatures,c=f.extend(true,{},a.options,{success:function(e,g){a.meReady(e,g)},error:function(e){a.handleError(e)}}),
|
16 |
+
d=a.media.tagName.toLowerCase();a.isDynamic=d!=="audio"&&d!=="video";a.isVideo=a.isDynamic?a.options.isVideo:d!=="audio"&&a.options.isVideo;if(b.isiPad&&a.options.iPadUseNativeControls||b.isiPhone&&a.options.iPhoneUseNativeControls){a.$media.attr("controls","controls");if(b.isiPad&&a.media.getAttribute("autoplay")!==null){a.media.load();a.media.play()}}else if(!(b.isAndroid&&a.AndroidUseNativeControls)){a.$media.removeAttr("controls");a.id="mep_"+mejs.mepIndex++;a.container=f('<div id="'+a.id+'" class="mejs-container"><div class="mejs-inner"><div class="mejs-mediaelement"></div><div class="mejs-layers"></div><div class="mejs-controls"></div><div class="mejs-clear"></div></div></div>').addClass(a.$media[0].className).insertBefore(a.$media);
|
17 |
+
a.container.addClass((b.isAndroid?"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=d.substring(0,1).toUpperCase()+d.substring(1);
|
18 |
+
a.width=a.options[d+"Width"]>0||a.options[d+"Width"].toString().indexOf("%")>-1?a.options[d+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+b+"Width"];a.height=a.options[d+"Height"]>0||a.options[d+"Height"].toString().indexOf("%")>-1?a.options[d+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!==null?a.$media.attr("height"):
|
19 |
+
a.options["default"+b+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.height;c.pluginHeight=a.width}mejs.MediaElement(a.$media[0],c)},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true});b.container.find(".mejs-control").css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility",
|
20 |
+
"visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(b.controlsAreVisible)if(a){b.controls.stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block");b.controlsAreVisible=false});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display",
|
21 |
+
"block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false}},controlsTimer:null,startControlsTimer:function(a){var b=this;a=typeof a!="undefined"?a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;
|
22 |
+
this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false);this.controlsEnabled=true},meReady:function(a,b){var c=this,d=mejs.MediaFeatures,e=b.getAttribute("autoplay");e=!(typeof e=="undefined"||e===null||e==="false");var g;if(!c.created){c.created=true;c.media=a;c.domNode=b;if(!(d.isAndroid&&c.options.AndroidUseNativeControls)&&!(d.isiPad&&c.options.iPadUseNativeControls)&&
|
23 |
+
!(d.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media);c.findTracks();for(g in c.options.features){d=c.options.features[g];if(c["build"+d])try{c["build"+d](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);
|
24 |
+
else c.controlsEnabled&&c.showControls(false)});else{(c.media.pluginType=="native"?c.$media:f(c.media.pluginElement)).click(function(){a.paused?a.play():a.pause()});c.container.bind("mouseenter mouseover",function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",
|
25 |
+
function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&&c.startControlsTimer(1E3)})}e&&!c.options.alwaysShowControls&&c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(h){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(h.target.videoHeight)){c.setPlayerSize(h.target.videoWidth,h.target.videoHeight);c.setControlsSize();c.media.setVideoSize(h.target.videoWidth,h.target.videoHeight)}},false)}a.addEventListener("play",
|
26 |
+
function(){for(var h=0,o=mejs.players.length;h<o;h++){var n=mejs.players[h];n.id!=c.id&&c.options.pauseOtherPlayers&&!n.paused&&!n.ended&&n.pause();n.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){try{c.media.setCurrentTime(0)}catch(h){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.media.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",
|
27 |
+
function(){c.updateDuration&&c.updateDuration();c.updateCurrent&&c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width,c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);f(window).resize(function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.container.find(".mejs-overlay-play").hide()}if(e&&
|
28 |
+
a.pluginType=="native"){a.load();a.play()}if(c.options.success)typeof c.options.success=="string"?window[c.options.success](c.media,c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0){var c=this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.options.defaultVideoWidth,
|
29 |
+
d=this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.options.defaultVideoHeight,e=this.container.parent().width();c=parseInt(e*d/c,10);if(this.container.parent()[0].tagName.toLowerCase()==="body"){e=f(window).width();c=f(window).height()}this.container.width(e).height(c);this.$media.width("100%").height("100%");this.container.find("object, embed, iframe").width("100%").height("100%");this.media.setVideoSize&&this.media.setVideoSize(e,c);this.layers.children(".mejs-layer").width("100%").height("100%")}else{this.container.width(this.width).height(this.height);
|
30 |
+
this.layers.children(".mejs-layer").width(this.width).height(this.height)}},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),d=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var e=c.siblings();if(this.options&&!this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){e.each(function(){if(f(this).css("position")!="absolute")a+=f(this).outerWidth(true)});b=this.controls.width()-a-(c.outerWidth(true)-
|
31 |
+
c.width())}c.width(b);d.width(b-(d.outerWidth(true)-d.width()));this.setProgressRail&&this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()},buildposter:function(a,b,c,d){var e=f('<div class="mejs-poster mejs-layer"></div>').appendTo(c);b=a.$media.attr("poster");if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):e.hide();d.addEventListener("play",function(){e.hide()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"),c=b.find("img");if(c.length==
|
32 |
+
0)c=f('<img width="100%" height="100%" />').appendTo(b);c.attr("src",a)},buildoverlays:function(a,b,c,d){if(a.isVideo){var e=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-loading"><span></span></div></div>').hide().appendTo(c),g=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-error"></div></div>').hide().appendTo(c),k=f('<div class="mejs-overlay mejs-layer mejs-overlay-play"><div class="mejs-overlay-button"></div></div>').appendTo(c).click(function(){d.paused?d.play():
|
33 |
+
d.pause()});d.addEventListener("play",function(){k.hide();e.hide();b.find(".mejs-time-buffering").hide();g.hide()},false);d.addEventListener("playing",function(){k.hide();e.hide();b.find(".mejs-time-buffering").hide();g.hide()},false);d.addEventListener("seeking",function(){e.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("seeked",function(){e.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone||k.show()},
|
34 |
+
false);d.addEventListener("waiting",function(){e.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("loadeddata",function(){e.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("canplay",function(){e.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("error",function(){e.hide();b.find(".mejs-time-buffering").hide();g.show();g.find("mejs-overlay-error").html("Error loading this resource")},false)}},buildkeyboard:function(a,b,c,d){f(document).keydown(function(e){if(a.hasFocus&&
|
35 |
+
a.options.enableKeyboard)for(var g=0,k=a.options.keyActions.length;g<k;g++)for(var h=a.options.keyActions[g],o=0,n=h.keys.length;o<n;o++)if(e.keyCode==h.keys[o]){e.preventDefault();h.action(a,d);return false}return true});f(document).click(function(e){if(f(e.target).closest(".mejs-container").length==0)a.hasFocus=false})},findTracks:function(){var a=this,b=a.$media.find("track");a.tracks=[];b.each(function(c,d){d=f(d);a.tracks.push({srclang:d.attr("srclang").toLowerCase(),src:d.attr("src"),kind:d.attr("kind"),
|
36 |
+
label:d.attr("label")||"",entries:[],isLoaded:false})})},changeSkin:function(a){this.container[0].className="mejs-container "+a;this.setPlayerSize(this.width,this.height);this.setControlsSize()},play:function(){this.media.play()},pause:function(){this.media.pause()},load:function(){this.media.load()},setMuted:function(a){this.media.setMuted(a)},setCurrentTime:function(a){this.media.setCurrentTime(a)},getCurrentTime:function(){return this.media.currentTime},setVolume:function(a){this.media.setVolume(a)},
|
37 |
+
getVolume:function(){return this.media.volume},setSrc:function(a){this.media.setSrc(a)},remove:function(){if(this.media.pluginType=="flash")this.media.remove();else this.media.pluginType=="native"&&this.media.prop("controls",true);this.isDynamic||this.$node.insertBefore(this.container);this.container.remove()}};if(typeof jQuery!="undefined")jQuery.fn.mediaelementplayer=function(a){return this.each(function(){new mejs.MediaElementPlayer(this,a)})};f(document).ready(function(){f(".mejs-player").mediaelementplayer()});
|
38 |
+
window.MediaElementPlayer=mejs.MediaElementPlayer})(mejs.$);
|
39 |
+
(function(f){f.extend(mejs.MepDefaults,{playpauseText:"Play/Pause"});f.extend(MediaElementPlayer.prototype,{buildplaypause:function(a,b,c,d){var e=f('<div class="mejs-button mejs-playpause-button mejs-play" ><button type="button" aria-controls="'+this.id+'" title="'+this.options.playpauseText+'"></button></div>').appendTo(b).click(function(g){g.preventDefault();d.paused?d.play():d.pause();return false});d.addEventListener("play",function(){e.removeClass("mejs-play").addClass("mejs-pause")},false);
|
40 |
+
d.addEventListener("playing",function(){e.removeClass("mejs-play").addClass("mejs-pause")},false);d.addEventListener("pause",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false);d.addEventListener("paused",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$);
|
41 |
+
(function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,d){f('<div class="mejs-button mejs-stop-button mejs-stop"><button type="button" aria-controls="'+this.id+'" title="'+this.options.stopText+'"></button></div>').appendTo(b).click(function(){d.paused||d.pause();if(d.currentTime>0){d.setCurrentTime(0);b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left","0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));
|
42 |
+
b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$);
|
43 |
+
(function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,d){f('<div class="mejs-time-rail"><span class="mejs-time-total"><span class="mejs-time-buffering"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span></span></div>').appendTo(b);b.find(".mejs-time-buffering").hide();var e=
|
44 |
+
b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var g=b.find(".mejs-time-current"),k=b.find(".mejs-time-handle"),h=b.find(".mejs-time-float"),o=b.find(".mejs-time-float-current"),n=function(l){l=l.pageX;var q=e.offset(),i=e.outerWidth(),j=0;j=0;var m=l-q.left;if(l>q.left&&l<=i+q.left&&d.duration){j=(l-q.left)/i;j=j<=0.02?0:j*d.duration;p&&d.setCurrentTime(j);if(!mejs.MediaFeatures.hasTouch){h.css("left",m);o.html(mejs.Utility.secondsToTimeCode(j));h.show()}}},p=false;e.bind("mousedown",function(l){if(l.which===
|
45 |
+
1){p=true;n(l);f(document).bind("mousemove.dur",function(q){n(q)}).bind("mouseup.dur",function(){p=false;h.hide();f(document).unbind(".dur")});return false}}).bind("mouseenter",function(){f(document).bind("mousemove.dur",function(l){n(l)});mejs.MediaFeatures.hasTouch||h.show()}).bind("mouseleave",function(){if(!p){f(document).unbind(".dur");h.hide()}});d.addEventListener("progress",function(l){a.setProgressRail(l);a.setCurrentRail(l)},false);d.addEventListener("timeupdate",function(l){a.setProgressRail(l);
|
46 |
+
a.setCurrentRail(l)},false);this.loaded=c;this.total=e;this.current=g;this.handle=k},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal;else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1,Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*
|
47 |
+
c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=this.total.width()*this.media.currentTime/this.media.duration,b=a-this.handle.outerWidth(true)/2;this.current.width(a);this.handle.css("left",b)}}})})(mejs.$);
|
48 |
+
(function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:" <span> | </span> "});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,d){f('<div class="mejs-time"><span class="mejs-currenttime">'+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"</span></div>").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");d.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a,
|
49 |
+
b,c,d){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+'<span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span>").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container");
|
50 |
+
f('<div class="mejs-time mejs-duration-container"><span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span></div>").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");d.addEventListener("timeupdate",function(){a.updateDuration()},
|
51 |
+
false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){if(this.media.duration&&this.durationD)this.durationD.html(mejs.Utility.secondsToTimeCode(this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$);
|
52 |
+
(function(f){f.extend(mejs.MepDefaults,{muteText:"Mute Toggle",hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,d){if(!(mejs.MediaFeatures.hasTouch&&this.options.hideVolumeOnTouchDevices)){var e=this.isVideo?this.options.videoVolume:this.options.audioVolume,g=e=="horizontal"?f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+this.id+'" title="'+this.options.muteText+
|
53 |
+
'"></button></div><div class="mejs-horizontal-volume-slider"><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current"></div><div class="mejs-horizontal-volume-handle"></div></div>').appendTo(b):f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+this.id+'" title="'+this.options.muteText+'"></button><div class="mejs-volume-slider"><div class="mejs-volume-total"></div><div class="mejs-volume-current"></div><div class="mejs-volume-handle"></div></div></div>').appendTo(b),
|
54 |
+
k=this.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),h=this.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),o=this.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),n=this.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),p=function(j,m){if(!k.is(":visible")&&typeof m!="undefined"){k.show();p(j,true);k.hide()}else{j=Math.max(0,j);j=Math.min(j,1);j==0?g.removeClass("mejs-mute").addClass("mejs-unmute"):g.removeClass("mejs-unmute").addClass("mejs-mute");
|
55 |
+
if(e=="vertical"){var r=h.height(),s=h.position(),t=r-r*j;n.css("top",s.top+t-n.height()/2);o.height(r-t);o.css("top",s.top+t)}else{r=h.width();s=h.position();r=r*j;n.css("left",s.left+r-n.width()/2);o.width(r)}}},l=function(j){var m=null,r=h.offset();if(e=="vertical"){m=h.height();parseInt(h.css("top").replace(/px/,""),10);m=(m-(j.pageY-r.top))/m;if(r.top==0||r.left==0)return}else{m=h.width();m=(j.pageX-r.left)/m}m=Math.max(0,m);m=Math.min(m,1);p(m);m==0?d.setMuted(true):d.setMuted(false);d.setVolume(m)},
|
56 |
+
q=false,i=false;g.hover(function(){k.show();i=true},function(){i=false;!q&&e=="vertical"&&k.hide()});k.bind("mouseover",function(){i=true}).bind("mousedown",function(j){l(j);f(document).bind("mousemove.vol",function(m){l(m)}).bind("mouseup.vol",function(){q=false;f(document).unbind(".vol");!i&&e=="vertical"&&k.hide()});q=true;return false});g.find("button").click(function(){d.setMuted(!d.muted)});d.addEventListener("volumechange",function(){if(!q)if(d.muted){p(0);g.removeClass("mejs-mute").addClass("mejs-unmute")}else{p(d.volume);
|
57 |
+
g.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(this.container.is(":visible")){p(a.options.startVolume);d.pluginType==="native"&&d.setVolume(a.options.startVolume)}}}})})(mejs.$);
|
58 |
+
(function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:"Fullscreen"});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,docStyleOverflow:null,isInIframe:false,buildfullscreen:function(a,b,c,d){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;if(mejs.MediaFeatures.hasTrueNativeFullScreen){c=null;c=mejs.MediaFeatures.hasMozNativeFullScreen?f(document):a.container;c.bind(mejs.MediaFeatures.fullScreenEventName,
|
59 |
+
function(){if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen=true;a.setControlsSize()}else{a.isNativeFullScreen=false;a.exitFullScreen()}})}var e=this,g=f('<div class="mejs-button mejs-fullscreen-button"><button type="button" aria-controls="'+e.id+'" title="'+e.options.fullscreenText+'"></button></div>').appendTo(b);if(e.media.pluginType==="native"||!e.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||
|
60 |
+
a.isFullScreen?a.exitFullScreen():a.enterFullScreen()});else{var k=null;b=function(){var i=document.createElement("x"),j=document.documentElement,m=window.getComputedStyle;if(!("pointerEvents"in i.style))return false;i.style.pointerEvents="auto";i.style.pointerEvents="x";j.appendChild(i);m=m&&m(i,"").pointerEvents==="auto";j.removeChild(i);return!!m}();console.log("supportsPointerEvents",b);if(b&&!mejs.MediaFeatures.isOpera){var h=false,o=function(){if(h){n.hide();p.hide();l.hide();g.css("pointer-events",
|
61 |
+
"");e.controls.css("pointer-events","");h=false}},n=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(o),p=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(o),l=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(o),q=function(){var i={position:"absolute",top:0,left:0};n.css(i);p.css(i);l.css(i);n.width(e.container.width()).height(e.container.height()-e.controls.height());i=g.offset().left-e.container.offset().left;fullScreenBtnWidth=
|
62 |
+
g.outerWidth(true);p.width(i).height(e.controls.height()).css({top:e.container.height()-e.controls.height()});l.width(e.container.width()-i-fullScreenBtnWidth).height(e.controls.height()).css({top:e.container.height()-e.controls.height(),left:i+fullScreenBtnWidth})};f(document).resize(function(){q()});g.mouseover(function(){if(!e.isFullScreen){var i=g.offset(),j=a.container.offset();d.positionFullscreenButton(i.left-j.left,i.top-j.top,false);g.css("pointer-events","none");e.controls.css("pointer-events",
|
63 |
+
"none");n.show();l.show();p.show();q();h=true}});d.addEventListener("fullscreenchange",function(){o()})}else g.mouseover(function(){if(k!==null){clearTimeout(k);delete k}var i=g.offset(),j=a.container.offset();d.positionFullscreenButton(i.left-j.left,i.top-j.top,true)}).mouseout(function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){d.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;f(document).bind("keydown",function(i){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||
|
64 |
+
e.isFullScreen)&&i.keyCode==27)a.exitFullScreen()})}},enterFullScreen:function(){var a=this;if(!(a.media.pluginType!=="native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){docStyleOverflow=document.documentElement.style.overflow;document.documentElement.style.overflow="hidden";normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&
|
65 |
+
setTimeout(function c(){if(a.isNativeFullScreen)f(window).width()!==screen.width?a.exitFullScreen():setTimeout(c,500)},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},
|
66 |
+
250);else{a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find("object, embed, iframe").width("100%").height("100%");a.media.setVideoSize(f(window).width(),
|
67 |
+
f(window).height())}a.layers.children("div").width("100%").height("100%");a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true}},exitFullScreen:function(){if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&&(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen();document.documentElement.style.overflow=
|
68 |
+
docStyleOverflow;this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find("object embed").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight);this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen");this.setControlsSize();this.isFullScreen=
|
69 |
+
false}}})})(mejs.$);
|
70 |
+
(function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:"Captions/Subtitles"});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,d){if(a.isVideo)if(a.tracks.length!=0){var e;a.chapters=f('<div class="mejs-chapters mejs-layer"></div>').prependTo(c).hide();a.captions=f('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position"><span class="mejs-captions-text"></span></div></div>').prependTo(c).hide();a.captionsText=a.captions.find(".mejs-captions-text");
|
71 |
+
a.captionsButton=f('<div class="mejs-button mejs-captions-button"><button type="button" aria-controls="'+this.id+'" title="'+this.options.tracksText+'"></button><div class="mejs-captions-selector"><ul><li><input type="radio" name="'+a.id+'_captions" id="'+a.id+'_captions_none" value="none" checked="checked" /><label for="'+a.id+'_captions_none">None</label></li></ul></div></div>').appendTo(b).hover(function(){f(this).find(".mejs-captions-selector").css("visibility","visible")},function(){f(this).find(".mejs-captions-selector").css("visibility",
|
72 |
+
"hidden")}).delegate("input[type=radio]","click",function(){lang=this.value;if(lang=="none")a.selectedTrack=null;else for(e=0;e<a.tracks.length;e++)if(a.tracks[e].srclang==lang){a.selectedTrack=a.tracks[e];a.captions.attr("lang",a.selectedTrack.srclang);a.displayCaptions();break}});a.options.alwaysShowControls?a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover"):a.container.bind("mouseenter",function(){a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover")}).bind("mouseleave",
|
73 |
+
function(){d.paused||a.container.find(".mejs-captions-position").removeClass("mejs-captions-position-hover")});a.trackToLoad=-1;a.selectedTrack=null;a.isLoadingTrack=false;for(e=0;e<a.tracks.length;e++)a.tracks[e].kind=="subtitles"&&a.addTrackButton(a.tracks[e].srclang,a.tracks[e].label);a.loadNextTrack();d.addEventListener("timeupdate",function(){a.displayCaptions()},false);d.addEventListener("loadedmetadata",function(){a.displayChapters()},false);a.container.hover(function(){if(a.hasChapters){a.chapters.css("visibility",
|
74 |
+
"visible");a.chapters.fadeIn(200).height(a.chapters.find(".mejs-chapter").outerHeight())}},function(){a.hasChapters&&!d.paused&&a.chapters.fadeOut(200,function(){f(this).css("visibility","hidden");f(this).css("display","block")})});a.node.getAttribute("autoplay")!==null&&a.chapters.css("visibility","hidden")}},loadNextTrack:function(){this.trackToLoad++;if(this.trackToLoad<this.tracks.length){this.isLoadingTrack=true;this.loadTrack(this.trackToLoad)}else this.isLoadingTrack=false},loadTrack:function(a){var b=
|
75 |
+
this,c=b.tracks[a],d=function(){c.isLoaded=true;b.enableTrackButton(c.srclang,c.label);b.loadNextTrack()};c.isTranslation?mejs.TrackFormatParser.translateTrackText(b.tracks[0].entries,b.tracks[0].srclang,c.srclang,b.options.googleApiKey,function(e){c.entries=e;d()}):f.ajax({url:c.src,success:function(e){c.entries=mejs.TrackFormatParser.parse(e);d();c.kind=="chapters"&&b.media.duration>0&&b.drawChapters(c)},error:function(){b.loadNextTrack()}})},enableTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||
|
76 |
+
a;this.captionsButton.find("input[value="+a+"]").prop("disabled",false).siblings("label").html(b);this.options.startLanguage==a&&f("#"+this.id+"_captions_"+a).click();this.adjustLanguageBox()},addTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("ul").append(f('<li><input type="radio" name="'+this.id+'_captions" id="'+this.id+"_captions_"+a+'" value="'+a+'" disabled="disabled" /><label for="'+this.id+"_captions_"+a+'">'+b+" (loading)</label></li>"));this.adjustLanguageBox();
|
77 |
+
this.container.find(".mejs-captions-translations option[value="+a+"]").remove()},adjustLanguageBox:function(){this.captionsButton.find(".mejs-captions-selector").height(this.captionsButton.find(".mejs-captions-selector ul").outerHeight(true)+this.captionsButton.find(".mejs-captions-translations").outerHeight(true))},displayCaptions:function(){if(typeof this.tracks!="undefined"){var a,b=this.selectedTrack;if(b!=null&&b.isLoaded)for(a=0;a<b.entries.times.length;a++)if(this.media.currentTime>=b.entries.times[a].start&&
|
78 |
+
this.media.currentTime<=b.entries.times[a].stop){this.captionsText.html(b.entries.text[a]);this.captions.show().height(0);return}this.captions.hide()}},displayChapters:function(){var a;for(a=0;a<this.tracks.length;a++)if(this.tracks[a].kind=="chapters"&&this.tracks[a].isLoaded){this.drawChapters(this.tracks[a]);this.hasChapters=true;break}},drawChapters:function(a){var b=this,c,d,e=d=0;b.chapters.empty();for(c=0;c<a.entries.times.length;c++){d=a.entries.times[c].stop-a.entries.times[c].start;d=Math.floor(d/
|
79 |
+
b.media.duration*100);if(d+e>100||c==a.entries.times.length-1&&d+e<100)d=100-e;b.chapters.append(f('<div class="mejs-chapter" rel="'+a.entries.times[c].start+'" style="left: '+e.toString()+"%;width: "+d.toString()+'%;"><div class="mejs-chapter-block'+(c==a.entries.times.length-1?" mejs-chapter-block-last":"")+'"><span class="ch-title">'+a.entries.text[c]+'</span><span class="ch-time">'+mejs.Utility.secondsToTimeCode(a.entries.times[c].start)+"–"+mejs.Utility.secondsToTimeCode(a.entries.times[c].stop)+
|
80 |
+
"</span></div></div>"));e+=d}b.chapters.find("div.mejs-chapter").click(function(){b.media.setCurrentTime(parseFloat(f(this).attr("rel")));b.media.paused&&b.media.play()});b.chapters.show()}});mejs.language={codes:{af:"Afrikaans",sq:"Albanian",ar:"Arabic",be:"Belarusian",bg:"Bulgarian",ca:"Catalan",zh:"Chinese","zh-cn":"Chinese Simplified","zh-tw":"Chinese Traditional",hr:"Croatian",cs:"Czech",da:"Danish",nl:"Dutch",en:"English",et:"Estonian",tl:"Filipino",fi:"Finnish",fr:"French",gl:"Galician",de:"German",
|
81 |
+
el:"Greek",ht:"Haitian Creole",iw:"Hebrew",hi:"Hindi",hu:"Hungarian",is:"Icelandic",id:"Indonesian",ga:"Irish",it:"Italian",ja:"Japanese",ko:"Korean",lv:"Latvian",lt:"Lithuanian",mk:"Macedonian",ms:"Malay",mt:"Maltese",no:"Norwegian",fa:"Persian",pl:"Polish",pt:"Portuguese",ro:"Romanian",ru:"Russian",sr:"Serbian",sk:"Slovak",sl:"Slovenian",es:"Spanish",sw:"Swahili",sv:"Swedish",tl:"Tagalog",th:"Thai",tr:"Turkish",uk:"Ukrainian",vi:"Vietnamese",cy:"Welsh",yi:"Yiddish"}};mejs.TrackFormatParser={pattern_identifier:/^([a-zA-z]+-)?[0-9]+$/,
|
82 |
+
pattern_timecode:/^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/,split2:function(a,b){return a.split(b)},parse:function(a){var b=0;a=this.split2(a,/\r?\n/);for(var c={text:[],times:[]},d,e;b<a.length;b++)if(this.pattern_identifier.exec(a[b])){b++;if((d=this.pattern_timecode.exec(a[b]))&&b<a.length){b++;e=a[b];for(b++;a[b]!==""&&b<a.length;){e=e+"\n"+a[b];b++}c.text.push(e);c.times.push({start:mejs.Utility.timeCodeToSeconds(d[1]),stop:mejs.Utility.timeCodeToSeconds(d[3]),
|
83 |
+
settings:d[5]})}}return c}};if("x\n\ny".split(/\n/gi).length!=3)mejs.TrackFormatParser.split2=function(a,b){var c=[],d="",e;for(e=0;e<a.length;e++){d+=a.substring(e,e+1);if(b.test(d)){c.push(d.replace(b,""));d=""}}c.push(d);return c}})(mejs.$);
|
84 |
+
(function(f){f.extend(mejs.MepDefaults,{contextMenuItems:[{render:function(a){if(typeof a.enterFullScreen=="undefined")return null;return a.isFullScreen?"Turn off Fullscreen":"Go Fullscreen"},click:function(a){a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}},{render:function(a){return a.media.muted?"Unmute":"Mute"},click:function(a){a.media.muted?a.setMuted(false):a.setMuted(true)}},{isSeparator:true},{render:function(){return"Download Video"},click:function(a){window.location.href=a.media.currentSrc}}]});
|
85 |
+
f.extend(MediaElementPlayer.prototype,{buildcontextmenu:function(a){a.contextMenu=f('<div class="mejs-contextmenu"></div>').appendTo(f("body")).hide();a.container.bind("contextmenu",function(b){if(a.isContextMenuEnabled){b.preventDefault();a.renderContextMenu(b.clientX-1,b.clientY-1);return false}});a.container.bind("click",function(){a.contextMenu.hide()});a.contextMenu.bind("mouseleave",function(){a.startContextMenuTimer()})},isContextMenuEnabled:true,enableContextMenu:function(){this.isContextMenuEnabled=
|
86 |
+
true},disableContextMenu:function(){this.isContextMenuEnabled=false},contextMenuTimeout:null,startContextMenuTimer:function(){var a=this;a.killContextMenuTimer();a.contextMenuTimer=setTimeout(function(){a.hideContextMenu();a.killContextMenuTimer()},750)},killContextMenuTimer:function(){var a=this.contextMenuTimer;if(a!=null){clearTimeout(a);delete a}},hideContextMenu:function(){this.contextMenu.hide()},renderContextMenu:function(a,b){for(var c=this,d="",e=c.options.contextMenuItems,g=0,k=e.length;g<
|
87 |
+
k;g++)if(e[g].isSeparator)d+='<div class="mejs-contextmenu-separator"></div>';else{var h=e[g].render(c);if(h!=null)d+='<div class="mejs-contextmenu-item" data-itemindex="'+g+'" id="element-'+Math.random()*1E6+'">'+h+"</div>"}c.contextMenu.empty().append(f(d)).css({top:b,left:a}).show();c.contextMenu.find(".mejs-contextmenu-item").each(function(){var o=f(this),n=parseInt(o.data("itemindex"),10),p=c.options.contextMenuItems[n];typeof p.show!="undefined"&&p.show(o,c);o.click(function(){typeof p.click!=
|
88 |
+
"undefined"&&p.click(c);c.contextMenu.hide()})});setTimeout(function(){c.killControlsTimer("rev3")},100)}})})(mejs.$);
|
includes/media-element/mejs-skins.css
ADDED
@@ -0,0 +1,283 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* TED player */
|
2 |
+
.mejs-container.mejs-ted {
|
3 |
+
|
4 |
+
}
|
5 |
+
.mejs-ted .mejs-controls {
|
6 |
+
background: #eee;
|
7 |
+
height: 65px;
|
8 |
+
}
|
9 |
+
|
10 |
+
.mejs-ted .mejs-button,
|
11 |
+
.mejs-ted .mejs-time {
|
12 |
+
position: absolute;
|
13 |
+
background: #ddd;
|
14 |
+
}
|
15 |
+
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-total {
|
16 |
+
background-color: none;
|
17 |
+
background: url(controls-ted.png) repeat-x 0 -52px;
|
18 |
+
height: 6px;
|
19 |
+
}
|
20 |
+
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-loaded {
|
21 |
+
background-color: none;
|
22 |
+
background: url(controls-ted.png) repeat-x 0 -52px;
|
23 |
+
width: 0;
|
24 |
+
height: 6px;
|
25 |
+
}
|
26 |
+
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-current {
|
27 |
+
width: 0;
|
28 |
+
height: 6px;
|
29 |
+
background-color: none;
|
30 |
+
background: url(controls-ted.png) repeat-x 0 -59px;
|
31 |
+
}
|
32 |
+
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-handle {
|
33 |
+
display: block;
|
34 |
+
margin: 0;
|
35 |
+
width: 14px;
|
36 |
+
height: 21px;
|
37 |
+
top: -7px;
|
38 |
+
border: 0;
|
39 |
+
background: url(controls-ted.png) no-repeat 0 0;
|
40 |
+
}
|
41 |
+
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-float {
|
42 |
+
display: none;
|
43 |
+
}
|
44 |
+
.mejs-ted .mejs-controls .mejs-playpause-button {
|
45 |
+
top: 29px;
|
46 |
+
left: 9px;
|
47 |
+
width: 49px;
|
48 |
+
height: 28px;
|
49 |
+
}
|
50 |
+
.mejs-ted .mejs-controls .mejs-playpause-button button {
|
51 |
+
width: 49px;
|
52 |
+
height: 28px;
|
53 |
+
background: url(controls-ted.png) no-repeat -50px -23px;
|
54 |
+
margin: 0;
|
55 |
+
padding: 0;
|
56 |
+
}
|
57 |
+
.mejs-ted .mejs-controls .mejs-pause button {
|
58 |
+
background-position: 0 -23px;
|
59 |
+
}
|
60 |
+
|
61 |
+
.mejs-ted .mejs-controls .mejs-fullscreen-button {
|
62 |
+
top: 34px;
|
63 |
+
right: 9px;
|
64 |
+
width: 17px;
|
65 |
+
height: 15px;
|
66 |
+
background : none;
|
67 |
+
}
|
68 |
+
.mejs-ted .mejs-controls .mejs-fullscreen-button button {
|
69 |
+
width: 19px;
|
70 |
+
height: 17px;
|
71 |
+
background: transparent url(controls-ted.png) no-repeat 0 -66px;
|
72 |
+
margin: 0;
|
73 |
+
padding: 0;
|
74 |
+
}
|
75 |
+
.mejs-ted .mejs-controls .mejs-unfullscreen button {
|
76 |
+
background: transparent url(controls-ted.png) no-repeat -21px -66px;
|
77 |
+
margin: 0;
|
78 |
+
padding: 0;
|
79 |
+
}
|
80 |
+
.mejs-ted .mejs-controls .mejs-volume-button {
|
81 |
+
top: 30px;
|
82 |
+
right: 35px;
|
83 |
+
width: 24px;
|
84 |
+
height: 22px;
|
85 |
+
}
|
86 |
+
.mejs-ted .mejs-controls .mejs-mute button {
|
87 |
+
background: url(controls-ted.png) no-repeat -15px 0;
|
88 |
+
width: 24px;
|
89 |
+
height: 22px;
|
90 |
+
margin: 0;
|
91 |
+
padding: 0;
|
92 |
+
}
|
93 |
+
.mejs-ted .mejs-controls .mejs-unmute button {
|
94 |
+
background: url(controls-ted.png) no-repeat -40px 0;
|
95 |
+
width: 24px;
|
96 |
+
height: 22px;
|
97 |
+
margin: 0;
|
98 |
+
padding: 0;
|
99 |
+
}
|
100 |
+
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-slider {
|
101 |
+
background: #fff;
|
102 |
+
border: solid 1px #aaa;
|
103 |
+
border-width: 1px 1px 0 1px;
|
104 |
+
width: 22px;
|
105 |
+
height: 65px;
|
106 |
+
top: -65px;
|
107 |
+
}
|
108 |
+
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-total {
|
109 |
+
background: url(controls-ted.png) repeat-y -41px -66px;
|
110 |
+
left: 8px;
|
111 |
+
width: 6px;
|
112 |
+
height: 50px;
|
113 |
+
}
|
114 |
+
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-current {
|
115 |
+
left: 8px;
|
116 |
+
width: 6px;
|
117 |
+
background: url(controls-ted.png) repeat-y -48px -66px;
|
118 |
+
height: 50px;
|
119 |
+
}
|
120 |
+
|
121 |
+
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-handle {
|
122 |
+
display: none;
|
123 |
+
}
|
124 |
+
|
125 |
+
.mejs-ted .mejs-controls .mejs-time span {
|
126 |
+
color: #333;
|
127 |
+
}
|
128 |
+
.mejs-ted .mejs-controls .mejs-currenttime-container {
|
129 |
+
position: absolute;
|
130 |
+
top: 32px;
|
131 |
+
right: 100px;
|
132 |
+
border: solid 1px #999;
|
133 |
+
background: #fff;
|
134 |
+
color: #333;
|
135 |
+
padding-top: 2px;
|
136 |
+
border-radius: 3px;
|
137 |
+
color: #333;
|
138 |
+
}
|
139 |
+
.mejs-ted .mejs-controls .mejs-duration-container {
|
140 |
+
|
141 |
+
position: absolute;
|
142 |
+
top: 32px;
|
143 |
+
right: 65px;
|
144 |
+
border: solid 1px #999;
|
145 |
+
background: #fff;
|
146 |
+
color: #333;
|
147 |
+
padding-top: 2px;
|
148 |
+
border-radius: 3px;
|
149 |
+
color: #333;
|
150 |
+
}
|
151 |
+
|
152 |
+
.mejs-ted .mejs-controls .mejs-time button{
|
153 |
+
color: #333;
|
154 |
+
}
|
155 |
+
.mejs-ted .mejs-controls .mejs-captions-button {
|
156 |
+
display: none;
|
157 |
+
}
|
158 |
+
/* END: TED player */
|
159 |
+
|
160 |
+
|
161 |
+
/* WMP player */
|
162 |
+
.mejs-container.mejs-wmp {
|
163 |
+
|
164 |
+
}
|
165 |
+
.mejs-wmp .mejs-controls {
|
166 |
+
background: transparent url(controls-wmp-bg.png) center 16px no-repeat;
|
167 |
+
height: 65px;
|
168 |
+
}
|
169 |
+
|
170 |
+
.mejs-wmp .mejs-button,
|
171 |
+
.mejs-wmp .mejs-time {
|
172 |
+
position: absolute;
|
173 |
+
background: transparent;
|
174 |
+
}
|
175 |
+
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-total {
|
176 |
+
background-color: transparent;
|
177 |
+
border: solid 1px #ccc;
|
178 |
+
height: 3px;
|
179 |
+
}
|
180 |
+
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-loaded {
|
181 |
+
background-color: rgba(255,255,255,0.3);
|
182 |
+
width: 0;
|
183 |
+
height: 3px;
|
184 |
+
}
|
185 |
+
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-current {
|
186 |
+
width: 0;
|
187 |
+
height: 1px;
|
188 |
+
background-color: #014CB6;
|
189 |
+
border: solid 1px #7FC9FA;
|
190 |
+
border-width: 1px 0;
|
191 |
+
border-color: #7FC9FA #fff #619FF2 #fff;
|
192 |
+
}
|
193 |
+
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-handle {
|
194 |
+
display: block;
|
195 |
+
margin: 0;
|
196 |
+
width: 16px;
|
197 |
+
height: 9px;
|
198 |
+
top: -3px;
|
199 |
+
border: 0;
|
200 |
+
background: url(controls-wmp.png) no-repeat 0 -80px;
|
201 |
+
}
|
202 |
+
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-float {
|
203 |
+
display: none;
|
204 |
+
}
|
205 |
+
.mejs-wmp .mejs-controls .mejs-playpause-button {
|
206 |
+
top: 10px;
|
207 |
+
left: 50%;
|
208 |
+
margin: 10px 0 0 -20px;
|
209 |
+
width: 40px;
|
210 |
+
height: 40px;
|
211 |
+
|
212 |
+
}
|
213 |
+
.mejs-wmp .mejs-controls .mejs-playpause-button button {
|
214 |
+
width: 40px;
|
215 |
+
height: 40px;
|
216 |
+
background: url(controls-wmp.png) no-repeat 0 0;
|
217 |
+
margin: 0;
|
218 |
+
padding: 0;
|
219 |
+
}
|
220 |
+
.mejs-wmp .mejs-controls .mejs-pause button {
|
221 |
+
background-position: 0 -40px;
|
222 |
+
}
|
223 |
+
|
224 |
+
.mejs-wmp .mejs-controls .mejs-currenttime-container {
|
225 |
+
position: absolute;
|
226 |
+
top: 25px;
|
227 |
+
left: 50%;
|
228 |
+
margin-left: -93px;
|
229 |
+
}
|
230 |
+
.mejs-wmp .mejs-controls .mejs-duration-container {
|
231 |
+
position: absolute;
|
232 |
+
top: 25px;
|
233 |
+
left: 50%;
|
234 |
+
margin-left: -58px;
|
235 |
+
}
|
236 |
+
|
237 |
+
|
238 |
+
.mejs-wmp .mejs-controls .mejs-volume-button {
|
239 |
+
top: 32px;
|
240 |
+
right: 50%;
|
241 |
+
margin-right: -55px;
|
242 |
+
width: 20px;
|
243 |
+
height: 15px;
|
244 |
+
}
|
245 |
+
.mejs-wmp .mejs-controls .mejs-volume-button button {
|
246 |
+
margin: 0;
|
247 |
+
padding: 0;
|
248 |
+
background: url(controls-wmp.png) no-repeat -42px -17px;
|
249 |
+
width: 20px;
|
250 |
+
height: 15px;
|
251 |
+
}
|
252 |
+
.mejs-wmp .mejs-controls .mejs-unmute button {
|
253 |
+
margin: 0;
|
254 |
+
padding: 0;
|
255 |
+
background: url(controls-wmp.png) no-repeat -42px 0;
|
256 |
+
width: 20px;
|
257 |
+
height: 15px;
|
258 |
+
}
|
259 |
+
.mejs-wmp .mejs-controls .mejs-volume-button .mejs-volume-slider {
|
260 |
+
background: rgba(102,102,102,0.6);
|
261 |
+
}
|
262 |
+
|
263 |
+
.mejs-wmp .mejs-controls .mejs-fullscreen-button {
|
264 |
+
top: 32px;
|
265 |
+
right: 50%;
|
266 |
+
margin-right: -82px;
|
267 |
+
width: 15px;
|
268 |
+
height: 14px;
|
269 |
+
}
|
270 |
+
.mejs-wmp .mejs-controls .mejs-fullscreen-button button {
|
271 |
+
margin: 0;
|
272 |
+
padding: 0;
|
273 |
+
background: url(controls-wmp.png) no-repeat -63px 0;
|
274 |
+
width: 15px;
|
275 |
+
height: 14px;
|
276 |
+
}
|
277 |
+
.mejs-wmp .mejs-controls .mejs-captions-button {
|
278 |
+
display: none;
|
279 |
+
}
|
280 |
+
/* END: WMP player */
|
281 |
+
|
282 |
+
|
283 |
+
|
includes/media-element/silverlightmediaelement.xap
ADDED
Binary file
|
loader.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: BuddyPress Media
|
4 |
+
Plugin URI: http://rtcamp.com/buddypress-media/
|
5 |
+
Description: This component adds missing media rich features like photos, videos and audios uploading to BuddyPress which are essential if you are building social network, seriously!
|
6 |
+
Version: 2.0
|
7 |
+
Author: rtCamp
|
8 |
+
Author URI: http://rtcamp.com
|
9 |
+
*/
|
10 |
+
|
11 |
+
/* A constant that can be checked to see if the BP Media is installed or not. */
|
12 |
+
define('BP_MEDIA_IS_INSTALLED', 1);
|
13 |
+
|
14 |
+
/* Constant to store the current version of the BP Media Plugin. */
|
15 |
+
define('BP_MEDIA_VERSION', '2.0');
|
16 |
+
|
17 |
+
/* A constant to be used as base for other URLs throughout the plugin */
|
18 |
+
define('BP_MEDIA_PLUGIN_DIR', dirname(__FILE__));
|
19 |
+
|
20 |
+
/* A constant to store the Database Version of the BP Media Plugin */
|
21 |
+
define('BP_MEDIA_DB_VERSION', '1');
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Function to initialize the BP Media Plugin
|
25 |
+
*
|
26 |
+
* It checks for the version minimum required version of buddypress before initializing.
|
27 |
+
*
|
28 |
+
* @uses BP_VERSION to check if the plugin supports the BuddyPress version.
|
29 |
+
*
|
30 |
+
* @since BP Media 2.0
|
31 |
+
*/
|
32 |
+
function bp_media_init() {
|
33 |
+
if (version_compare(BP_VERSION, '1.5.5', '>')) {
|
34 |
+
require( BP_MEDIA_PLUGIN_DIR . '/includes/bp-media-loader.php' );
|
35 |
+
}
|
36 |
+
}
|
37 |
+
add_action('bp_include', 'bp_media_init');
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Function to do the tasks required to be done while activating the plugin
|
41 |
+
*/
|
42 |
+
function bp_media_activate() {
|
43 |
+
//todo
|
44 |
+
}
|
45 |
+
register_activation_hook(__FILE__, 'bp_media_activate');
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Function to do the tasks during deactivation.
|
49 |
+
*
|
50 |
+
* Will Make this function to do the db deletion and other things that might have been created with the plugin.
|
51 |
+
*/
|
52 |
+
function bp_media_deactivate() {
|
53 |
+
//todo
|
54 |
+
}
|
55 |
+
register_deactivation_hook(__FILE__, 'bp_media_deactivate');
|
56 |
+
?>
|
readme.txt
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== BuddyPress Media Component ===
|
2 |
+
Contributors: rtcamp
|
3 |
+
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9488824
|
4 |
+
Tags: BuddyPress, media, multimedia, audio, video, photo, images, upload, share, MediaElement.js
|
5 |
+
License: GPLv2 or later
|
6 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
7 |
+
Requires at least: 3.3.2
|
8 |
+
Tested up to: 3.4.1
|
9 |
+
Stable tag: 2.0
|
10 |
+
|
11 |
+
BuddyPress Media Component adds multimedia features to your BuddyPress based social network.
|
12 |
+
|
13 |
+
== Description ==
|
14 |
+
[BuddyPress Media Component](http://rtcamp.com/buddypress-media/) adds multimedia features to your BuddyPress based social network, so that your members can upload and share photos, audio and videos with their friends.
|
15 |
+
|
16 |
+
= Features =
|
17 |
+
* Images, Audio and Video Support
|
18 |
+
* Superior Performance
|
19 |
+
* HTML5 player with fall back
|
20 |
+
* Highly Scalable
|
21 |
+
|
22 |
+
== Installation ==
|
23 |
+
Install the plugin from the 'Plugins' section in your dashboard (Plugins > Add New > Search for BuddyPress Media).
|
24 |
+
|
25 |
+
Alternatively you can [download lastest version](http://downloads.wordpress.org/plugin/buddypress-media.2.0.zip) of BuddyPress Media Component plugin from the repository. Unzip it and upload it to the plugins folder of your WordPress installation (wp-content/plugins/ directory of your WordPress installation).
|
26 |
+
|
27 |
+
Activate it through the 'Plugins' section.
|
28 |
+
|
29 |
+
== Frequently Asked Questions ==
|
30 |
+
Please visit [BuddyPress Media Component's FAQ page](http://rtcamp.com/buddypress-media/faq/)
|
31 |
+
|
32 |
+
== Screenshots ==
|
33 |
+
Please visit [BuddyPress Media Component's Features page](http://rtcamp.com/buddypress-media/features/)
|
34 |
+
|
35 |
+
== Changelog ==
|
36 |
+
|
37 |
+
= 2.0 =
|
38 |
+
* Integration into BuddyPress Activities
|
39 |
+
* HTML5 Audio Tag Support (with fallback)
|
40 |
+
* HTML5 Video Tag Support (with fallback)
|