Full flashvideo.module code

  1. <?php
  2. // $Id: flashvideo.module,v 1.20.2.32 2008/02/20 04:44:26 travist Exp $
  3.  
  4. /**
  5.  * @file
  6.  * Enables the ability to attach a Flash video to a node.
  7.  */
  8.  
  9. require_once(drupal_get_path('module', 'flashvideo') . '/flashvideo_objects.inc');
  10.  
  11. /**
  12.  * The Status defines for a FlashVideo video.
  13.  */
  14.  
  15. define('FLASHVIDEO_STATUS_OK', 0);
  16. define('FLASHVIDEO_STATUS_CONVERTING', 1);
  17. define('FLASHVIDEO_STATUS_PENDING', 2);         // Not used anymore...
  18. define('FLASHVIDEO_STATUS_CONVERTED', 3);
  19.  
  20. // A string of default flash mime types.  Each one separated by a new line character "\n".
  21. define('FLASHVIDEO_MIMETYPE_STRING', "flv-application/octet-stream\napplication/octet-stream\napplication/x-flash-video\nvideo/x-flv");
  22.  
  23. // A string representation of the [FileType, MimeType, Player] combination.
  24. $flashvideo_filetype_string = "[avi, video/avi, windowsmedia]\n[mpeg, video/quicktime, quicktime]\n[mpg, video/quicktime, quicktime]\n[mov, video/quicktime, quicktime]\n[rm, application/vnd.rn-realmedia, realmedia]\n";
  25. $flashvideo_filetype_string .= "[swf, 0, swf]\n[flv, flv-application/octet-stream, flash]\n[playlist, 0, flash]\n[wmv, video/x-ms-wmv, windowsmedia]\n[3gp, video/3gpp, quicktime]\n[mp4, video/mp4, quicktime]\n[dir, application/x-director, dcr]\n";
  26. $flashvideo_filetype_string .= "[dcr, application/x-director, dcr]\n[ogg, application/ogg, ogg_theora]\n[youtube, 0, youtube]\n[googlevideo, 0, googlevideo]\n[brightcove, 0, brightcove]";
  27. define('FLASHVIDEO_FILETYPE_STRING', $flashvideo_filetype_string);
  28.  
  29. /**
  30.  * The flags that can be overidden within the hooks to allow for specific functionality.
  31.  */
  32.  
  33. define('FLASHVIDEO_REGEN_THUMB', 0x1);   // Bit field letting the flashvideo module know to regenerate the thumbnail.
  34. define('FLASHVIDEO_REGEN_VIDEO', 0x2);   // Bit field letting the flashvideo module know to regenerate the video.
  35.  
  36. // Quick Function for formating our array elements.
  37. function fid_format(&$item){$item = 'f.fid='.$item;}   
  38.        
  39. // Quick Function that returns the file extension given a file path.                                                                   
  40. function get_file_ext($filepath){ return strtolower(substr($filepath, strrpos($filepath, '.') + 1)); }
  41.    
  42. // Quick Function that returns the base file name given a file path.  
  43. function filename($filepath){ return basename($filepath, "." . get_file_ext($filepath)); }
  44.  
  45. /**
  46.  * Wrapper function around the variable_get function to allow for global variables.
  47.  */
  48. function flashvideo_variable_get($node_type, $name, $default) {
  49.   global $conf;
  50.   if($node_type == NULL) {
  51.      return variable_get($name, $default);
  52.   }
  53.   else if(isset($conf['flashvideo_'.$node_type.'_'.$name])) {
  54.      return $conf['flashvideo_'.$node_type.'_'.$name];
  55.   }  
  56.   else if(isset($conf['flashvideo_global_'.$name])) {
  57.      return $conf['flashvideo_global_'.$name];
  58.   }
  59.   else {
  60.      return $default;
  61.   }
  62. }
  63.  
  64. /**
  65.  * Implementation of hook_help()
  66.  */
  67. function flashvideo_help($section = 'admin/help#flashvideo') {
  68.    switch ($section) {
  69.       case 'admin/help#flashvideo':
  70.          $output = '<p>' . 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 <b>[video]</b> tag.') . '</p>';
  71.          $output .= '<p>' . 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.') . '</p>';
  72.          $output .= '<p>' . 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 <b>Administer->Logs->Status Report</b> and then click on the link that says <b>run cron manually</b>.  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 <b>[video]</b> tag, and also reference the video thumbnail by providing the <b>[thumbnail]</b> tag.') . '</p>';
  73.          $output .= '<p>' . t('Parameters for these tags are provided by using a "<b>:</b>" to indicate a new parameter is being provided.  The following format should be used for both the <b>[video]</b> and <b>[thumbnail]</b> tags.  <b>[video: param=value ]</b> where <b>param</b> is the name of the parameter being passed, and <b>value</b> is the value of the parameter.') . '</p>';
  74.          $output .= '<p>' . t('The following parameters can be used...') . '</p>';
  75.          $output .= t('<ul>
  76.                       <li><b>index</b> (For both <em>video</em> and <em>thumbnail</em> tags) - This is used to reference a video when multiple videos have been provided for each node.  If no <b>node</b> parameter is specified, then this will reference the node in which the tag resides.  Example: <em>[video: index=0]</em> would reference the first video uploaded to that node, while <em>[video: index=1]</em> would reference the second video uploaded to that node.</li>
  77.                       <li><b>node</b> (For both <em>video</em> and <em>thumbnail</em> tags) - This is used to reference a video in another node.  Example: <em>[video: node=10: index=0]</em> would reference the first video uploaded to node 10.</li>
  78.                       <li><b>fids</b> (For both <em>video</em> and <em>thumbnail</em> tags) - File ID\'s:  This parameter can specify a single File ID, or many File ID\'s separated by a "-".  If many File ID\'s are specified then those videos will play in that order.  If you would like to show all your videos uploaded to a node in a playlist fashion, all you have to specify is <strong>fids=node</strong>...  Example: <em>[video: fids=6]</em> would play the video for file ID 6, while <em>[video: fids:5-3-34]</em> would play files 5 followed by 3 followed by 34.</li>
  79.                       <li><b>file</b> (For both <em>video</em> and <em>thumbnail</em> tags) - Used to specify a certain file by it\'s file name.  Referenced from the system files directory.</li>
  80.                       <li><b>id</b> (For <em>video</em> tags only) - The <b>id</b> tags are used to play YouTube, Google, and Brightcove videos.  For YouTube video\'s simply just place the ID after the tag.  For Google and Brightcove Videos, you will need to place <b>google-</b> and <b>brightcove-</b> respectively at the beginning of the tag.  Example:  <em>[video:id=google-3754293779500828561]</em> will play video 3754293779500828561 from video.google.com, and <em>[video:id=SmVAWKfJ4Go]</em> will play a video from YouTube with the ID SmVAWKfJ4Go.</li>
  81.                       <li><b>width</b> (For <em>video</em> tags only) - This parameter will override the default width of the video with the value given from this parameter.</li>
  82.                       <li><b>height</b> (For <em>video</em> tags only) - This parameter will override the default height of the video with the value given from this parameter.</li>
  83.                       <li><b>autostart</b> (Values are true or false, and only used for <em>video</em> tags) - This parameter indicates if the video should start automatically.</li>
  84.                       <li><b>flashvar</b> (For <em>video</em> tags only) - This parameter is used to specify custom FlashVars within the object code of the player.  This can be used to override default functionality of any video player.  The following schema should be used to denote any FlashVars for your video... <strong>[video:flashvar|param=value]</strong> where "flashvar" indicates that the parameter is a FlashVar followed by a "|" and then your FlashVar parameter and value.  For example, if I want to set my intro image for my video as "intro.jpg", my [video] tag would look like the following... <strong>[video : flashvar|image=intro.jpg]</strong></li>
  85.                     </ul>');
  86.          $output .= '<p>' . t('The following are examples of using the [video] and [thumbnail] tag system...') . '</p>';
  87.          $output .= t('<ul>
  88.                       <li><b>[video]</b> - The first video uploaded to this node, with all parameters using their defaults.</li>
  89.                       <li><b>[video: index=2 : width=320 : height:240]</b> - The third video uploaded to this node with dimensions of 320x240</li>
  90.                       <li><b>[thumbnail: index=1]</b> - The thumbnail for the 2nd video uploaded to this node.</li>
  91.                       <li><b>[video: autostart=false]</b> - The first video uploaded to this node will not start automatically.</li>
  92.                     </ul><br/>');
  93.          $output .= '<h2>' . t('Importing Videos') . '</h2>';
  94.          $output .= '<p>' . t('The FlashVideo module has also included a way for someone to import a large number of videos by just placing them in a directory (using FTP or some other means).  Here is how it works.  Within the <strong>files</strong> directory, simply create a new directory and name it <strong>video_import</strong> (or else defined within the FlashVideo Settings page).  Then, whatever video files you place within that directory will not only be added to the Drupal Files database, but also be added to the FlashVideo cron cycle conversion queue.  This makes it VERY simple for a site administrator to add MANY videos to their site without having to upload them individually to a node.') . '</p><br/>';
  95.          $output .= '<h2>' . t('Using the FlashVideo API') . '</h2>';
  96.          $output .= '<p>' . t('As of version 2.2, FlashVideo has introduced a new API that allows for developers to hook into the FlashVideo system to add specific conversion utilities besides the previous default of FFMPEG.  It does this through the use of two new Hooks that can be used to override how the FlashVideo module performs its conversion routine.  These hooks are as follows...') . '</p>';
  97.          
  98.          $header = array(t('Hook Name'), t('Description'));
  99.                         $rows[] = array(t('<b>flashvideo_submit</b>'), t('This hook gets invoked when the user presses the Submit button on a node insertion and update.  The default parameters are passed to this hook.') );
  100.                         $rows[] = array(t('<b>flashvideo_get_params</b>'), t('This hook gets invoked just before the actual conversion is performed allowing you to override any of the default parameters.') );
  101.                         $rows[] = array(t('<b>flashvideo_save_file</b>'), t('This hook gets invoked when the FlashVideo module has finished converting the FLV video and is saving it in the database.') );
  102.                         $rows[] = array(t('<b>flashvideo_get_file</b>'), t('This hook allows other modules to catch the FlashVideo module right before it sets the filepath of the video allowing them to override the path of the video.  Great for external storage plugins.') );
  103.                         $rows[] = array(t('<b>flashvideo_delete_file</b>'), t('This hook gets invoked when the FlashVideo module is deleting a file from the database.') );
  104.                         $output .= '<br/>' . theme('table', $header, $rows) . '<br/>';
  105.                         $rows = array();
  106.                         $output .= '<p>' . t('The following table is a list of all parameters that can be overidden within these hooks.') . '</p>';
  107.                         $header = array(t('Parameter Name'), t('Type'), t('Description'));
  108.                         $rows[] = array(t('<b>output_dir</b>'), t('Text'), t('Used to command the output directory.  This is relative to the system files directory.') );
  109.                         $rows[] = array(t('<b>cmd_path</b>'), t('Text'), t(' Used to specify the CWD path to the conversion utility executable.  Be sure to include the executable in the path.  Example <em>/usr/bin/ffmpeg</em>') );
  110.                         $rows[] = array(t('<b>video_args</b>'), t('Text'), t('The arguments given to the conversion utility executable to generate a video.  The same format should be used as in the FlashVideo Settings.') );
  111.                         $rows[] = array(t('<b>thumb_args</b>'), t('Text'), t(' The arguments given to the ffmpeg executable to generate a thumbnail.  The same format should be used as in the FlashVideo Settings.') );
  112.                         $rows[] = array(t('<b>thumbsize</b>'), t('Text'), t('The thumbnail size specified in the following format "WIDTH x HEIGHT".  Example <em>130x100</em>') );
  113.                         $rows[] = array(t('<b>thumbwidth</b>'), t('Integer'), t('The thumbnail width.') );
  114.                         $rows[] = array(t('<b>thumbheight</b>'), t('Integer'), t('The thumbnail height.') );
  115.                         $rows[] = array(t('<b>thumbtime</b>'), t('Text'), t('The amount of time to delay before taking a snapshot of the video. Denoted as "00:00:00"') );
  116.                         $rows[] = array(t('<b>thumbsecs</b>'), t('Integer'), t('The amount of seconds to delay before taking a snapshot of the video.') );
  117.                         $rows[] = array(t('<b>thumbext</b>'), t('Text'), t('The extension of the output thumbnail.  Example: For JPG\'s this would be <em>jpg</em>') );
  118.                         $rows[] = array(t('<b>videoext</b>'), t('Text'), t('The extension of the output video.  Example: For output FLV\'s, this would be <em>flv</em>') );
  119.                         $rows[] = array(t('<b>videomime</b>'), t('Text'), t('The mime type of the output video.') );
  120.                        
  121.                         $output .= '<br/>' . theme('table', $header, $rows) . '<br/>';  
  122.                         $output .= '<p>' . t('Please Refer to the FlashVideo CCK plugin to observe how to utilize this new API.') . '</p>';      
  123.          
  124.          return $output;
  125.       case 'admin/settings/modules#description':  
  126.          return t('Allows you to insert videos into nodes.');
  127.    }
  128. }
  129.  
  130. /**
  131.  * Implementation of hook_perm().
  132.  */
  133. function flashvideo_perm() {
  134.    return array('administer flashvideo');
  135. }
  136.  
  137. /**
  138.  * Checks all of their PHP settings to make sure that their PHP directives are all set according to the recommended settings.
  139.  */
  140.  
  141. function _flashvideo_get_php_settings() {
  142.    $file_uploads           =  ini_get('file_uploads');         // Whether or not to allow HTTP file uploads
  143.    $post_max_size          =  ini_get('post_max_size');        // Get their Max Post size.
  144.    $upload_max_filesize    =  ini_get('upload_max_filesize');  // Get their Max Upload size.
  145.    $max_execution_time     =  ini_get('max_execution_time');   // Get their Max Execution Time.
  146.    $max_input_time         =  ini_get('max_input_time');       // This sets the maximum time in seconds a script is allowed to parse input data, like POST, GET and file uploads
  147.    
  148.    // Give them an error if they have file uploads turned off.
  149.    if($file_uploads != "1") {
  150.       drupal_set_message('File uploads (file_uploads) are not enabled in your php.ini file. The FlashVideo module will not work unless this directive is set.', 'error');
  151.    }
  152.    
  153.    $output = '<p><b>IMPORTANT NOTE:</b>&nbsp;&nbsp;In order for the FlashVideo module to work according to design, ';
  154.    $output .= 'some parameters need to be set in your <b>php.ini</b> file or the root <b>.htaccess</b> file.  These parameters are as follows...</p>';
  155.    $output .= '<p style="padding-left: 10px;"><ul>';
  156.    $output .=  '<li><em>post_max_size</em> - The maximum allowed POST size.  Must be greater than or equal to Maximum Upload Size.</li>';
  157.    $output .=  '<li><em>upload_max_filesize</em> - The maximum allowed file upload size.</li>';
  158.    $output .=  '<li><em>max_execution_time</em> - The maximum allowed time (in seconds) that a script is allowed to run.  Needed for long file conversions.</li>';
  159.    $output .=  '<li><em>max_input_time</em> - The maximum time (in seconds) a script is allowed to parse input data, like POST, GET and file uploads.  Needed to keep large uploads from timing out.</li>';  
  160.    $output .= '</ul></p>';
  161.    $output .= '<p>The following shows the recommended values for these parameters followed by your current settings.</p>';
  162.    $output .= '<p style="padding-left: 10px;"><ul>';
  163.    $output .=     '<li><b>Recommended Settings:</b><br/>';
  164.    $output .=        '<ul>';
  165.    $output .=           '<li><em>post_max_size=100M</em></li>';
  166.    $output .=           '<li><em>upload_max_filesize=100M</em></li>';
  167.    $output .=           '<li><em>max_execution_time=1000</em></li>';
  168.    $output .=           '<li><em>max_input_time=1000</em></li>';  
  169.    $output .=        '</ul>';
  170.    $output .=     '</li>';
  171.    $output .=     '<li><b>Your current Settings:</b><br/>';
  172.    $output .=        '<ul>';  
  173.    $output .=           '<li><em>post_max_size='. $post_max_size .'</em></li>';
  174.    $output .=           '<li><em>upload_max_filesize='. $upload_max_filesize .'</em></li>';
  175.    $output .=           '<li><em>max_execution_time='. $max_execution_time .'</em></li>';
  176.    $output .=           '<li><em>max_input_time='. $max_input_time .'</em></li>';  
  177.    $output .=        '</ul>';
  178.    $output .=     '</li>';
  179.    $output .= '</ul></p>';
  180.    $output .= '<p><b>Warning:  Please consult your hosting provider or a professional before making the Recommeneded changes.  Drupal or the writers of the FlashVideo module will not be held responsible for any malfunctions due to this change.  Change these PHP settings at your own risk!</b></p><br/>';
  181.    
  182.    return $output;
  183. }
  184.  
  185. /**
  186.  *    Extracts the [FileType, MimeType, Player] string into an array.
  187.  */
  188.  
  189. function flashvideo_get_allowed_filetypes() {
  190.    $filestring = flashvideo_variable_get(NULL, 'flashvideo_video_filetypes', FLASHVIDEO_FILETYPE_STRING);
  191.    $filetypes = preg_split("/[\n\r]+/", $filestring);                // Split the file infos.
  192.    $filearray = array();                                             // Default our File Array.
  193.    if(count($filetypes)) {                                          
  194.       foreach($filetypes as $filetype) {                             // Iterate through our filetypes.
  195.          $filetype = preg_replace("/[\s\[\]]+/", "", $filetype);     // Replace all white space and brackets.
  196.          $fileinfo = explode(",", $filetype);                        // Split the parameters in their own array.
  197.          if(count($fileinfo) == 3) {
  198.             $filearray[$fileinfo[0]]['mimetype']   = $fileinfo[1];   // Set the mime type of the file.
  199.             $filearray[$fileinfo[0]]['player']     = $fileinfo[2];   // Set the player of the file.
  200.          }
  201.       }
  202.    }
  203.    return $filearray;
  204. }
  205.  
  206. /**
  207.  * Implements play callback function from node menu
  208.  */
  209. function flashvideo_play($video) {
  210.    $filetype = $video['override'] ? 'flv' : _flashvideo_get_filetype($video['file']);
  211.    $filetypes = flashvideo_get_allowed_filetypes();
  212.    if(isset($filetypes[$filetype]) && $filetypes[$filetype]) {
  213.       return theme('flashvideo_play_' . $filetypes[$filetype]['player'], $video);
  214.    }
  215.    else {
  216.       return _flashvideo_get_filetype($video['file']) . ' filetypes are not supported';
  217.    }
  218. }
  219.  
  220. /**
  221.  *  Populates and returns a FlashVars string.
  222.  *
  223.  *  To allow for custom usage for the FlashVar string, the FlashVideo module has
  224.  *  put into place a method for creating custom FlashVar strings.  You can do this two
  225.  *  ways... by either specifying it within the FlashVideo Settings where it says "Custom FlashVars"
  226.  *  which will be used for that node type, or you can be more specific by using the [video] tag
  227.  *  for each video uploaded to that node using the following schema...
  228.  *
  229.  *          [video:flashvar|param=value]  
  230.  *
  231.  *      where "flashvar" indicates that the parameter is a FlashVar followed by a "|"
  232.  *      and then your FlashVar parameter and value.  For example, if I want to set my intro
  233.  *      image for my video as "intro.jpg", my [video] tag would look like the following...
  234.  *
  235.  *          [video : flashvar|image=intro.jpg]
  236.  *
  237.  *  If you wish to use the API function call, then all you will need to do then is just
  238.  *  add a sub array under 'flashvars' in the $params array like the following and then pass
  239.  *  that $params array to the "flashvideo_get_video" API call.
  240.  *
  241.  *          $params['flashvars']['parameter'] = value
  242.  *
  243.  */
  244.  
  245. function flashvideo_get_flashvars($video) {
  246.    
  247.    // Get the basic FlashVar string...
  248.    $flashvars = flashvideo_variable_get($video['nodetype'], 'flashvars', 'file=@video');
  249.    
  250.    $playlist = (strpos($video['file'], 'getplaylist') !== FALSE);
  251.    $output_dir = flashvideo_variable_get($video['nodetype'], 'outputdir', '');
  252.    $output_dir = ($output_dir == '') ? $output_dir : ($output_dir . '/');  
  253.    
  254.    // Determine the intro image for the video...
  255.    if(!isset($video['flashvars']['image']) && (strpos($flashvars, 'image') === FALSE)) {
  256.       if($playlist || (flashvideo_variable_get($video['nodetype'], 'introthumb', 1) == 0)) {
  257.          if(flashvideo_variable_get($video['nodetype'], 'introimg', '') != '') {
  258.             $video['flashvars']['image'] = check_url(file_create_url($output_dir . flashvideo_variable_get($video['nodetype'], 'introimg', '') ));  
  259.          }
  260.       }
  261.       else {
  262.          $video['flashvars']['image'] = check_url(str_replace(".flv", ".jpg", $video['file']));  
  263.       }  
  264.    }
  265.  
  266.    // If they have an intro image set, then we need to figure out how long to show it...
  267.    if(!isset($video['flashvars']['rotatetime']) && $video['flashvars']['image'] && (strpos($flashvars, 'rotatetime') === FALSE)) {
  268.       $video['flashvars']['rotatetime'] = flashvideo_variable_get($video['nodetype'], 'introtime', '3');
  269.    }
  270.      
  271.    // Set up the logo image...
  272.    if(!isset($video['flashvars']['logo']) && (flashvideo_variable_get