' . t('The FlashVideo module for Drupal 5.x is an easy to use module that expands the Upload module by allowing users to upload videos and attach those videos to any content. Even more exciting, is that FlashVideo automatically performs the very common Flash format conversion as well as create an image thumbnail of any newly uploaded video for every cron cycle. Once the video is in Flash format, the video can then be embedded in that node using the very simple [video] tag.') . '
';
$output .= '
' . t('To enable this module for a certain node type, you must first go to the ' . l(t('FlashVideo Settings'), 'admin/settings/flashvideo') . ' and select the FlashVideo settings for any available node type in the Drupal system. Once the FlashVideo module has been enabled for that node type, you will then notice the modified Upload form when you add new content for that node type.') . '
';
$output .= '
' . t('Once a video has been uploaded, it will then have to wait for the next Cron cycle for the conversion to Flash format to begin. You can manually run the cron operation by going to Administer->Logs->Status Report and then click on the link that says run cron manually. After the video has been converted, it will then be available to any node referencing that video. That node can then reference the video by using the [video] tag, and also reference the video thumbnail by providing the [thumbnail] tag.') . '
';
$output .= '
' . t('Parameters for these tags are provided by using a ":" to indicate a new parameter is being provided. The following format should be used for both the [video] and [thumbnail] tags. [video: param=value ] where param is the name of the parameter being passed, and value is the value of the parameter.') . '
';
$output .= '
' . t('The following parameters can be used...') . '
';
$output .= t('
index (For both video and thumbnail tags) - This is used to reference a video when muliple videos have been provided for each node. Example: [video: index=0] would reference the first video uploaded to the node, while [video: index=1] would reference the second video uploaded to that node.
width (For video tags only) - This parameter will override the default width of the video with the value given from this parameter.
height (For video tags only) - This parameter will overide the default height of the video with the value given from this paramter.
autostart (Values are true or false, and only used for video tags) - This parameter indicates if the video should start automatically.
');
$output .= '
' . t('The following are examples of using the [video] and [thumbail] tag system...') . '
';
$output .= t('
[video] - The first video uploaded to this node, with all parameters using their defaults.
[video: index=2 : width=320 : height:240] - The third video uploaded to this node with dimensions of 320x240
[thumbnail: index=1] - The thumbnail for the 2nd video uploaded to this node.
[video: autostart=false] - The first video uploaded to this node will not start automatically.
');
return $output;
case 'admin/settings/modules#description':
return t('Allows you to insert videos into nodes.');
}
}
/**
* Implementation of hook_perm().
*/
function flashvideo_perm() {
return array('administer flashvideo');
}
/**
* Implements play callback function from node menu
*/
function flashvideo_play($node) {
// include video.js file for Internet Explorer fixes
theme('flashvideo_get_script');
switch (_flashvideo_get_filetype($node->vidfile)) {
case 'mpeg':
case 'mpg':
case 'mov':
case 'mp4':
case '3gp':
case '3g2':
return theme('flashvideo_play_quicktime', $node);
case 'rm':
return theme('flashvideo_play_realmedia', $node);
case 'flv':
return theme('flashvideo_play_flash', $node);
case 'swf':
return theme('flashvideo_play_swf', $node);
case 'dir':
case 'dcr':
return theme('flashvideo_play_dcr', $node);
case 'wmv':
case 'avi':
return theme('flashvideo_play_windowsmedia', $node);
case 'ogg':
return theme('flashvideo_play_ogg_theora', $node);
case 'youtube':
return theme('flashvideo_play_youtube', $node);
case 'googlevideo':
return theme('flashvideo_play_googlevideo', $node);
default:
return _flashvideo_get_filetype($node->vidfile) . ' filetypes are not supported';
//drupal_set_message('Video type not supported', 'error');
break;
}
}
/**
* Implementation of hook_form_alter()
*/
function flashvideo_form_alter($form_id, &$form) {
if (isset($form['type'])) {
$node_type = _flashvideo_get_node_type($form['type']['#value']);
//We want to move the File attachments to the top and also change a couple of parameters.
if(variable_get($node_type . '_flashvideo_enable', 0)) {
if( isset($form['attachments']) ) {
$form['attachments']['#title'] = variable_get($node_type . '_flashvideo_upload_title', t('Video Upload'));
$form['attachments']['#collapsed'] = FALSE;
$form['attachments']['#weight'] = variable_get($node_type . '_flashvideo_weight', -10);
$form['attachments']['#required'] = variable_get($node_type . '_flashvideo_require', 0);
}
}
}
}
/**
* Implementation of hook_menu().
*/
function flashvideo_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'admin/settings/flashvideo',
'title' => t('FlashVideo Settings'),
'description' => t('Administer the FlashVideo module.'),
'callback' => 'flashvideo_settings',
'access' => user_access('administer flashvideo'),
'type' => MENU_NORMAL_ITEM
);
}
else {
$items[] = array(
'path' => 'admin/settings/flashvideo/edit',
'title' => t('Edit FlashVideo'),
'callback' => 'flashvideo_settings_main',
'access' => user_access('administer flashvideo'),
'type' => MENU_CALLBACK
);
}
return $items;
}
function flashvideo_settings() {
//Must have "administer site configuration" and "administer flashvideo" privilages.
if (!user_access('administer flashvideo') || !user_access('administer site configuration')) {
drupal_access_denied();
}
// We need to set the weight of this module to 10 so that we can form_alter the upload module.
db_query("UPDATE {system} SET weight=10 WHERE type='module' AND name='flashvideo'");
// We need to change the max upload size, and also add the extensions to the file uploads.
$size = variable_get('upload_uploadsize_default', 1);
$user_size = variable_get('upload_usersize_default', 1);
if($size == 1)
variable_set('upload_uploadsize_default', 100);
if($user_size == 1)
variable_set('upload_usersize_default', 1000);
$extensions = variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps');
$new_exts = array('avi', 'mpeg', 'mpg', 'mov', 'rm', 'flv', 'wmv', '3gp', 'mp4', 'dir', 'dcr');
foreach($new_exts as $new_ext) {
if(strpos($extensions, $new_ext) === FALSE)
$extensions .= ' ' . $new_ext;
}
variable_set('upload_extensions_default', $extensions);
$header = array(t('NodeType'), t('Status'), t('Operations'));
// Create a list of all node types.
$types = node_get_types();
foreach($types as $type)
{
$node_type = _flashvideo_get_node_type($type->name);
$status = variable_get($node_type . '_flashvideo_enable', 0) ? '(Enabled)' : '(Disabled)';
$rows[] = array($type->name, $status, l(t('FlashVideo Settings for this node type.'), "admin/settings/flashvideo/edit/$type->name"));
}
return theme('table', $header, $rows);
}
function flashvideo_settings_main() {
//Must have "administer site configuration" and "administer flashvideo" privilages.
if (!user_access('administer flashvideo') || !user_access('administer site configuration')) {
drupal_access_denied();
}
$args = func_get_args();
$node_type = $args[0];
if($node_type)
return drupal_get_form('flashvideo_settings_form', $node_type);
}
function _flashvideo_get_node_type($node_type) {
$node_type = strpos($node_type, ' ') ? substr($node_type, 0, strpos($node_type, ' ')) : $node_type;
return strtolower($node_type);
}
function flashvideo_settings_form($node_type) {
$node_type = _flashvideo_get_node_type($node_type);
$form[$node_type . '_flashvideo_enable'] = array(
'#type' => 'checkbox',
'#title' => t('Enable the FlashVideo for this Node Type'),
'#default_value' => variable_get($node_type . '_flashvideo_enable', 0),
'#description' => t("Enable the FlashVideo for this Node Type.")
);
$form[$node_type . '_flashvideo_require'] = array(
'#type' => 'checkbox',
'#title' => t('Require the FlashVideo for this node type.'),
'#default_value' => variable_get($node_type . '_flashvideo_require', 0),
'#description' => t("If checked, the video will be required to submit this node type.")
);
$form[$node_type . '_flashvideo_upload_title'] = array(
'#title' => t('FlashVideo Upload Title'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_upload_title', t('Video Upload')),
'#maxlength' => 128,
'#description' => t('The title for the Video Upload for this node.')
);
$form[$node_type . '_flashvideo_weight'] = array(
'#title' => t('FlashVideo Upload Weight'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_weight', -10),
'#maxlength' => 10,
'#description' => t('Determines how high in the submit form you would like to have the video upload. The lower the value, the higher the placement.')
);
$form[$node_type . '_flashvideo_player_download'] = array(
'#type' => 'checkbox',
'#title' => t('Attach Video Player Download Link'),
'#default_value' => variable_get($node_type . '_flashvideo_player_download', 0),
'#description' => t("Add a link to download the player at the bottom of the Video object.")
);
$form[$node_type . '_flashvideo_attachment_links'] = array(
'#type' => 'checkbox',
'#title' => t('Show Videos as Attachments'),
'#default_value' => variable_get($node_type . '_flashvideo_attachment_links', 0),
'#description' => t("Checking this box will show all videos in the attachments section of this node type.")
);
$form['performance'] = array('#type' => 'fieldset', '#title' => t('Performance'), '#collapsible' => TRUE, '#collapsed' => TRUE);
$form['performance'][$node_type . '_flashvideo_search_thumbnails'] = array(
'#type' => 'checkbox',
'#title' => t('Search for thumbnails in the Node Body.'),
'#default_value' => variable_get($node_type . '_flashvideo_search_thumbnails', 0),
'#description' => t("Checking this box will allow you to have video thumbnails in the Node body, at a performance cost.")
);
$form['performance'][$node_type . '_flashvideo_search_video'] = array(
'#type' => 'checkbox',
'#title' => t('Search for videos in the Node Teaser.'),
'#default_value' => variable_get($node_type . '_flashvideo_search_video', 0),
'#description' => t("Checking this box will allow you to have video objects in the Node Teasers, at a slight performance cost.")
);
$form['ffmpeg'] = array('#type' => 'fieldset', '#title' => t('FFMPEG settings'), '#collapsible' => TRUE, '#collapsed' => TRUE);
$form['ffmpeg'][$node_type . '_flashvideo_use_ffmpeg_php'] = array(
'#type' => 'checkbox',
'#title' => t('Use FFMPEG-PHP to extract video information.'),
'#default_value' => variable_get($node_type . '_flashvideo_use_ffmpeg_php', 0),
'#description' => t("Checking this box will extract the uploaded video information, but is not essential to making this module work.")
);
$form['ffmpeg'][$node_type . '_flashvideo_ffmpeg_path'] = array(
'#title' => t('ffmpeg Path'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_ffmpeg_path', '/usr/bin/ffmpeg'),
'#maxlength' => 128,
'#description' => t('The path to the ffmpeg binary.'),
'#required' => TRUE
);
$form['ffmpeg'][$node_type . '_flashvideo_output_dir'] = array(
'#title' => t('Output Directory'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_output_dir', '/files'),
'#maxlength' => 128,
'#description' => t('The output directory to contain the thumbnail and video.'),
'#required' => TRUE
);
$form['ffmpeg'][$node_type . '_flashvideo_flash_player'] = array(
'#title' => t('Flash Player Name'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_flash_player', 'Player.swf'),
'#maxlength' => 128,
'#description' => t('The name of the Flash Player. Note: This player MUST reside in the output directory to work.'),
'#required' => TRUE
);
$form['ffmpeg'][$node_type . '_flashvideo_thumbnail_size'] = array(
'#title' => t('Thumbnail Size'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_thumbnail_size', '130x100'),
'#maxlength' => 10,
'#description' => t('The size of the thumnail. Width x Height. Example "130x100"'),
'#required' => TRUE
);
$form['ffmpeg'][$node_type . '_flashvideo_thumbnail_time'] = array(
'#title' => t('Thumbnail Time'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_thumbnail_time', '00:00:02'),
'#maxlength' => 10,
'#description' => t('The amount of time to move from the beginning of the video before taking a snapshot. Example "00:00:02" is 2 seconds.'),
'#required' => TRUE
);
$form['ffmpeg'][$node_type . '_flashvideo_max_num_failures'] = array(
'#title' => t('Maximum Failures'),
'#type' => 'textfield',
'#default_value' => variable_get($node_type . '_flashvideo_max_num_failures', 5),
'#maxlength' => 10,
'#description' => t('The maximum amount of conversion failures, before it reverts to using standard (non-Flash) video display.'),
'#required' => TRUE
);
return system_settings_form($form);
}
/**
* 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 _flashvideo_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 = substr($vidfile, strrpos($vidfile, '.') + 1);
}
else {
$file_type = FALSE;
}
return strtolower($file_type);
}
/**
* Returns the correct mime-type for the video. Returns false if the
* mime-type cannot be detected.
*/
function _flashvideo_get_mime_type($filename, $extension = FALSE) {
$file_type = $extension ? $filename : _flashvideo_get_filetype($filename);
switch ($file_type) {
case 'avi':
return 'video/avi';
case 'mpeg':
case 'mpg':
case 'mov':
return 'video/quicktime';
case 'rm':
return 'application/vnd.rn-realmedia';
case 'flv':
return 'flv-application/octet-stream';
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;
}
}
/**
* 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 _flashvideo_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);
}
}
/**
* Convert filesize to bytes
*
* @return
* integer bytes
*/
function _flashvideo_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;
}
}
function _perform_ffmpeg($file, $output_dir, $ffmpeg_path, $thumbsize = NULL, $thumbtime = '') {
// Get the base filename and then rename it according to the node ID and security measures.
$new_extension = $thumbsize ? ".jpg" : ".flv";
$new_file_name = preg_replace("/[^a-zA-Z0-9_\.]/", "_", $file->nid . "_" . basename($file->filepath, "." . $file->extension)); // Rename output file.
$output_path = getcwd() . $output_dir . $new_file_name . $new_extension;
// Only convert if the input file exists, and the output file does not exists.
if((file_exists($file->filepath) && filesize($file->filepath) > 0) && !(file_exists($output_path) && filesize($output_path) > 0)) {
// Ok... LET'S DO THIS!!!
db_query('UPDATE {flashvideo} SET status=1 WHERE fid='.$file->fid); // Status = 1 - File is converting.
$command = ($thumbsize) ? "$ffmpeg_path -y -i {$file->filepath} -vframes 1 -ss $thumbtime -an -vcodec mjpeg -f rawvideo -s " . $thumbsize->width . "x" . $thumbsize->height ." {$output_path}" :
"$ffmpeg_path -i {$file->filepath} -f flv -acodec mp3 -ab 64 -ac 1 {$output_path}";
exec($command); // Execute the command.
// Check if the file exists.
if(file_exists($output_path) && filesize($output_path) > 0) {
$new_filepath = substr($output_dir, 1) . basename($output_path);
$fid = db_next_id('{files}_fid');
db_query('INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, \'%s\', \'%s\', \'%s\', %d)',
$fid, $file->nid, basename($file->filename, "." . $file->extension) . $new_extension, $new_filepath, ($thumbsize ? 'jpg' : 'flv-application/octet-stream'), filesize($output_path));
$params = db_fetch_object(db_query("SELECT video_index, width, height FROM {flashvideo} WHERE fid = %d", $file->fid));
db_query("INSERT INTO {flashvideo} (fid, nid, oid, status, video_index, width, height) VALUES (%d, %d, %d, 3, %d, %d, %d)", $fid, $file->nid, $file->fid, $params->video_index, $params->width, $params->height);
db_query('UPDATE {flashvideo} SET status=2 WHERE fid='.$file->fid); // Status = 2 - File is pending.
return $new_file_name;
}
db_query('UPDATE {flashvideo} SET status=0 WHERE fid='.$file->fid); // So that it will try again later.
db_query('INSERT INTO {ffmpeg_data} (fid, created, input_file, output_file, status, data) VALUES (%d, NOW(), \'%s\', \'%s\', %d, \'%s\')',
$file->fid, $file->filepath, $output_path, 0, 'Conversion Failed: '. $command);
}
return FALSE;
}
/**
* Implementation of hook_cron
*/
function flashvideo_cron() {
// I will use the Cron task to convert all uploaded video's to Flash file format.
$types = node_get_types();
foreach($types as $type){
$node_type = _flashvideo_get_node_type($type->name);
if(variable_get($node_type . '_flashvideo_enable', 0)) {
$output_dir = variable_get($node_type . '_flashvideo_output_dir', '/files') . '/'; // The output directory
$max_num_failures = variable_get($node_type . '_flashvideo_max_num_failures', 5); // The maximum number of conversion failures.
$ffmpeg_path = variable_get($node_type . '_flashvideo_ffmpeg_path', '/usr/bin/ffmpeg'); // The path to our ffmpeg executable.
$size = explode('x', strtolower(variable_get($node_type . '_flashvideo_thumbnail_size', '130x100'))); // The video size as "width x height"
$thumbsize = (object)array('width' => $size[0], 'height' => $size[1]); // The thumbnail size as "width x height
$thumbtime = variable_get($node_type . '_flashvideo_thumbnail_time', '00:00:02'); // The amount of time to delay before taking a picture snapshot.
// First we will want to grab all files that have not been processed yet.
$sql = 'SELECT f.* FROM {files} f LEFT JOIN {flashvideo} fv ON f.fid = fv.fid LEFT JOIN {node} n ON f.nid = n.nid ';
$sql .= 'WHERE ((n.type = \''.$node_type.'\') AND (fv.status = 0) AND (n.moderate != 1))';
$files = db_query($sql);
while($file = db_fetch_object($files)) {
$failures = db_result(db_query('SELECT COUNT(*) FROM {ffmpeg_data} data LEFT JOIN {files} ON data.fid = files.fid WHERE (data.fid = %d) AND (data.status = 0)', $file->fid));
if(!strpos($file->filename, 'NOCONVERT') && ($failures < $max_num_failures)) {
$file->filepath = getcwd() . '/' . $file->filepath; // Normalize the filepath to the base of the system.
$file->extension = _flashvideo_get_filetype($file->filepath); // Get the file extension.
if(_flashvideo_get_mime_type($file->extension, TRUE) && $file->extension != 'flv') { // Make sure it is a video file.
$new_thumb_name = _perform_ffmpeg($file, $output_dir, $ffmpeg_path, $thumbsize, $thumbtime); // Create a thumbnail of the video.
if($new_file_name = _perform_ffmpeg($file, $output_dir, $ffmpeg_path)) { // Convert the video to flash.
$new_video_name = basename($new_file_name, ".flv") . "." . $file->extension; // Rename the original video.
rename($file->filepath, getcwd() . $output_dir . $new_video_name);
db_query('UPDATE {files} SET filepath=\'' . substr($output_dir, 1) . $new_video_name.'\' WHERE fid='.$file->fid);
$sql = 'UPDATE {node} SET status = 1 WHERE nid='. $file->nid; // update the status of the node.
db_query($sql);
$sql = 'TRUNCATE cache'; // Delete the cache so that our node will update.
db_query($sql);
db_query('INSERT INTO {ffmpeg_data} (fid, created, input_file, output_file, status) VALUES (%d, NOW(), \'%s\', \'%s\', %d)', $file->fid, $file->filepath, $output_path, 1);
}
}
}
else {
// We are unable to convert the video... Not all is lost. We will just use the original video.
// update the status of the file.
$sql = 'UPDATE {flashvideo} SET status=3 WHERE fid='. $file->fid;
db_query($sql);
}
}
}
}
}
function _get_video_thumbnail($node, $video_filename ) {
if(count($node->files)) {
foreach($node->files as $file) { // Loop through and see if an image matches the filename of this video.
$file = (object)$file;
$file_type = _flashvideo_get_filetype($file->filename);
if(($file_type == 'jpg' || $file_type == 'png') && (basename($file->filename, "." . $file_type) == $video_filename ))
return $file;
}
}
return FALSE;
}
// Link into the operations of the upload module for file insertion and deletion.
function _flashvideo_update_files($node) {
$video_index = 0;
if(count($node->files)) {
foreach ($node->files as $file) {
$file = (object)$file;
if ($file->remove) {
$files = db_query("SELECT * FROM {files} f LEFT JOIN {flashvideo} fv ON f.fid = fv.fid WHERE fv.oid = %d", $file->fid);
db_query('DELETE FROM {flashvideo} WHERE oid = %d', $file->fid);
while($oldfile = db_fetch_object($files)) {
db_query('DELETE FROM {files} WHERE fid = %d', $oldfile->fid);
file_delete($oldfile->filepath);
}
}
else {
$found = db_result(db_query("SELECT count(*) FROM {flashvideo} WHERE fid=%d", $file->fid));
if(_flashvideo_get_mime_type($file->filename)) { // Only add if the file is a video and is not already in our flashvideo table.
if(!$found) {
$node_type = _flashvideo_get_node_type($node->type);
if(variable_get($node_type . '_flashvideo_use_ffmpeg_php', 0)) {
$extension = "ffmpeg";
$extension_soname = $extension . "." . PHP_SHLIB_SUFFIX;
$extension_fullname = PHP_EXTENSION_DIR . "/" . $extension_soname;
// load extension
if (!extension_loaded($extension)) {
dl($extension_soname);
$movie = new ffmpeg_movie($file->filepath); // ffmpeg-PHP : used to get video information.
}
}
$width = ($movie) ? $movie->getFrameWidth() : 450;
$height = ($movie) ? $movie->getFrameHeight() : 337;
db_query("INSERT INTO {flashvideo} (fid, nid, oid, status, video_index, width, height) VALUES (%d, %d, %d, 0, %d, %d, %d)", $file->fid, $node->nid, $file->fid, $video_index, $width, $height);
}
$video_index++;
}
}
}
}
}
/**
* Parses a single tag, and places all parameters in an array.
*/
function _flashvideo_parse_param($body, &$pos, &$params, $max_size = 50) {
$string = '';
$size = 0;
while(($size < $max_size) && substr($body, $pos, 1) == ' ') { // Ignore white space.
$pos++;
$size++;
}
if(substr($body, $pos++, 1) == ':') {
while(($size < $max_size) && (substr($body, $pos, 1) != ':') && (substr($body, $pos, 1) != ']')) {
$string .= strtolower(substr($body, $pos++, 1)); // Extract the data
$size++;
}
$parts = explode('=', $string);
if((strlen($parts[0]) > 0) && (strlen($parts[1]) > 0))
$params[strtolower(trim($parts[0]))] = strtolower(trim($parts[1]));
return TRUE; // A parameter was provided and parsed. Return true.
}
return FALSE;
}
/**
* Given a node variable, and index, this will return a video thumbnail.
*/
function flashvideo_get_thumb_object(&$node, $index) {
global $base_url;
if($node->thumbnail[$index] == '') {
$url = $base_url . '/' .drupal_get_path('module', 'flashvideo') . '/thumbnail_MIA.png';
$node->thumbnail[$index] = '';
}
return $node->thumbnail[$index];
}
/**
* Given a node variable, and index, and some parameters, this will return a video object.
*/
function flashvideo_get_video_object(&$node, $index, $params) {
global $base_url;
if($node->video_obj[$index] == '') {
$url = $base_url . '/' .drupal_get_path('module', 'flashvideo') . '/video_MIA.png';
$node->video_obj[$index] = '';
}
else {
$params['autostart'] = ($params['autostart']) ? $params['autostart'] : 'true';
$params['width'] = ($params['width']) ? $params['width'] : $node->video_width[$index];
$params['height'] = ($params['height']) ? $params['height'] : $node->video_height[$index];
$node->video_obj[$index] = str_replace("[--WIDTH--]", $params['width'], $node->video_obj[$index]); // String replacments
$node->video_obj[$index] = str_replace("[--HEIGHT--]", $params['height'], $node->video_obj[$index]);
$node->video_obj[$index] = str_replace("[--AUTOSTART--]", $params['autostart'], $node->video_obj[$index]);
}
return $node->video_obj[$index];
}
/**
* Search and Replace routine. Scans the body of a node and replaces every tag and its parameters with an object.
*/
function _flashvideo_replace_tags(&$node, $tag) {
$max_num_params = 4; // The maximum number of parameters allowed. All others will be ignored.
$body = ($node->body == '') ? $node->teaser : $node->body;
for($pos = 0; (($pos = $startpos = strpos($body, $tag, $pos)) !== FALSE); $pos++) { // Search for tags
// We need to check to see if this tag has "!" in front of it, if it does, then we will ignore this tag.
if(substr($body, $pos - 1, 1) == '!') {
$body = substr_replace($body, $tag, $pos - 1, strlen($tag) + 1);
}
else {
$pos += strlen($tag);
$params = array(); // Initialize the params array
while(_flashvideo_parse_param($body, $pos, $params)); // Parse all the parameters.
$params['index'] = ($params['index']) ? $params['index'] : 0; // If they didn't provide an index, then we will just use the default.
$object = ($tag == '[thumbnail') ? flashvideo_get_thumb_object($node, $params['index']) : flashvideo_get_video_object($node, $params['index'], $params);
$body = substr_replace($body, $object, $startpos, ($pos - $startpos)); // Replace this tag.
}
}
if($node->body == '')
$node->teaser = $body;
else
$node->body = $body;
}
/**
* Implementation of hook_link()
*/
function flashvideo_link($type, $node = NULL, $teaser = FALSE) {
$links = array();
// Display a link with the number of attachments
$node_type = _flashvideo_get_node_type($node->type);
if (!variable_get($node_type . '_flashvideo_attachment_links', 0) && $teaser && $type == 'node' && isset($node->files) && user_access('view uploaded files')) {
$num_files = 0;
if(count($node->files)) {
foreach ($node->files as $file) {
if (!_flashvideo_get_mime_type($file->filename) && $file->list) {
$num_files++;
}
}
}
if ($num_files) {
$links['upload_attachments'] = array(
'title' => format_plural($num_files, '1 attachment', '@count attachments'),
'href' => "node/$node->nid",
'attributes' => array('title' => t('Read full article to view attachments.')),
'fragment' => 'attachments'
);
}
else {
$links['upload_attachments'] = '';
}
}
return $links;
}
/**
* Implementation of hook_nodeapi()
*/
function flashvideo_nodeapi(&$node, $op, $teaser) {
// Only if the node type is enabled.
$node_type = _flashvideo_get_node_type($node->type);
if(variable_get(strtolower($node_type) . '_flashvideo_enable', 0)) {
switch ($op) {
case 'insert':
case 'update':
_flashvideo_update_files($node);
break;
case 'load':
// We need to load the video and thumbnail object into our $node.
$files = db_query("SELECT * FROM {files} f LEFT JOIN {flashvideo} fv ON f.fid = fv.fid WHERE (f.nid = %d) AND (fv.status = 3)", $node->nid);
while($file = db_fetch_object($files)) {
$original_video = $video = '';
$file_type = _flashvideo_get_filetype($file->filepath);
$file_mime = _flashvideo_get_mime_type($file_type, TRUE);
if($file_type == 'flv')
$video = file_create_url($file->filepath);
else if($file_mime)
$original_video = file_create_url($file->filepath);
else if($file_type == 'jpg' || $file_type == 'png')
$node->thumbnail[$file->video_index] = '';
if($file_mime) {
$node->vidfile = ($video == '') ? $original_video : $video;
$node->video_width[$file->video_index] = $file->width;
$node->video_height[$file->video_index] = $file->height;
$node->video_obj[$file->video_index] = flashvideo_play($node);
}
}
$node->play_counter = db_result(db_query("SELECT play_counter FROM {flashvideo} WHERE nid = %d", $node->nid));
break;
case 'view':
// If they uploaded a video, we don't want to see those video's in the attachments.
$node_type = _flashvideo_get_node_type($node->type);
if (!variable_get($node_type . '_flashvideo_attachment_links', 0) && !$teaser && isset($node->files) && user_access('view uploaded files')) {
$files = array();
if (count($node->files) ) {
foreach ($node->files as $file) {
$file = (object)$file;
if(!_flashvideo_get_mime_type($file->filename))
$files[] = $file;
}
}
if (count($files)) {
$node->content['files'] = array(
'#value' => theme('upload_attachments', $files),
'#weight' => 50,
);
}
else {
$node->content['files']['#value'] = '';
}
}
break;
case 'alter':
// Here we will do a search and replace for anyone who is using the video and thumbnail tags.
if(!$teaser) {
db_query("UPDATE {flashvideo} SET play_counter = play_counter + 1 WHERE nid = %d", $node->nid); //Increment play counter.
}
if(!$teaser || variable_get($node_type . '_flashvideo_search_video', 0))
_flashvideo_replace_tags($node, '[video');
if($teaser || variable_get($node_type . '_flashvideo_search_thumbnail', 0))
_flashvideo_replace_tags($node, '[thumbnail');
break;
case 'rss item':
$attributes['url'] = _flashvideo_get_fileurl($node->vidfile[0]); // Only show the first video
$attributes['length'] = $node->size;
$mime_type = _flashvideo_get_mime_type($node->vidfile[0]);
if ($mime_type) {
$attributes['type'] = $mime_type;
}
$media['url'] = $attributes['url'];
$media['fileSize'] = $attributes['length'];
$media['type'] = $attributes['type'];
return array(array('key' => 'enclosure', 'attributes' => $attributes), array('key' => 'media', 'value' => '', 'attributes' => $media));
case 'delete':
case 'delete revision':
foreach ($node->files as $file) {
$file = (object)$file;
db_query('DELETE FROM {flashvideo} WHERE fid = %d', $file->fid);
db_query('DELETE FROM {ffmpeg_data} WHERE fid = %d', $file->fid);
}
break;
}
}
}
/*********************************************************************
* Themeable functions for playing videos. They print a page with a player embedded.
*********************************************************************/
/**
* Play videos from in FLV Flash video format
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_flash($node) {
$loader_base = substr($node->vidfile, 0, strrpos($node->vidfile, '/'));
$node_type = _flashvideo_get_node_type($node->type);
$loader_location = _flashvideo_get_fileurl($loader_base . '/' . variable_get($node_type . '_flashvideo_flash_player', 'Player.swf'));
$file = basename($node->vidfile);
// this will be executed by not Internet Explorer browsers
$output .= '';
$output = _theme_flashvideo_format_play($node->type, $output, t('http://www.macromedia.com/go/getflashplayer'),
t('Link to Macromedia Flash Player Download Page'),
t('Download latest Flash Player'));
return $output;
}
/**
* Play Flash .swf files.
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_swf($node) {
$url = _flashvideo_get_fileurl($node->vidfile);
// this will be executed by not Internet Explorer browsers
$output .= '';
$output .= '';
$output = _theme_flashvideo_format_play($node->type, $output, t('http://www.macromedia.com/go/getflashplayer'),
t('Link to Flash player download'),
t('Download the latest Flash player'));
return $output;
}
/**
* Play Director .dcr/.dir files.
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_dcr($node) {
$url = _flashvideo_get_fileurl($node->vidfile);
// this will be executed by not Internet Explorer browsers
$output .= '';
$output .= '';
$output = _theme_flashvideo_format_play($node->type, $output, t('http://www.macromedia.com/shockwave/download/'),
t('Link to Macromedia Shockwave Player Download Page'),
t('Download latest Shockwave Player'));
return $output;
}
/**
* Play videos from in Quicktime format
*
* @see http://developer.apple.com/internet/ieembedprep.html
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_quicktime($node) {
$url = _flashvideo_get_fileurl($node->vidfile);
//Increase the height to accommodate the player controls on the bottom.
// this will be executed by not Internet Explorer browsers
$output = '
'; // only one needed becouse only one opening tag has been parsed by browsers
/*
$output = '';
*/
$output = _theme_flashvideo_format_play($node->type, $output, t('http://www.apple.com/quicktime/download'),
t('Link to QuickTime Download Page'),
t('Download latest Quicktime Player'));
return $output;
}
/**
* Play videos from in Realmedia format
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_realmedia($node) {
// Real's embeded player includes the controls
// in the height
$url = _flashvideo_get_fileurl($node->vidfile);
// this will be executed by not Internet Explorer browsers
$output = '
'; // only one needed becouse only one opening tag has been parsed by browsers
$output = _theme_flashvideo_format_play($node->type, $output, t('http://www.real.com/'),
t('Link to Real'),
t('Download latest Realmedia Player'));
return $output;
}
/**
* Play videos from in WindowsMediaVideo format
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_windowsmedia($node) {
// Windows Media's embeded player includes the controls in the height
$url = _flashvideo_get_fileurl($node->vidfile);
// this will be executed by not Internet Explorer browsers
$output = '
'; // only one needed becouse only one opening tag has been parsed by browsers
$output = _theme_flashvideo_format_play($node->type, $output, t('http://windowsupdate.microsoft.com/'),
t('Link to Windows Update'),
t('Download latest Windows Media Player'));
return $output;
}
/**
* Play videos hosted on youtube.com
* Allows users to host videos on youtube.com and then use the video ID to post it in the module.
* In the future it could also use the youtube developer API to get info and comments of the video.
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_youtube($node) {
// this will be executed by not Internet Explorer browsers
$output = '
';
$output = _theme_flashvideo_format_play($node->type, $output, t('http://www.youtube.com/t/help_center'), t('Link to youtube.com'), t('youtube.com'));
return $output;
}
/**
* Play videos hosted on video.google.com
* Allows users to host videos on video.google.com and then use the video ID to post it in the module.
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_googlevideo($node) {
// Strip heading "google:"
$videoid = substr($node->vidfile, 7);
// this will be executed by not Internet Explorer browsers
$output = '
';
$output = _theme_flashvideo_format_play($node->type, $output, t('http://video.google.com/support'), t('Link to video.google.com'), t('video.google.com'));
return $output;
}
/**
* Play Ogg Theora videos with Cortado Applet
*
* @param $node
* object with node information
*
* @return
* string of content to display
*/
function theme_flashvideo_play_ogg_theora($node) {
global $base_url;
$cortado_location = variable_get('video_cortado', $base_url . '/cortado.jar');
$url = _flashvideo_get_fileurl($node->vidfile);
$output = '
';
$output = _theme_flashvideo_format_play($node->type, $output,
t('http://java.com/download/'), t('Link to java.com'), t('Download Java'));
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_flashvideo_format_play($node_type, $output, $url, $title, $link_text) {
$output = "\n
\n";
}
/**
* Takes an associative array of $fields with 'title' and 'body' keys and outputs the HTML.
* This theme function allows the same HTML code to generate all the custom and metadata fields.
*
* @param $fields
* array with 'title' and 'body' keys
*
* @return
* string of content to display
*/
function theme_flashvideo_fields($fields) {
$output = '';
$odd_even = 'odd';
foreach ($fields as $field) {
$output .= "
\n";
$odd_even = ($odd_even == 'odd') ? 'even' : 'odd'; //Always switch its value.
}
return $output;
}
/**
* Import the video.js script
*/
function theme_flashvideo_get_script() {
drupal_set_html_head('');
}
/**
* 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 _flashvideo_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 .= '\n';
}
return $output;
}