video.module in Video 5
Same filename and directory in other branches
Display video in Quicktime MOV, Realmedia RM, Flash FLV & SWF, or Windows Media WMV formats.
@author Fabio Varesano <fvaresano at yahoo dot it> @desc last edit by Heshan Wanigasooriya <heshan at heidisoft dot com>
File
video.moduleView source
<?php
// ex: set tabstop=2 expandtab shiftwidth=2 softtabstop=2:
/**
* @file
* Display video in Quicktime MOV, Realmedia RM, Flash FLV & SWF,
* or Windows Media WMV formats.
*
* @author Fabio Varesano <fvaresano at yahoo dot it>
* @desc last edit by Heshan Wanigasooriya <heshan at heidisoft dot com>
*/
/**
* Let's include views logic if views module is enabled
*/
if (module_exists('views')) {
include drupal_get_path('module', 'video') . '/views_video.inc';
}
/********************************************************************
* General Hooks
********************************************************************/
/**
* Help hook
*
* @param $section
* string of the area of Drupal where help was requested
*
* @return
* string of help information
*/
function video_help($section = 'admin/help#video') {
switch ($section) {
case 'admin/help#video':
$output = '<p>' . t('The video module (4.7 or with backport patch to 4.6) allows users to post video content to their site. The emergence of portable phones with video capture capabilities has made video capture ubiquitous. Video logging, or <a href="%elink-en-wikipedia-org">vlogging</a> as a medium for personal video broadcasting has proven to be popular and is following the blogging, and podcasting phenomena\'s. Videos are useful for creative collaboration among community members. If community members can not meet in person videos of meetings are valuable for enhancing the interaction between community members.', array(
'%elink-en-wikipedia-org' => 'http://en.wikipedia.org/wiki/Vlog',
)) . '</p>';
$output .= '<p>' . t('The video module can be administered to flash player settings. There are a number of page and menu links which can be added to play and download video content on the site. Other configurable options include play and download counters. Multi-file downloads can also be configured under settings.') . '</p>';
$output .= t('<p>You can:</p>
<ul>
<li>Enable <em>most played videos</em>, <em>latest videos</em>, and <em>top videos</em> blocks at <a href="%admin-block">administer >> block</a>.</li>
<li>Create video posts at <a href="%node-add-video">create content >> video</a>.</li>
<li>Administer video module settings at <a href="%admin-settings-video">administer >> settings >> video</a>.</li>
</ul>
', array(
'%admin-block' => url('admin/settings/block'),
'%node-add-video' => url('node/add/video'),
'%admin-settings-video' => url('admin/content/video'),
));
$output .= '<p>' . t('For more information please read the configuration and customization handbook <a href="%video">Video page</a>.', array(
'%video' => 'http://www.drupal.org/handbook/modules/video/',
)) . '</p>';
return $output;
case 'admin/settings/modules#description':
return t('Allows video nodes.');
case 'node/add#video':
return t('Allows you to insert videos as nodes.');
case 'video/help':
// Get the video-type-specific help contents
$help_items = array();
return theme('item_list', module_invoke_all('v_help'));
}
}
/**
* Implementation of hook_menu().
*
* @param $may_cache
* boolean indicating whether cacheable menu items should be returned
*
* @return
* array of menu information
*/
function video_menu($may_cache) {
global $user;
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'video',
'title' => t('videos'),
'callback' => 'video_page',
'access' => user_access('access video'),
'type' => MENU_SUGGESTED_ITEM,
);
$items[] = array(
'path' => 'video/feed',
'title' => t('videos feed'),
'callback' => 'video_feed',
'access' => user_access('access video'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'node/add/video',
'title' => t('Video'),
'callback' => 'video_add',
'access' => user_access('create video'),
);
$items[] = array(
'path' => 'admin/settings/video',
'title' => t('Video'),
'description' => t('Configure different aspects of the video module and its plugins'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'video_settings_form',
),
'access' => user_access('administer video'),
'type' => MENU_NORMAL_ITEM,
);
}
else {
//If $may_cache is false.
if (arg(0) == 'node' && is_numeric(arg(1))) {
if ($node = node_load(arg(1)) and $node->type == 'video') {
//enable the download tab only if it is supported
if (video_support_download($node)) {
$menu_type = variable_get('video_displaydownloadmenutab', 1) ? MENU_LOCAL_TASK : MENU_CALLBACK;
$items[] = array(
'path' => 'node/' . $node->nid . '/download',
'title' => t('Download'),
'callback' => 'video_download',
'callback arguments' => array(
$node,
),
'access' => user_access('access video') && node_access('view', $node, $user->uid),
'weight' => 5,
'type' => $menu_type,
);
}
}
}
}
return $items;
}
/**
* Internal Drupal links hook
*
* @param $type
* string type of link to show
*
* @param $node
* object of node information
*
* @return
* array of link information
*/
function video_link($type, $node = NULL) {
$link = array();
// Node links for a video
if ($type == 'node' && $node->type == 'video' && $node->vidfile && user_access('access video')) {
//If the video is of type youtube and multi-file downloads aren't turned on don't show the download link.
if (!video_support_download($node) || $node->disable_multidownload == 1) {
$display_download_link = 0;
}
else {
$display_download_link = variable_get('video_displaydownloadlink', 1);
}
if ($display_download_link == 1) {
$link['video_download'] = array(
'title' => t('download'),
'href' => "node/{$node->nid}/download",
'attributes' => array(
'class' => 'outgoing',
'title' => t('download @link', array(
'@link' => $node->title,
)),
),
);
}
if (variable_get('video_displayplaytime', 1) && $node->playtime_seconds > 0) {
// hide the duration if the admin hided it or we don't have playtime informations
$link['playtime'] = array(
'title' => format_interval($node->playtime_seconds),
);
}
if (variable_get('video_displayfilesize', 1) && $node->size != 0) {
$link['size'] = array(
'title' => format_size($node->size),
);
}
if (variable_get('video_playcounter', 1) && user_access('view play counter')) {
$link['play_counter'] = array(
'title' => format_plural($node->play_counter, '1 play', '@count plays'),
);
}
if (variable_get('video_downloadcounter', 1) && user_access('view download counter') && video_support_download($node)) {
$link['download_counter'] = array(
'title' => format_plural($node->download_counter, '1 download', '@count downloads'),
);
}
return $link;
}
return array();
}
/**
* Displays a Drupal page containing recently added videos
*
* @return
* string HTML output
*/
function video_page() {
$output = '';
if (arg(1) != 'help') {
//We are not reading help so output a list of recent video nodes.
$result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'video' AND n.status = 1 ORDER BY n.created DESC"), variable_get('default_nodes_main', 10));
while ($node = db_fetch_object($result)) {
$output .= node_view(node_load($node->nid), 1);
}
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
// adds feed icon and link
drupal_add_link(array(
'rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => variable_get('site_name', 'drupal') . ' ' . t('videos'),
'href' => url('video/feed/'),
));
$output .= '<br />' . theme('feed_icon', url('video/feed'));
}
return $output;
}
/**
* Generate an RSS feed for videos
*
* @return
* feed
*/
function video_feed() {
$channel = array(
'title' => variable_get('site_name', 'drupal') . ' ' . t('videos'),
'description' => t('Latest videos on') . ' ' . variable_get('site_name', 'drupal'),
'link' => url('video', NULL, NULL, TRUE),
);
$result = db_query('SELECT n.nid FROM {node} n WHERE n.type = "video" AND n.status = 1 ORDER BY n.created DESC');
node_feed($result, $channel);
}
/**
* Permissions hook
*
* @return
* array of permissions
*/
function video_perm() {
$array = array(
'create video',
'access video',
'administer video',
'play video',
'download video',
'view play counter',
'view download counter',
'edit own video',
'edit all video nodes',
);
return $array;
}
/**
* Settings Hook
*
* @return
* string of form content or error message
*/
function video_settings_form() {
global $base_url;
$form = array();
$form['menu'] = array(
'#type' => 'fieldset',
'#title' => t('General behavior'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$vtypes = video_get_types_infos();
if ($vtypes) {
// no vtype available
$video_types = array();
foreach ($vtypes as $vtype => $info) {
$video_types[$vtype] = $info['#name'];
}
$video_types[0] = t('No default type');
$form['menu']['video_default_video_type'] = array(
'#type' => 'select',
'#title' => t('Choose default video type'),
'#default_value' => variable_get('video_default_video_type', 0),
'#description' => t('For installations that have more than one video type available, this sets the default video type when a user visits node/add/video'),
'#options' => $video_types,
);
}
$form['menu']['video_displaydownloadmenutab'] = array(
'#type' => 'checkbox',
'#title' => t('Display download menu tab'),
'#default_value' => variable_get('video_displaydownloadmenutab', 1),
'#description' => t('Toggle display of menu tab to download video from the node page.'),
);
$form['menu']['video_show_help_text'] = array(
'#type' => 'checkbox',
'#title' => t('Show help text'),
'#default_value' => variable_get('video_show_help_text', TRUE),
'#description' => t('Enabling this may help users play the video.'),
);
$form['menu']['video_displaydownloadlink'] = array(
'#type' => 'checkbox',
'#title' => t('Display download link'),
'#default_value' => variable_get('video_displaydownloadlink', 1),
'#description' => t('Toggle display of "download" link (below the node content in most themes).'),
);
$form['menu']['video_displayplaytime'] = array(
'#type' => 'checkbox',
'#title' => t('Display playtime'),
'#default_value' => variable_get('video_displayplaytime', 1),
'#description' => t('Toggle the display of the playtime for a video.'),
);
$form['menu']['video_displayfilesize'] = array(
'#type' => 'checkbox',
'#title' => t('Display filesize'),
'#default_value' => variable_get('video_displayfilesize', 1),
'#description' => t('Toggle the display of the filesize for a video.'),
);
$form['resolutions'] = array(
'#type' => 'fieldset',
'#title' => t('Video resolutions'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['resolutions']["video_resolution_width"] = array(
'#type' => 'textfield',
'#title' => t("Default width"),
'#default_value' => variable_get("video_resolution_width", 400),
'#description' => t('The width which will be used to scale video during playing. This let all videos on the website look the same'),
);
$i = 1;
while ($i <= 4) {
$form['resolutions']["video_resolution_{$i}_name"] = array(
'#type' => 'textfield',
'#title' => t("Resolution {$i} name"),
'#default_value' => variable_get("video_resolution_{$i}_name", ''),
);
$form['resolutions']["video_resolution_{$i}_value"] = array(
'#type' => 'textfield',
'#title' => t("Resolution {$i} value"),
'#default_value' => variable_get("video_resolution_{$i}_value", ''),
'#description' => t('The resolution: two numbers representing width and height separated by an "x"'),
);
$i++;
}
// statistics stuff
$form['counters'] = array(
'#type' => 'fieldset',
'#title' => t('Statistics counters'),
'#description' => t('To allow users to view counters visit: ') . l(t('access control'), 'admin/access'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['counters']['video_playcounter'] = array(
'#type' => 'checkbox',
'#title' => t('Count play hits'),
'#default_value' => variable_get('video_playcounter', 1),
'#description' => t('Counts a hit everytime someone views the play page.'),
);
$form['counters']['video_downloadcounter'] = array(
'#type' => 'checkbox',
'#title' => t('Count downloads'),
'#default_value' => variable_get('video_downloadcounter', 1),
'#description' => t('Counts a hit everytime someone downloads a video.'),
);
$form['flash'] = array(
'#type' => 'fieldset',
'#title' => t('Flash settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['flash']['video_flvplayerloader'] = array(
'#type' => 'textfield',
'#title' => t('Filename of Flash loader'),
'#default_value' => variable_get('video_flvplayerloader', 'FlowPlayer.swf'),
'#description' => t('The name of the Shockwave file that manages loading the FLV movie. This is relative to the website root.'),
);
$form['ogg'] = array(
'#type' => 'fieldset',
'#title' => t('Ogg Theora settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['ogg']['video_cortado'] = array(
'#type' => 'textfield',
'#title' => t('Filename of Cortado Java Applet'),
'#default_value' => variable_get('video_cortado', $base_url . '/cortado.jar'),
'#description' => t('The path to the Cortado Applet to play Ogg Theora Files.'),
);
return system_settings_form($form);
}
/**
* Form API callback to validate the upload settings form.
*
* Keeps the use from showing the play tab or the play link
* if they have chosen to display the video in the node body.
*
* @param $form_id
* The identifier of the form
*
* @param $form_values
* form values from the settings page
*
*/
function video_settings_form_validate($form_id, $form_values) {
//print_r($form_values); die;
// if admin set a name for a resolution he also have to set its value
while ($i <= 4) {
if ($form_values["video_resolution_{$i}_name"] != '' && $form_values["video_resolution_{$i}_value"] == '') {
form_set_error("video_resolution_{$i}_value", t('You have to set a value for resolution %res_num if you want to enable it.', array(
'%res_num' => $i,
)));
}
if ($form_values["video_resolution_{$i}_value"] != '' && !preg_match('/^[0-9]{2,4}x[0-9]{2,4}$/', $form_values["video_resolution_{$i}_value"])) {
// check valid resolution value
form_set_error("video_resolution_{$i}_value", t('You have to set valid value for resolution %res_num if you want to enable it. A valid value is 400x300', array(
'%res_num' => $i,
)));
}
$i++;
}
// for future use
}
/******************************************************************************
* Node Hooks
******************************************************************************/
/**
* Implementation of _node_info().
*
* @return
* array
*/
function video_node_info() {
return array(
'video' => array(
'name' => t('Video'),
'module' => 'video',
'description' => t('Allow a variety of video formats to be posted as nodes in your site'),
),
);
}
/**
* access hook
*/
function video_access($op, $node) {
global $user;
if ($op == 'create') {
return user_access('create video');
}
if ($op == 'update' || $op == 'delete') {
return user_access('edit own video') && $user->uid == $node->uid || user_access('edit all video nodes');
}
}
/**
* Implementation of hook_nodeapi().
* We use this to append <enclosure> tags to the RSS feeds Drupal generates.
*/
function video_nodeapi($node, $op, $arg) {
switch ($op) {
case 'rss item':
if ($node->type == 'video') {
// RSS Enclosure http://cyber.law.harvard.edu/rss/rss.html#ltenclosuregtSubelementOfLtitemgt
$attributes['url'] = _video_get_fileurl($node->vidfile);
$attributes['length'] = $node->size;
$mime_type = _video_get_mime_type($node);
if ($mime_type) {
$attributes['type'] = $mime_type;
$enclosure = array(
'key' => 'enclosure',
'attributes' => $attributes,
);
}
// MRSS media:content http://search.yahoo.com/mrss
$media['url'] = $attributes['url'];
if ($attributes['length'] > 1) {
$media['fileSize'] = $attributes['length'];
}
if ($mime_type) {
$media['type'] = $mime_type;
}
if (isset($node->playtime_seconds) && $node->playtime_seconds > 0) {
$media['duration'] = $node->playtime_seconds;
}
if (isset($node->video_bitrate) && $node->video_bitrate > 0) {
$media['bitrate'] = $node->video_bitrate;
}
if (isset($node->videox) && isset($node->videoy) && $node->videox > 0) {
$media['width'] = $node->videox;
$media['height'] = $node->videoy;
}
if (isset($node->audio_sampling_rate) && $node->audio_sampling_rate > 0) {
$media['samplingrate'] = $node->audio_sampling_rate;
}
$mrss = array(
'key' => 'media:content',
'attributes' => $media,
);
// work around for http://drupal.org/node/157709
static $been_here = FALSE;
if (!$been_here) {
$mrss['namespace'] = array(
'xmlns:media="http://search.yahoo.com/mrss/"',
);
$been_here = TRUE;
}
}
return array(
$enclosure,
$mrss,
);
case 'revision delete':
db_query('DELETE FROM {video} WHERE vid = %d', $node->vid);
break;
}
}
/**
* Create video submission page. Let the user select the actived video types
* or display the video form for the selected video type
*/
function video_add() {
global $user;
$edit = isset($_POST['edit']) ? $_POST['edit'] : '';
// If a video type has been specified, validate its existence.
$vtypes = video_get_types();
if (arg(3) && in_array(arg(3), $vtypes)) {
// is a valid video type
$type = arg(3);
// Initialize settings:
$node = (object) array(
'uid' => $user->uid,
'name' => $user->name,
'type' => 'video',
'vtype' => $type,
);
$output = drupal_get_form('video_node_form', $node);
drupal_set_title(t('Submit %name video', array(
'%name' => $type,
)));
}
else {
if (count($vtypes) == 1) {
// only one vtype active. redirect the user to the active type form
// Initialize settings:
$node = (object) array(
'uid' => $user->uid,
'name' => $user->name,
'type' => 'video',
'vtype' => $vtypes[0],
);
$output = drupal_get_form('video_node_form', $node);
drupal_set_title(t('Submit %name video', array(
'%name' => $vtypes[0],
)));
}
else {
if ($vtype = variable_get('video_default_video_type', 0)) {
// Initialize settings:
$node = (object) array(
'uid' => $user->uid,
'name' => $user->name,
'type' => 'video',
'vtype' => $vtype,
);
$output = drupal_get_form('video_node_form', $node);
drupal_set_title(t('Submit %name video', array(
'%name' => $vtype,
)));
}
else {
$output = video_types_page();
}
}
}
return $output;
}
/**
* Display a video types selection page
*/
function video_types_page() {
drupal_set_title(t('Submit Video'));
// we have to set a titl ebecause the node module will not do it for us as we are using a callback video_add()
$vtypes = video_get_types_infos();
if (!$vtypes) {
// no vtype available
return t('There are no Video types enabled.');
}
else {
$items = array();
foreach ($vtypes as $vtype => $infos) {
$out = '<dt>' . l($infos['#name'], "node/add/video/{$vtype}", array(
'title' => t('Add a !s.', array(
'!s' => $infos['#name'],
)),
)) . '</dt>';
$out .= '<dd>' . $infos['#description'] . '</dd>';
$items[$vtype] = $out;
}
// let's order by type name
ksort($items);
return t('Choose from the following available video types:') . '<dl>' . implode('', $items) . '</dl>';
}
}
/**
* Return an array containing enabled Video Types
*/
function video_get_types() {
return array_keys(video_get_types_infos());
}
/**
* Return an array containing informations on enabled Video Types
*/
function video_get_types_infos() {
static $infos = NULL;
if (!is_array($infos)) {
$infos = module_invoke_all('v_info');
}
return $infos;
}
/**
* Return the informations for a given video type
*/
function video_get_type_info($type) {
return module_invoke('video_' . $type, 'v_info');
}
/**
* Return true if a given video type is downloadable
*/
function video_support_download($node) {
$info = video_get_type_info($node->vtype);
return $info[$node->vtype]['#downloadable'];
}
/**
* Hook, displays the contents of the node form page for creating and editing nodes.
*
* @param $node
* object
*
* @return
* string value of form content
*/
function video_form($node) {
//We must unserialize the array for display in the forms.
if ($node->serial_data) {
$node->serial_data = unserialize($node->serialized_data);
}
$form = array();
// default node stuff
$type = node_get_types('type', $node);
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#size' => 60,
'#maxlength' => 128,
'#required' => TRUE,
'#default_value' => $node->title,
'#weight' => -20,
);
if ($type->has_body) {
$form['body_filter']['body'] = array(
'#type' => 'textarea',
'#title' => check_plain($type->body_label),
'#required' => $type->min_word_count > 0,
'#rows' => 10,
'#default_value' => $node->body,
);
$form['body_filter']['format'] = filter_form($node->format);
}
// set an hidden field to store video type
$form['vtype'] = array(
'#type' => 'hidden',
'#value' => $node->vtype,
);
$form['video'] = array(
'#type' => 'fieldset',
'#title' => t('Video Information'),
'#weight' => -19,
);
if (!video_support_autoresolution($node)) {
// this vtype doesn't support autoresolution
// let's display the resolution selection
$form['video']['vresolution'] = array(
'#type' => 'select',
'#title' => t('Resolution'),
'#description' => t("Select the approriate resolution (aspect ratio) for your video.<br />If you don't know what to choose then the default value will probably be ok for you."),
'#options' => _video_get_resolution_options(),
'#default_value' => _video_get_resolution_selected_option($node),
'#required' => true,
);
}
if (!video_support_autoplaytime($node)) {
// this vtype doesn't support autoplaytime
$form['video']['playtime'] = array(
'#type' => 'fieldset',
'#title' => t('Playtime'),
'#collapsible' => true,
'#collapsed' => $node->playtime_seconds ? false : true,
// display expanded if we have values inserted by the user
'#description' => t('Insert here the duration of the video.<br />Values may be entered in excess of their normal "clock maximum" (the seconds field may be 3600 to represent 1 hour), however each value will be summed for a total of all three.'),
);
$playtime = _video_sec2hms($node->playtime_seconds);
$form['video']['playtime']['playtime_hours'] = array(
'#type' => 'textfield',
'#title' => t('Hours'),
'#size' => 11,
'#maxlength' => 11,
'#default_value' => $playtime['hours'],
);
$form['video']['playtime']['playtime_minutes'] = array(
'#type' => 'textfield',
'#title' => t('Minutes'),
'#size' => 11,
'#maxlength' => 11,
'#default_value' => $playtime['minutes'],
);
$form['video']['playtime']['playtime_seconds'] = array(
'#type' => 'textfield',
'#title' => t('Seconds'),
'#required' => FALSE,
'#size' => 11,
'#maxlength' => 11,
'#default_value' => $playtime['seconds'],
);
}
// Get the video-type-specific bits.
$form = module_invoke('video_' . $node->vtype, 'v_form', $node, $form);
return $form;
}
/**
* Implementation of hook_validate
*/
function video_validate($node) {
if (!video_support_autoresolution($node) || $node->vresolution) {
// we have some resolution value
// form api checked for good values of vresolution
if (variable_get("video_{$node->vresolution}_value", '') == '') {
}
}
module_invoke('video_' . $node->vtype, 'v_validate', $node);
}
/**
* Implementation of hook submit
*/
function video_submit(&$node) {
if (video_support_autoresolution($node)) {
// vtype support autoresolution getting
$xy = module_invoke('video_' . $node->vtype, 'v_auto_resolution', $node);
if ($xy) {
$node->videox = $xy[0];
$node->videoy = $xy[1];
}
}
else {
// we should have a good value (checked by Form API)
if ($node->vresolution) {
$res = explode('x', variable_get('video_resolution_' . $node->vresolution . '_value', ''));
$node->videox = $res[0];
$node->videoy = $res[1];
}
}
if (video_support_autoplaytime($node)) {
// vtype support auto playtime
$node->playtime_seconds = module_invoke('video_' . $node->vtype, 'v_auto_playtime', $node);
}
else {
// vtype does not support auto_playtime
$node->playtime_seconds += $node->playtime_hours * 3600 + $node->playtime_minutes * 60;
}
}
/**
* Implementation of hook_insert.
* Create video record in the video table
*
* @return
* TRUE on success, FALSE on error
*/
function video_insert($node) {
$node->serialized_data = serialize($node->serial_data);
//Serialize the data for insertion into the database.
return db_query("INSERT INTO {video} (vid, nid, vtype, vidfile, size, videox, videoy, video_bitrate, audio_bitrate, audio_sampling_rate, audio_channels, playtime_seconds, disable_multidownload, download_folder, use_play_folder, serialized_data) VALUES (%d, %d, '%s', '%s', %d, %d, %d, %d, %d, %d, '%s', %d, %d, '%s', %d, '%s')", $node->vid, $node->nid, $node->vtype, $node->vidfile, $node->size, $node->videox, $node->videoy, $node->video_bitrate, $node->audio_bitrate, $node->audio_sampling_rate, $node->audio_channels, $node->playtime_seconds, $node->disable_multidownload, $node->download_folder, $node->use_play_folder, $node->serialized_data);
}
/**
* Hook
*
* @return
* TRUE on success, FALSE on error
*/
function video_update($node) {
if ($node->revision) {
//If a new node revision is being added then insert a new row.
return video_insert($node);
}
else {
$node->serialized_data = serialize($node->serial_data);
//Serialize the data for insertion into the database.
return db_query("UPDATE {video} SET vidfile='%s', size=%d, videox=%d, videoy=%d, video_bitrate=%d, audio_bitrate=%d, audio_sampling_rate=%d, audio_channels='%s', playtime_seconds=%d, disable_multidownload=%d, download_folder='%s', use_play_folder=%d, serialized_data='%s' WHERE vid = %d", $node->vidfile, $node->size, $node->videox, $node->videoy, $node->video_bitrate, $node->audio_bitrate, $node->audio_sampling_rate, $node->audio_channels, $node->playtime_seconds, $node->disable_multidownload, $node->download_folder, $node->use_play_folder, $node->serialized_data, $node->vid);
}
}
/**
* Implementation of hook_delete
*/
function video_delete($node) {
db_query("DELETE FROM {video} WHERE nid = %d", $node->nid);
}
/**
* Implementation of hook_load()
*
* @param $node
* object or boolean FALSE on error
*/
function video_load($node) {
if (is_numeric($node->vid)) {
$node = db_fetch_object(db_query("SELECT * FROM {video} WHERE vid = %d", $node->vid));
// load serialized data for plug-ins
$node->serial_data = unserialize($node->serialized_data);
return $node;
}
else {
return false;
}
}
/**
* Implementation of hook_view().
*/
function video_view(&$node, $teaser = FALSE, $page = FALSE) {
// include the video css file
drupal_add_css(drupal_get_path('module', 'video') . '/video.css');
//Run the body through the standard filters.
$node = node_prepare($node, $teaser);
// theme the teaser
$node->teaser = theme('video_teaser', $node, $teaser, $page);
// if we are viewing the page, run the body through the theme
if ($page) {
$output = '';
if (user_access('play video')) {
$node->content['video_player'] = array(
'#value' => theme('video_player', $node),
'#weight' => -1,
);
}
else {
$output .= l(t('login'), "user/login", array(
'class' => 'outgoing',
'title' => t('login to your account'),
));
$output .= ' ' . t('or') . ' ';
$output .= l(t('register'), "user/register", array(
'class' => 'outgoing',
'title' => t('create a new account'),
));
$output .= ' ' . t('to play video');
$node->content['video_player'] = array(
'#value' => $output,
'#weight' => -1,
);
}
}
return $node;
}
/********************************************************************
* Block display functions
********************************************************************/
/**
* Hook block. Does all the interaction with the drupal block system. Uses video_block_list() for DB queries.
*
* @param $op
* string type of block
*
* @param $delta
* integer 0 for latest, 1 for played+downloaded, 2 for most played, 3 for most downloaded.
*
* @param $edit
* array holds the data submitted by the configure forms.
*
* @return
* array
*/
function video_block($op = 'list', $delta = 0, $edit = array()) {
if ($op == 'list') {
$blocks[0]['info'] = t('Latest videos');
$blocks[1]['info'] = t('Top videos');
$blocks[2]['info'] = t('Most played videos');
$blocks[3]['info'] = t('Most downloaded');
$blocks[4]['info'] = t('Random video');
return $blocks;
}
else {
if ($op == 'view') {
switch ($delta) {
case 0:
return array(
'subject' => variable_get('video_block_title_0', t('Latest videos')),
'content' => video_block_list($delta),
);
case 1:
return array(
'subject' => variable_get('video_block_title_1', t('Top videos')),
'content' => video_block_list($delta),
);
case 2:
return array(
'subject' => variable_get('video_block_title_2', t('Most played videos')),
'content' => video_block_list($delta),
);
case 3:
return array(
'subject' => variable_get('video_block_title_3', t('Most downloaded')),
'content' => video_block_list($delta),
);
case 4:
return array(
'subject' => variable_get('video_block_title_4', t('Random video')),
'content' => video_block_list($delta),
);
}
}
else {
if ($op == 'configure') {
switch ($delta) {
//Get the default title of the block incase the variable is not set yet.
case 0:
$default_title = t('Latest videos');
break;
case 1:
$default_title = t('Top videos');
break;
case 2:
$default_title = t('Most played videos');
break;
case 3:
$default_title = t('Most downloaded');
break;
case 4:
$default_title = t('Random video');
}
$form['video_block_title'] = array(
'#type' => 'textfield',
'#title' => t('Block display title'),
'#default_value' => variable_get("video_block_title_{$delta}", $default_title),
);
$form['video_block_limit'] = array(
'#type' => 'select',
'#title' => t('Number of videos to list in block'),
'#default_value' => variable_get("video_block_limit_{$delta}", 10),
'#options' => drupal_map_assoc(array(
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
)),
);
return $form;
}
else {
if ($op == 'save') {
variable_set("video_block_title_{$delta}", $edit['video_block_title']);
variable_set("video_block_limit_{$delta}", $edit['video_block_limit']);
}
}
}
}
}
/**
* Query DB for block content
*
* @param $delta
* int 0, 1, 2, or 3. Determines which type of block is being accessed.
*
* @return
* string HTML content for a block
*/
function video_block_list($delta = 0) {
$count = variable_get("video_block_limit_{$delta}", 10);
switch ($delta) {
case 0:
$orderby = 'n.created';
break;
case 1:
$orderby = 'v.download_counter + v.play_counter';
break;
case 2:
$orderby = 'v.play_counter';
break;
case 3:
$orderby = 'v.download_counter';
break;
case 4:
$count = 1;
$orderby = 'RAND()';
break;
}
return node_title_list(db_query_range(db_rewrite_sql("SELECT n.nid, n.title, {$orderby} FROM {node} n INNER JOIN {video} v ON n.vid = v.vid WHERE n.type = 'video' AND n.status = 1 AND n.moderate = 0 ORDER BY {$orderby} DESC"), 0, $count));
}
/****************************************************
* Menu callback functions
****************************************************/
/**
* Redirects to download the video file.
*/
function video_download($node) {
// $node as been loaded by video_menu
if ($node) {
if (video_support_download($node) && _video_allow_download($node)) {
//Make sure the video type is not youtube before downloading.
_video_download_goto($node);
}
else {
//If video is type youtube then it can't be downloaded.
drupal_set_message(t('There are no files to download for this video.'), 'error');
print theme('page', '');
}
}
else {
drupal_not_found();
}
}
/**
* Return true if the video is downloadable, false otherwise
*/
function _video_allow_download($node) {
// TODO: now videos are downloadable by default. why not implementing a feature to let users choose if they want their videos to be downloadable?
return true;
}
/**
* Theme the teaser
*
* This is just in place for site admins and theme developers
* who need to adjust how the teaser is themed.
*
* @param $node
* The node to be displayed.
* @param $teaser
* Whether we are to generate a "teaser" or summary of the node, rather than display the whole thing.
* @param $page
* Whether the node is being displayed as a standalone page. If this is TRUE, the node title should not be displayed, as it will be printed automatically by the theme system. Also, the module may choose to alter the default breadcrumb trail in this case.
*
* @return
* html
*/
function theme_video_teaser($node, $teaser = FALSE, $page = FALSE) {
return $node->teaser;
}
/**
* theme the view of the page to include the video
* assumes that body was put through prepare in hook_view
*
* @param $node
* The node to be displayed.
* @param $teaser
* Whether we are to generate a "teaser" or summary of the node, rather than display the whole thing.
* @param $page
* Whether the node is being displayed as a standalone page. If this is TRUE, the node title should not be displayed, as it will be printed automatically by the theme system. Also, the module may choose to alter the default breadcrumb trail in this case.
*
* @return
* html
*/
function theme_video_view($node, $teaser = FALSE, $page = FALSE) {
return '<div id="video_body">' . $node->body . '</div>';
}
/**
* theme function to control which player is presented
*
* @param $node
* node object
*
* @return
* html
*/
function theme_video_player($node) {
// include video.js file for Internet Explorer fixes
theme('video_get_script');
if (variable_get('video_playcounter', 1)) {
db_query("UPDATE {video} SET play_counter = play_counter + 1 where vid = %d", $node->vid);
//Increment play counter.
}
_video_scale_video($node);
$output = module_invoke('video_' . $node->vtype, 'v_play', $node);
return $output;
}
/**
* Cut down on redundant link text
*
* @param $url
* string URL to link to
*
* @param $title
* string title of link to show on mouseover
*
* @param $link_text
* string text of the link
*
* @return
* string HTML link
*/
function theme_video_format_play($output, $url, $title, $link_text) {
$output = "\n<div id=\"video-player\">\n" . $output;
if (variable_get('video_show_help_text', TRUE)) {
$output .= "<p>\n" . t('Problems viewing videos?');
$output .= "<br />\n";
$output .= l($link_text, $url, array(
'title' => $title,
), NULL, NULL, TRUE);
}
return $output . "\n</p> \n </div>\n";
}
/**
* Import the video.js script
*/
function theme_video_get_script() {
drupal_add_js(drupal_get_path('module', 'video') . '/video.js');
}
/******************************************************************************
* End theme functions
******************************************************************************
* Start private functions created for this module.
******************************************************************************/
/**
* Pull the file extension from a filename
*
* @param $vidfile
* string filename to get the filetype from.
*
* @return
* string value of file type or boolean FALSE on error
*/
function _video_get_filetype($vidfile) {
//If the filename doesn't contain a ".", "/", or "\" and is exactly 11 characters then consider it a youtube video ID.
if (!strpos($vidfile, '.') and !strpos($vidfile, '/') and !strpos($vidfile, '\\') and strlen($vidfile) == 11) {
$file_type = 'youtube';
}
else {
if (strpos($vidfile, 'google:') === 0) {
$file_type = 'googlevideo';
}
else {
if (strstr($vidfile, '.')) {
//If file contains a "." then get the file extension after the "."
$file_type = end(explode('.', $vidfile));
}
else {
$file_type = FALSE;
}
}
}
return strtolower($file_type);
}
/**
* Forward user directly to the file for downloading
*
*/
function _video_download_goto($node) {
if (user_access('download video')) {
if (variable_get('video_downloadcounter', 1)) {
db_query("UPDATE {video} SET download_counter = download_counter + 1 where vid = %d", $node->vid);
//Increment download counter.
}
// let the submodule handle the real download logic
module_invoke('video_' . $node->vtype, 'v_download', $node);
}
else {
//If the user does not have access to download videos.
drupal_set_message(t('You do not have permission to download videos.'), 'error');
drupal_goto("node/" . $node->nid);
//Use the nid we just loaded to go back to the node page.
}
}
/**
* Convert filesize to bytes
*
* @return
* integer bytes
*/
function _video_size2bytes($node) {
if (!empty($node->size)) {
switch ($node->size_format) {
case 'Kb':
// KiloBits
return intval($node->size * 128);
break;
case 'KB':
// KiloBytes
return intval($node->size * 1024);
break;
case 'Mb':
// MegaBits
return intval($node->size * 131072);
break;
case 'MB':
// MegaBytes
return intval($node->size * 1048576);
break;
case 'Gb':
// GigaBits
return intval($node->size * 134217728);
break;
case 'GB':
// GigaBytes
return intval($node->size * 1073741824);
break;
default:
return (int) $node->size;
break;
}
}
else {
return 0;
}
}
/**
* Convert seconds to hours, minutes, and seconds.
* Derived from h:m:s example by Jon Haworth
*
* @link
* http://www.laughing-buddha.net/jon/php/sec2hms/
*
* @param $sec
* integer value of seconds.
*
* @return
* array associative with key values of hours, minutes, and seconds.
*/
function _video_sec2hms($sec = 0) {
$hms = array();
// 3600 seconds in an hour and trash remainder
$hms['hours'] = intval(intval($sec) / 3600);
// dividing the total seconds by 60 will give us
// the number of minutes, but we're interested in
// minutes past the hour: to get that, we need to
// divide by 60 again and keep the remainder
$hms['minutes'] = intval($sec / 60 % 60);
$hms['seconds'] = intval($sec % 60);
//keep the remainder.
return $hms;
}
/**
* Returns an absolute url which references
* to the video file
*
* @param $video_file
* string containing absolute or relative URL to video.
*
* @return
* string containing absolute URL path to video file.
*/
function _video_get_fileurl($video_file) {
global $base_url;
//creation of absolute url
if (preg_match("/^(http|ftp|mm|rstp)(s?):\\/\\//", $video_file)) {
//If path is absolute
return check_plain($video_file);
}
else {
// path is relative to drupal install
return check_plain($base_url . '/' . $video_file);
}
}
/**
* Returns the correct mime-type for the video. Returns false if the
* mime-type cannot be detected.
*/
function _video_get_mime_type($node) {
switch (_video_get_filetype($node->vidfile)) {
case 'mov':
return 'video/quicktime';
case 'avi':
// Added
return 'video/x-msvideo';
case 'mpg':
// Added
case 'mpeg':
// Added
return 'video/mpeg';
// Added
case 'divx':
return 'video/vnd.divx';
case 'rm':
return 'application/vnd.rn-realmedia';
case 'flv':
return 'flv-application/octet-stream';
case 'asf':
return 'video/x-ms-asf';
case 'wmv':
return 'video/x-ms-wmv';
case '3gp':
return 'video/3gpp';
case 'mp4':
return 'video/mp4';
case 'dir':
case 'dcr':
return 'application/x-director';
// We can't support this sources properly, so return false.
case 'youtube':
case 'googlevideo':
return false;
case 'ogg':
return 'application/ogg';
default:
// We couldn't detect the mime-type, so return false.
return false;
}
}
/**
* Generates the HTML for any object parameters in an embedded video.
*
* @param $node the node which is being played
*
* @return
* string with the parameters in HTML form.
*/
function _video_get_parameters(&$node) {
// call hook_v_get_params
$param_value = module_invoke_all('v_get_params', $node);
$output = '';
foreach ($param_value as $param => $value) {
$output .= '<param name="' . check_plain($param) . '" value="' . check_plain($value) . '" />\\n';
}
return $output;
}
/**
* Return true if the video support auto resolution
*/
function video_support_autoresolution($node) {
$info = video_get_type_info($node->vtype);
$has_hook = module_hook('video_' . $node->vtype, 'v_auto_resolution');
return $has_hook && isset($info[$node->vtype]['#autoresolution']) && $info[$node->vtype]['#autoresolution'];
}
/**
* Return true if the video support auto playtime
*/
function video_support_autoplaytime($node) {
$info = video_get_type_info($node->vtype);
$has_hook = module_hook('video_' . $node->vtype, 'v_auto_playtime');
return $has_hook && isset($info[$node->vtype]['#autoplaytime']) && $info[$node->vtype]['#autoplaytime'];
}
/**
* Get the resolution options array to use on the video form
*/
function _video_get_resolution_options() {
$options = array();
$i = 1;
while ($i <= 4) {
if (variable_get('video_resolution_' . $i . '_value', '') != '') {
// only if we have a value
$options[$i] = variable_get('video_resolution_' . $i . '_name', '');
}
$i++;
}
return $options;
}
/**
* Get the selected resolution id from the videox and videoy fields
*/
function _video_get_resolution_selected_option($node) {
$value = $node->videox . "x" . $node->videoy;
$i = 1;
while ($i <= 4) {
if (variable_get('video_resolution_' . $i . '_value', '') == $value) {
return $i;
}
$i++;
}
}
/**
* Scale a video to match the desired width
*/
function _video_scale_video(&$node) {
$def_width = (int) variable_get("video_resolution_width", 400);
if (!$node->videox || !$node->videoy) {
$height = $def_width * 3 / 4;
}
else {
$height = $def_width * ($node->videoy / $node->videox);
// do you remember proportions?? :-)
}
$height = round($height);
// add one if odd
if ($height % 2) {
$height++;
}
$node->video_scaled_x = $def_width;
$node->video_scaled_y = $height;
}
Functions
Name | Description |
---|---|
theme_video_format_play | Cut down on redundant link text |
theme_video_get_script | Import the video.js script |
theme_video_player | theme function to control which player is presented |
theme_video_teaser | Theme the teaser |
theme_video_view | theme the view of the page to include the video assumes that body was put through prepare in hook_view |
video_access | access hook |
video_add | Create video submission page. Let the user select the actived video types or display the video form for the selected video type |
video_block | Hook block. Does all the interaction with the drupal block system. Uses video_block_list() for DB queries. |
video_block_list | Query DB for block content |
video_delete | Implementation of hook_delete |
video_download | Redirects to download the video file. |
video_feed | Generate an RSS feed for videos |
video_form | Hook, displays the contents of the node form page for creating and editing nodes. |
video_get_types | Return an array containing enabled Video Types |
video_get_types_infos | Return an array containing informations on enabled Video Types |
video_get_type_info | Return the informations for a given video type |
video_help | Help hook |
video_insert | Implementation of hook_insert. Create video record in the video table |
video_link | Internal Drupal links hook |
video_load | Implementation of hook_load() |
video_menu | Implementation of hook_menu(). |
video_nodeapi | Implementation of hook_nodeapi(). We use this to append <enclosure> tags to the RSS feeds Drupal generates. |
video_node_info | Implementation of _node_info(). |
video_page | Displays a Drupal page containing recently added videos |
video_perm | Permissions hook |
video_settings_form | Settings Hook |
video_settings_form_validate | Form API callback to validate the upload settings form. |
video_submit | Implementation of hook submit |
video_support_autoplaytime | Return true if the video support auto playtime |
video_support_autoresolution | Return true if the video support auto resolution |
video_support_download | Return true if a given video type is downloadable |
video_types_page | Display a video types selection page |
video_update | Hook |
video_validate | Implementation of hook_validate |
video_view | Implementation of hook_view(). |
_video_allow_download | Return true if the video is downloadable, false otherwise |
_video_download_goto | Forward user directly to the file for downloading |
_video_get_filetype | Pull the file extension from a filename |
_video_get_fileurl | Returns an absolute url which references to the video file |
_video_get_mime_type | Returns the correct mime-type for the video. Returns false if the mime-type cannot be detected. |
_video_get_parameters | Generates the HTML for any object parameters in an embedded video. |
_video_get_resolution_options | Get the resolution options array to use on the video form |
_video_get_resolution_selected_option | Get the selected resolution id from the videox and videoy fields |
_video_scale_video | Scale a video to match the desired width |
_video_sec2hms | Convert seconds to hours, minutes, and seconds. Derived from h:m:s example by Jon Haworth |
_video_size2bytes | Convert filesize to bytes |