View source
<?php
defined('VIDEO_RENDERING_PENDING') || define('VIDEO_RENDERING_PENDING', 1);
defined('VIDEO_RENDERING_INQUEUE') || define('VIDEO_RENDERING_INQUEUE', 2);
defined('VIDEO_RENDERING_ACTIVE') || define('VIDEO_RENDERING_ACTIVE', 5);
defined('VIDEO_RENDERING_COMPLETE') || define('VIDEO_RENDERING_COMPLETE', 10);
defined('VIDEO_RENDERING_FAILED') || define('VIDEO_RENDERING_FAILED', 20);
module_load_include('inc', 'video', 'video.field');
module_load_include('inc', 'video', 'video.features');
function video_init() {
drupal_add_css(drupal_get_path('module', 'video') . '/css/video.css');
drupal_add_js(drupal_get_path('module', 'video') . '/js/video.js');
}
function video_permission() {
$perms = array(
'bypass conversion video' => array(
'title' => t('Bypass video conversion'),
'description' => t('Warning: Give to trusted roles only; this permission has security implications.'),
),
'convert on submission' => array(
'title' => t('Convert video on submit'),
'description' => t('Warning: Give to trusted roles only; this permission has security implications.'),
),
'override player dimensions' => array(
'title' => t('Change default player dimentions'),
'description' => t('Warning: Give to trusted roles only; this permission has usability implications.'),
),
'use default thumb' => array(
'title' => t('Use default thumbnail'),
),
're convert video' => array(
'title' => t('Re queue video'),
),
'administer video presets' => array(
'title' => t('Administer video presets'),
'description' => t('Perform administration tasks for the video presets.'),
),
);
return $perms;
}
function video_theme() {
$theme = array();
$theme['video'] = array(
'variables' => array(
'item' => NULL,
'path' => NULL,
'video_style' => NULL,
'entity' => NULL,
'field' => NULL,
'instance' => NULL,
),
'file' => 'video.theme.inc',
);
$theme['video_thumbnail'] = array(
'variables' => array(
'item' => NULL,
'path' => NULL,
'video_style' => NULL,
'entity' => NULL,
'field' => NULL,
'instance' => NULL,
),
'file' => 'video.theme.inc',
);
$theme['video_widget'] = array(
'render element' => 'element',
'file' => 'video.theme.inc',
);
$theme['video_conversion_failed'] = array(
'variables' => array(),
'file' => 'video.theme.inc',
);
$theme['video_inprogress'] = array(
'variables' => array(),
'file' => 'video.theme.inc',
);
$path = drupal_get_path('module', 'video') . '/theme';
$players = video_video_players();
foreach ($players as $tpl => $value) {
$theme[$tpl] = array(
'variables' => array(
'video' => NULL,
'themed_output' => NULL,
),
'template' => str_replace('_', '-', $tpl),
'path' => $path,
);
}
$theme['video_flv'] = array(
'variables' => array(
'video' => NULL,
),
'file' => 'video.theme.inc',
);
$theme['video_html5'] = array(
'variables' => array(
'video' => NULL,
),
'file' => 'video.theme.inc',
);
return $theme;
}
function video_cron() {
if (variable_get('video_cron', TRUE)) {
module_load_include('inc', 'video', 'includes/conversion');
$video_conversion = new video_conversion();
if ($videos = $video_conversion
->load_job_queue()) {
$queue = DrupalQueue::get('video_queue');
foreach ($videos as $video) {
if ($queue
->createItem($video)) {
$video_conversion
->change_status($video->vid, VIDEO_RENDERING_INQUEUE);
}
}
}
}
}
function video_cron_queue_info() {
$queues['video_queue'] = array(
'worker callback' => 'video_queue_process',
'time' => variable_get('video_queue_timeout', 90),
);
return $queues;
}
function video_queue_process($video) {
module_load_include('inc', 'video', 'includes/conversion');
$video_conversion = new video_conversion();
$video_conversion
->process($video);
}
function video_thumb_process(&$element, &$form_state) {
$file = $element['#value'];
$delta = $file['fid'];
$field = field_widget_field($element, $form_state);
$instance = field_widget_instance($element, $form_state);
$settings = $instance['widget']['settings'];
$gen_fail = FALSE;
if (isset($element['preview']) && $file['fid'] != 0) {
if (in_array($field['settings']['autothumbnail'], array(
'auto',
'auto_fallback',
))) {
$default_thumb = array();
$transcoder = new video_transcoder();
if ($thumbs = $transcoder
->generate_thumbnails($file)) {
$default_thumb = array_rand($thumbs);
if (!empty($thumbs)) {
foreach ($thumbs as $fid => $img) {
$thumbss[$img->fid] = theme('image_style', array(
'style_name' => $field['settings']['preview_video_thumb_style'],
'path' => $img->uri,
));
}
}
}
if (!empty($thumbss)) {
$element['thumbnail'] = array(
'#type' => 'radios',
'#title' => t('Video thumbnails'),
'#element_validate' => array(
'video_thumbnail_validate',
),
'#options' => $thumbss,
'#default_value' => !empty($file['thumbnail']) ? $file['thumbnail'] : $thumbs[$default_thumb]->fid,
'#weight' => 10,
'#attributes' => array(
'class' => array(
'video-thumbnails',
),
'onchange' => 'videoftp_thumbnail_change()',
'rel' => 'video_large_thumbnail-' . $delta,
),
);
}
else {
$gen_fail = TRUE;
}
}
if (!empty($gen_fail) && $field['settings']['autothumbnail'] == 'auto_fallback' || $field['settings']['autothumbnail'] == 'manual_upload') {
$element['thumbnail'] = array(
'#title' => t('Video thumbnail'),
'#type' => 'managed_file',
'#description' => t('The uploaded image will be used as video thumbnail on this video.'),
'#default_value' => !empty($file['thumbnail']['fid']) && is_integer($file['thumbnail']['fid']) ? $file['thumbnail']['fid'] : NULL,
'#upload_location' => file_default_scheme() . '://' . variable_get('video_thumb_path', 'videos/thumbnails') . '/' . $file['fid'],
);
}
if ($field['settings']['autothumbnail'] == 'no') {
$element['thumbnail'] = array(
'#type' => 'value',
'#value' => NULL,
);
}
if (isset($file['thumbnail']) && !empty($file['thumbnail'])) {
$large_thumb = file_load($file['thumbnail']);
}
elseif (!empty($field['settings']['default_video_thumbnail']['fid'])) {
$large_thumb = file_load($field['settings']['default_video_thumbnail']['fid']);
}
else {
}
if (!empty($large_thumb)) {
$element['preview']['#suffix'] = '<div class="video_large_thumbnail-' . $delta . '">' . theme('image_style', array(
'style_name' => $field['settings']['preview_video_thumb_style'],
'path' => $large_thumb->uri,
)) . '</div>';
}
}
}
function video_file_delete($file) {
db_delete('video_files')
->condition('fid', $file->fid)
->execute();
}
function video_web_extensions($ext) {
$extensions = array_filter(explode(' ', $ext));
$web_extensions = array(
'mov',
'mp4',
'3gp',
'3g2',
'mpg',
'mpeg',
'divx',
'mkv',
'rm',
'flv',
'f4v',
'swf',
'dir',
'dcr',
'asf',
'wmv',
'avi',
'mpg',
'mpeg',
'ogg',
'ogv',
'webm',
);
if (count(array_diff($extensions, $web_extensions))) {
return FALSE;
}
return TRUE;
}
function video_views_api() {
return array(
'api' => 2.0,
'path' => drupal_get_path('module', 'video') . '/views',
);
}
function video_widget_element_settings(&$element, &$form_state) {
$file = $element['#value'];
$delta = $element['#delta'];
$field = field_widget_field($element, $form_state);
$instance = field_widget_instance($element, $form_state);
$settings = $instance['settings'];
$default_dimensions = user_access('override player dimensions');
$description = t('Set your video dimensions. This will create your player with these dimensions.');
$dimensions = $settings['default_dimensions'];
$player_dimensions = $settings['default_player_dimensions'];
$options = video_explode("\n", variable_get("video_metadata_dimensions", video_default_dimensions()));
if ($field['settings']['autoconversion'] && isset($element['preview']) && $file['fid'] != 0 && $default_dimensions) {
$file_object = file_load($file['fid']);
$video_info = _video_dimensions_options($options, drupal_realpath($file_object->uri));
$description = t('Set your video dimensions. This will create your player
and transcode your video with these dimensions. Your video size is !size,
if you choose a higher resolution, this could cause video distortion.
You are shown dimensions that match your aspect ratio,
if you choose dimensions that do not match your ratio, we will pad your
video by adding black bars on either the top or bottom while maintaining
your videos original aspect ratio.', array(
'!size' => $video_info['width'] . 'x' . $video_info['height'],
));
foreach ($options as $key => $value) {
if (stristr($value, t('(Matches Resolution)')) == TRUE) {
$dimensions = $key;
break;
}
}
}
if (isset($file['dimensions']) && !empty($file['dimensions'])) {
$dimensions = $file['dimensions'];
}
if (isset($file['player_dimensions']) && !empty($file['player_dimensions'])) {
$player_dimensions = $file['player_dimensions'];
}
if ($field['settings']['autoconversion']) {
$element['dimensions'] = array(
'#type' => 'select',
'#title' => t('Dimensions for Video Transcoding'),
'#default_value' => $dimensions,
'#description' => $description,
'#options' => $options,
);
}
$element['player_dimensions'] = array(
'#type' => 'select',
'#title' => t('Dimensions for Video Player'),
'#default_value' => $player_dimensions,
'#description' => t('WxH of your video player.'),
'#options' => $options,
);
if (!$default_dimensions) {
$element['dimensions']['#type'] = 'value';
$element['dimensions']['#value'] = $dimensions;
$element['player_dimensions']['#type'] = 'value';
$element['player_dimensions']['#value'] = $player_dimensions;
}
if ($field['settings']['autoconversion']) {
module_load_include('inc', 'video', '/includes/conversion');
$video_conversion = new video_conversion();
$video = $video_conversion
->load_job($file['fid']);
if (user_access('re convert video') && isset($video->video_status) && ($video->video_status == VIDEO_RENDERING_COMPLETE || $video->video_status == VIDEO_RENDERING_FAILED)) {
$status = array(
VIDEO_RENDERING_COMPLETE => 'completed',
VIDEO_RENDERING_FAILED => 'failed',
);
$element['re_convert_video'] = array(
'#type' => 'checkbox',
'#title' => t('Video conversion has been <b>' . $status[$video->video_status] . '!</b>. Re-queue video?.'),
'#description' => t('This will re-convert your video to output formats when you save, or scheduling it for cron.'),
'#attributes' => array(
'class' => array(
'video-re-convert',
'video-' . $video->video_status,
),
),
);
}
if (user_access('bypass conversion video')) {
$element['bypass_autoconversion'] = array(
'#type' => 'checkbox',
'#title' => t('Bypass auto conversion'),
'#default_value' => isset($file['bypass_autoconversion']) ? $file['bypass_autoconversion'] : variable_get('video_bypass_conversion', FALSE),
'#description' => t('This will bypass your auto conversion of videos.'),
'#attributes' => array(
'class' => array(
'video-bypass-auto-conversion',
),
),
);
}
elseif (variable_get('video_bypass_conversion', FALSE)) {
$element['bypass_autoconversion'] = array(
'#type' => 'value',
'#value' => variable_get('video_bypass_conversion', FALSE),
);
}
$convert = isset($file['convert_video_on_save']) ? $file['convert_video_on_save'] : variable_get('video_convert_on_save', FALSE);
if (user_access('convert on submission')) {
$element['convert_video_on_save'] = array(
'#type' => 'checkbox',
'#title' => t('Convert video on save'),
'#default_value' => $convert,
'#description' => t('This will convert your video to flv format when you save, instead of scheduling it for cron.'),
'#attributes' => array(
'class' => array(
'video-convert-video-on-save',
),
),
);
}
elseif (variable_get('video_convert_on_save', FALSE)) {
$element['convert_video_on_save'] = array(
'#type' => 'value',
'#value' => variable_get('video_convert_on_save', FALSE),
);
}
}
$default_thumb = isset($file['use_default_video_thumb']) ? $file['use_default_video_thumb'] : variable_get('video_use_default_thumb', FALSE);
if (user_access('use default thumb')) {
$element['use_default_video_thumb'] = array(
'#type' => 'checkbox',
'#title' => t('Use the default thumbnail for this video?'),
'#default_value' => $default_thumb,
'#description' => t('This will set a flag for this video to use the default video thumbnail when outputed..'),
'#attributes' => array(
'class' => array(
'video-use-default-video-thumb',
),
),
);
if ($default_thumb) {
$element['use_default_video_thumb']['#attributes']['checked'] = 'checked';
}
}
else {
$element['use_default_video_thumb'] = array(
'#type' => 'value',
'#value' => $default_thumb,
);
}
}
function _video_dimensions_options(&$options, $video) {
$aspect_ratio = _video_aspect_ratio($video);
foreach ($options as $key => $value) {
$wxh = explode('x', $value);
if ($aspect_ratio['width'] == $wxh[0] && $aspect_ratio['height'] == $wxh[1]) {
$options[$key] = $value . ' ' . t('(Matches Resolution)');
}
else {
$ratio = number_format($wxh[0] / $wxh[1], 4);
if ($ratio == $aspect_ratio['ratio']) {
$options[$key] = $value . ' ' . t('(Matches Ratio)');
}
}
}
return $aspect_ratio;
}
function _video_aspect_ratio($video) {
$transcoder = new video_transcoder();
$wxh = $transcoder
->get_dimensions($video);
$width = $wxh['width'];
$height = $wxh['height'];
if (!$width || !$height) {
watchdog('video_conversion', 'We could not determine the height and width of the video: ' . $video, array(), WATCHDOG_DEBUG);
return;
}
$ratio = number_format($width / $height, 4);
$aspect_ratio = array(
'width' => $width,
'height' => $height,
'ratio' => $ratio,
);
return $aspect_ratio;
}
function video_video_extensions() {
$extensions = array(
'divx' => 'video_play_divx',
'mkv' => 'video_play_divx',
'mov' => 'video_play_quicktime',
'3gp' => 'video_play_quicktime',
'3g2' => 'video_play_quicktime',
'mp4' => 'video_play_quicktime',
'rm' => 'video_play_realmedia',
'f4v' => 'video_play_flv',
'flv' => 'video_play_flv',
'swf' => 'video_play_flash',
'dir' => 'video_play_dcr',
'dcr' => 'video_play_dcr',
'asf' => 'video_play_windowsmedia',
'wmv' => 'video_play_windowsmedia',
'avi' => 'video_play_windowsmedia',
'mpg' => 'video_play_windowsmedia',
'mpeg' => 'video_play_windowsmedia',
'ogg' => 'video_play_theora',
'ogv' => 'video_play_theora',
'webm' => 'video_play_theora',
);
return $extensions;
}
function video_video_players() {
$players = array(
'video_play_html5' => t('HTML5 Player'),
'video_play_divx' => t('Divx Player'),
'video_play_quicktime' => t('Quicktime'),
'video_play_realmedia' => t('Real Media Player'),
'video_play_flv' => t('FLV Flash Players'),
'video_play_flash' => t('SWF Flash Player'),
'video_play_dcr' => t('Director/Shockwave'),
'video_play_windowsmedia' => t('Windows Media Player'),
'video_play_theora' => t('Theora Player'),
);
return $players;
}
function video_video_flv_players() {
$options = array();
if (module_exists('swftools')) {
$options['swftools'] = t('SWF Tools');
}
if (module_exists('flowplayer')) {
$options['flowplayer'] = t('Flowplayer');
}
return $options;
}
function video_video_html5_players() {
$options = array();
if (module_exists('videojs')) {
$options['videojs'] = t('VideoJS');
}
if (module_exists('video')) {
$options['video'] = t('Default HTML5');
}
return $options;
}
function video_default_instance_settings($widget) {
$form = array();
$form['default_dimensions'] = array(
'#type' => 'select',
'#title' => t('Default Video Resolution Dimensions'),
'#default_value' => !empty($widget['default_dimensions']) ? $widget['default_dimensions'] : '',
'#options' => video_explode("\n", variable_get("video_metadata_dimensions", video_default_dimensions())),
'#description' => t('Default transcoding resolution WIDTHxHEIGHT, in px, that FFMPEG will use to transcode your video files.'),
'#weight' => 15,
);
$form['default_player_dimensions'] = array(
'#type' => 'select',
'#title' => t('Default Video Player Dimensions'),
'#default_value' => !empty($widget['default_player_dimensions']) ? $widget['default_player_dimensions'] : '',
'#options' => video_explode("\n", variable_get("video_metadata_dimensions", video_default_dimensions())),
'#description' => t('Default player WIDTHxHEIGHT in px. This is your actual player dimensions that your video will be playing in.'),
'#weight' => 16,
);
return $form;
}
function video_default_field_settings($settings) {
$form = array();
$form['autoconversion'] = array(
'#type' => 'checkbox',
'#title' => t('Enable video conversion.'),
'#description' => t('Use ffmpeg(Default) or Zencoder to automatically convert videos to web compatible types eg. FLV, Please make sure to configure your transcoder settings.'),
'#default_value' => isset($settings['autoconversion']) ? $settings['autoconversion'] : '',
'#weight' => 17,
);
$thumb_options = array(
'auto' => 'Automatically generate thumbnails',
'auto_fallback' => 'Automatically generate thumbnails, with fallback to manual upload if fail',
'manual_upload' => 'Manually upload a thumbnail',
'no' => 'Don\'t create thumbnail',
);
$form['autothumbnail'] = array(
'#type' => 'radios',
'#title' => t('Thumbnail Generation'),
'#options' => $thumb_options,
'#description' => t('To use ffmpeg(Default) to create thumbnails, Please make sure to configure your transcoder settings before using ffmpeg to create thumbnails.'),
'#default_value' => isset($settings['autothumbnail']) ? $settings['autothumbnail'] : 'no',
'#weight' => 18,
);
$form['default_video_thumbnail'] = array(
'#title' => t('Default video thumbnail'),
'#type' => 'managed_file',
'#element_validate' => array(
'video_field_default_thumbnail_validate',
),
'#description' => t('If use default thumbnanil is selected, this image will be shown on display.'),
'#default_value' => !empty($settings['default_video_thumbnail']['fid']) ? $settings['default_video_thumbnail']['fid'] : '',
'#upload_location' => 'public://videos/thumbnails/default',
'#weight' => 19,
);
$form['preview_video_thumb_style'] = array(
'#title' => t('Preview thumbnail style'),
'#type' => 'select',
'#options' => image_style_options(FALSE),
'#empty_option' => '<' . t('no preview') . '>',
'#default_value' => !empty($settings['preview_video_thumb_style']) ? $settings['preview_video_thumb_style'] : '',
'#description' => t('The preview image will be shown while editing the content.'),
'#weight' => 20,
);
return $form;
}
function video_explode($delimeter, $dimensions) {
$options = array();
$values = explode($delimeter, $dimensions);
foreach ($values as $value) {
if (!empty($value) && video_format_right($value)) {
$options[trim($value)] = trim($value);
}
}
return $options;
}
function video_format_right($value) {
$format = explode("x", $value);
if (!isset($format[0]) || !is_numeric(trim($format[0]))) {
return FALSE;
}
if (!isset($format[1]) || !is_numeric(trim($format[1]))) {
return FALSE;
}
return TRUE;
}
function video_default_dimensions() {
return "176x144\n352x288\n704x576\n1408x1152\n128x96\n160x120\n320x240\n640x480\n800x600\n1024x768\n1600x1200\n2048x1024\n1280x1024\n2560x2048\n5120x4096\n852x480\n1366x768\n1600x1024\n1920x1200\n2560x1600\n3200x2048\n3840x2400\n6400x4096\n7680x4800\n320x200\n640x350\n852x480\n1280x720\n1920x1080\n640x360\n320x180";
}
function rmdirr($dir) {
if ($objs = glob($dir . "/*")) {
foreach ($objs as $obj) {
is_dir($obj) ? rmdirr($obj) : unlink($obj);
}
}
@rmdir($dir);
}
function video_features_api() {
return array(
'video' => array(
'name' => t('Video Presets'),
'default_hook' => 'video_default_presets',
'file' => drupal_get_path('module', 'video') . '/video.features.inc',
),
);
}
function video_file_download($uri) {
$path = file_uri_target($uri);
if (strpos($path, 'styles/') === 0) {
$args = explode('/', $path);
array_shift($args);
$style_name = array_shift($args);
array_shift($args);
$original_uri = file_uri_scheme($uri) . '://' . implode('/', $args);
if ($info = image_get_info($uri)) {
$headers = module_invoke_all('file_download', $original_uri);
if (!in_array(-1, $headers)) {
return array(
'Content-Type' => $info['mime_type'],
'Content-Length' => $info['file_size'],
'Expires' => gmdate(DATE_RFC1123, REQUEST_TIME + 1209600),
'Cache-Control' => 'max-age=1209600, private, must-revalidate',
);
}
}
return -1;
}
$files = file_load_multiple(array(), array(
'uri' => $uri,
));
if (count($files)) {
$file = reset($files);
if ($file->status) {
return file_file_download($uri, 'video');
}
}
}
function _video_object_to_array($data) {
if (is_array($data) || is_object($data)) {
$result = array();
foreach ($data as $key => $value) {
$result[$key] = _video_object_to_array($value);
}
return $result;
}
return $data;
}