diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/video_customfields/video_customfields.info | 4 | ||||
-rw-r--r-- | plugins/video_customfields/video_customfields.module | 63 | ||||
-rw-r--r-- | plugins/video_ffmpeg_helper/README.txt | 42 | ||||
-rw-r--r-- | plugins/video_ffmpeg_helper/video_ffmpeg_helper.info | 5 | ||||
-rw-r--r-- | plugins/video_ffmpeg_helper/video_ffmpeg_helper.install | 93 | ||||
-rw-r--r-- | plugins/video_ffmpeg_helper/video_ffmpeg_helper.module | 469 | ||||
-rw-r--r-- | plugins/video_ffmpeg_helper/video_render.php | 124 | ||||
-rw-r--r-- | plugins/video_ffmpeg_helper/video_scheduler.php | 38 | ||||
-rw-r--r-- | plugins/video_image/video_image.info | 5 | ||||
-rw-r--r-- | plugins/video_image/video_image.module | 530 | ||||
-rw-r--r-- | plugins/video_multidownload/video_multidownload.info | 4 | ||||
-rw-r--r-- | plugins/video_multidownload/video_multidownload.module | 78 | ||||
-rw-r--r-- | plugins/video_optmetadata/video_optmetadata.info | 4 | ||||
-rw-r--r-- | plugins/video_optmetadata/video_optmetadata.module | 21 | ||||
-rw-r--r-- | plugins/video_params/video_params.info | 4 | ||||
-rw-r--r-- | plugins/video_params/video_params.module | 11 |
16 files changed, 1095 insertions, 400 deletions
diff --git a/plugins/video_customfields/video_customfields.info b/plugins/video_customfields/video_customfields.info index 9ef1537..0179566 100644 --- a/plugins/video_customfields/video_customfields.info +++ b/plugins/video_customfields/video_customfields.info @@ -1,5 +1,5 @@ -; $Id$ name = Video Custom Fields description = Enable addition of custom fileds on video nodes created by video module. -dependencies = video +dependencies[] = video package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_customfields/video_customfields.module b/plugins/video_customfields/video_customfields.module index 5b51c8e..97d8816 100644 --- a/plugins/video_customfields/video_customfields.module +++ b/plugins/video_customfields/video_customfields.module @@ -1,19 +1,20 @@ <?php -// $Id$ - /** * @file * Enable addition of custom fileds on video nodes created by video module. * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ /** * Implementation of hook_help(). */ -function video_customfields_help($section) { - switch ($section) { +function video_customfields_help($path, $arg) { + switch ($path) { case 'admin/settings/modules#description': return t('Enable addition of custom fileds on video nodes created by video module.'); } @@ -30,16 +31,36 @@ function video_customfields_perm() { /** * Implementation of hook_menu(). */ -function video_customfields_menu($may_cache) { +function video_customfields_menu() { $items = array(); +/* TODO + Non menu code that was placed in hook_menu under the '!$may_cache' block + so that it could be run during initialization, should now be moved to hook_init. + Previously we called hook_init twice, once early in the bootstrap process, second + just after the bootstrap has finished. The first instance is now called boot + instead of init. + + In Drupal 6, there are now two hooks that can be used by modules to execute code + at the beginning of a page request. hook_boot() replaces hook_boot() in Drupal 5 + and runs on each page request, even for cached pages. hook_boot() now only runs + for non-cached pages and thus can be used for code that was previously placed in + hook_menu() with $may_cache = FALSE: + + Dynamic menu items under a '!$may_cache' block can often be simplified + to remove references to arg(n) and use of '%<function-name>' to check + conditions. See http://drupal.org/node/103114. + + The title and description arguments should not have strings wrapped in t(), + because translation of these happen in a later stage in the menu system. +*/ + $may_cache=true; if ($may_cache) { - $items[] = array( - 'path' => 'admin/content/video/customfields', - 'title' => t('Customfields'), - 'description' => t('Administer video_customfields module settings'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('video_customfields_settings_form'), - 'access' => user_access('administer site configuration'), + $items['admin/content/video/customfields'] = array( + 'title' => 'Customfields', + 'description' => 'Administer video_customfields module settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('video_customfields_settings_form'), + 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); } @@ -116,20 +137,20 @@ function video_customfields_settings_form() { * We use this to add some custom fields to the video creation form. * Fields will be displayed only if field title is set on settings page. */ -function video_customfields_form_alter($form_id, &$form) { - +function video_customfields_form_alter(&$form, &$form_state, $form_id) { + if($form_id == 'video_node_form' && isset($form['video']) && user_access('insert custom fields')) { //get node object from form $node = $form['#node']; - + $title1 = variable_get('video_customfield1', ''); $title2 = variable_get('video_customfield2', ''); $title3 = variable_get('video_customfield3', ''); $title4 = variable_get('video_customfield4', ''); $title5 = variable_get('video_customfield5', ''); $title6 = variable_get('video_customfield6', ''); - + //Only display the custom fields group if atleast one field has a title. if ($title1 . $title2 . $title3 . $title4 . $title5 . $title6 != '') { $form['customfields'] = array('#type' => 'fieldset', '#title' => variable_get('video_customfieldtitle', 'Custom Fields'), '#collapsible' => TRUE, '#collapsed' => variable_get('video_customgroupcollapsed', FALSE), '#weight' => -17); @@ -245,3 +266,13 @@ function theme_video_customfields($node) { } +/** + * Implementation of hook_theme(). + */ +function video_customfields_theme() { + return array( + 'video_customfields' => array( + 'arguments' => array('node' => NULL), + ), + ); +} diff --git a/plugins/video_ffmpeg_helper/README.txt b/plugins/video_ffmpeg_helper/README.txt index e69de29..5b6788c 100644 --- a/plugins/video_ffmpeg_helper/README.txt +++ b/plugins/video_ffmpeg_helper/README.txt @@ -0,0 +1,42 @@ +FFMPEG Video.module helper +========================== + +This helper module facilitates uploading new videos using the video module. It +features a batch processing queue for videos to be transcoded and automatic +thumbnail generation. + +IMPORTANT: the ffmpeg helper currently only works on unix based environment. It currently doesn't support Windows based servers. + +Install instructions +-------------------- + +1. Activate the video_ffmpeg_helper module +2. Setup it's advanced options to meet your needs +3. Move (or symlink) video_render.php and video_scheduler.php into your Drupal root +4. Edit the first line of those files to meet your needs +5. Check permissions of the files and folders (/tmp/video and files/* must be writable by the webserver or the user executling the cron job) +6. You now have two options to execute the video_scheduler.php script: + + 6.1 (default) Enable the execution of video_scheduler.php using standard drupal cron. + + 6.2 Schedule the execution of video_scheduler.php using unix cron + + The crontab should look something like this: + + # m h dom mon dow user command + */20 * * * * www-data cd /absolute/path/to/drupal/ ; php video_scheduler.php http://www.example.com/path_to_drupal + + This will execute the video_scheduler every 20 minutes. + + Note that the video_scheduler doesn't produce any output and cannot be called + from the web. It will, however, put some information in the watchdog. + + + +Troubleshooting +------------------------ + +Configuring and installing ffmpeg in a web server environment might be pretty difficult. In order to help you troubleshoot the transcoding process the ffmpeg helper puts debugging informations on the drupal logs. I strongly suggest to have a look at them if you are experiencing problems with transcoding. + +The ffmpeg puts in the drupal logs the commands it was trying to execute. You might try to rerun them on a command shell in order understand what went wrong. + diff --git a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info index f2ed8e6..e5ce7aa 100644 --- a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info +++ b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info @@ -1,5 +1,6 @@ -; $Id$ name = Video ffmpeg Helper description = Provide apis for ffmpeg. Simplify video nodes creation. -dependencies = video video_upload +dependencies[] = video +dependencies[] = video_upload package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install index a8cedff..36289d5 100644 --- a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install +++ b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install @@ -1,40 +1,77 @@ <?php -// $Id$ - - /** * @file * Provide installation functions for video_ffmpeg_helper.module . * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ +/** + * Implementation of hook_schema(). + */ +function video_ffmpeg_helper_schema() { + $schema['video_rendering'] = array( + 'description' => t('TODO'), + 'fields' => array( + 'vid' => array( + 'description' => t('TODO'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'nid' => array( + 'description' => t('TODO'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'origfile' => array( + 'description' => t('TODO'), + 'type' => 'text', + 'not null' => TRUE, + 'default' => '', + ), + 'pid' => array( + 'description' => t('TODO'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'status' => array( + 'description' => t('TODO'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'started' => array( + 'description' => t('TODO'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'completed' => array( + 'description' => t('TODO'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('vid'), + ); + + return $schema; +} + function video_ffmpeg_helper_install() { - switch ($GLOBALS['db_type']) { - case 'mysql': - case 'mysqli': - db_query("CREATE TABLE {video_rendering} ( - vid int(10) unsigned NOT NULL default '0', - nid int(10) unsigned NOT NULL default '0', - origfile text NOT NULL default '', - pid int(10) unsigned NOT NULL default '0', - status int(1) unsigned NOT NULL default '0', - started int NOT NULL default '0', - completed int NOT NULL default '0', - PRIMARY KEY (vid) - ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;"); - break; - case 'pgsql': - db_query("CREATE TABLE {video_rendering} ( - vid integer NOT NULL default '0', - nid integer NOT NULL default '0', - origfile text NOT NULL default '', - pid integer NOT NULL default '0', - status integer NOT NULL default '1', - PRIMARY KEY (vid) - );"); - break; - } + // Create tables. + drupal_install_schema('video_ffmpeg_helper'); } diff --git a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module index c1f94ec..446058d 100644 --- a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module +++ b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module @@ -1,44 +1,85 @@ <?php -// $Id$ /** * @file * Provide some api for use ffmpeg. Simplify video nodes creation. * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ /** * Define some constants */ -define('VIDEO_RENDERING_PENDING', 0); +define('VIDEO_RENDERING_PENDING', 1); define('VIDEO_RENDERING_ACTIVE', 5); define('VIDEO_RENDERING_COMPLETE', 10); +define('VIDEO_RENDERING_FAILED', 20); + + + +function video_ffmpeg_helper_cron() { + global $base_url; + + if(variable_get('video_ffmpeg_helper_auto_cvr_cron', true)) { + exec("php video_scheduler.php $base_url > /dev/null &"); + } +} + + +/** + * Implementatio of hook_perm() +*/ +function video_ffmpeg_helper_perm() { + return array('bypass automatic video conversion'); +} /** * Implementation of hook_help(). */ -function video_ffmpeg_helper_help($section) { - switch ($section) { +function video_ffmpeg_helper_help($path, $arg) { + switch ($path) { case 'admin/modules#description': - return t('Enable thumbnails support for video module.'); + return t('Enable ffmpeg support for video module.'); } } /** * Implementation of hook_menu() */ -function video_ffmpeg_helper_menu($may_cache) { +function video_ffmpeg_helper_menu() { $items = array(); +/* TODO + Non menu code that was placed in hook_menu under the '!$may_cache' block + so that it could be run during initialization, should now be moved to hook_init. + Previously we called hook_init twice, once early in the bootstrap process, second + just after the bootstrap has finished. The first instance is now called boot + instead of init. + + In Drupal 6, there are now two hooks that can be used by modules to execute code + at the beginning of a page request. hook_boot() replaces hook_boot() in Drupal 5 + and runs on each page request, even for cached pages. hook_boot() now only runs + for non-cached pages and thus can be used for code that was previously placed in + hook_menu() with $may_cache = FALSE: + + Dynamic menu items under a '!$may_cache' block can often be simplified + to remove references to arg(n) and use of '%<function-name>' to check + conditions. See http://drupal.org/node/103114. + + The title and description arguments should not have strings wrapped in t(), + because translation of these happen in a later stage in the menu system. +*/ + $may_cache=true; if ($may_cache) { - $items[] = array( - 'path' => 'admin/content/video/ffmpeg_helper', - 'title' => t('Video ffmpeg Helper'), - 'description' => t('Administer video_ffmpeg_helper module settings'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('video_ffmpeg_helper_admin_settings'), - 'access' => user_access('administer site configuration'), + $items['admin/settings/video/ffmpeg_helper'] = array( + 'title' => 'Video ffmpeg Helper', + 'description' => 'Administer video_ffmpeg_helper module settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('video_ffmpeg_helper_admin_settings'), + 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); } @@ -48,23 +89,18 @@ function video_ffmpeg_helper_menu($may_cache) { /** * Validation for settings form */ -function video_ffmpeg_helper_admin_settings_validate($form_id, &$form_values, &$form) { - if ($form_values['video_ffmpeg_helper_auto_thumbnail']) { - if (function_exists('is_executable')) { - $test = 'is_executable'; - } else { - $test = 'file_exists'; - } - if (!$test($form_values['video_ffmpeg_helper_ffmpeg_path'])) { - form_set_error('video_image_ffmpeg_path', t('Set correct path for thumbnailer')); +function video_ffmpeg_helper_admin_settings_validate($form, &$form_state) { + if (variable_get('video_image_auto_thumbnail', 0)) { + if (!_video_ffmpeg_helper_check_exe_path($form_state['values']['video_ffmpeg_helper_ffmpeg_path'])) { + form_set_error('video_ffmpeg_helper_ffmpeg_path', t('Set correct path for ffmpeg')); } - if (!is_numeric($form_values['video_ffmpeg_helper_auto_thumbnail_seek'])) { + if (!is_numeric($form_state['values']['video_ffmpeg_helper_auto_thumbnail_seek'])) { form_set_error('video_ffmpeg_helper_auto_thumbnail_seek', t('Seek time must be an integer')); } - $options = $form_values['video_ffmpeg_helper_thumbnailer_options']; - if (!strstr($options, '%videofile') || !strstr($options, '%thumbfile')) { - form_set_error('video_ffmpeg_helper_thumbnailer_options', t('Thumbnail options must contain mandatory arguments %videofile and %thumbfile')); - } + $options = $form_state['values']['video_ffmpeg_helper_thumbnailer_options']; + if (!strstr($options, '%videofile') || !strstr($options, '%thumbfile')) { + form_set_error('video_ffmpeg_helper_thumbnailer_options', t('Thumbnail options must contain mandatory arguments %videofile and %thumbfile')); + } } } @@ -73,55 +109,43 @@ function video_ffmpeg_helper_admin_settings_validate($form_id, &$form_values, &$ * Settings form */ function video_ffmpeg_helper_admin_settings() { - // let's execute after video_image - if (module_exists('video_image')) { - if (variable_get('video_ffmpeg_helper_auto_thumbnail', 0)) { - $upload_weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_image'")); - db_query("UPDATE {system} SET weight=".($upload_weight+1)." WHERE name='video_ffmpeg_helper'"); - } + // let's execute after video_image and video_upload + if (module_exists('video_image') && variable_get('video_image_auto_thumbnail', 0)) { + $weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_image'")); + } else { // video_image might be disabled.. execute after video_upload + $weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_upload'")); } - + // update the weight in the system table + db_query("UPDATE {system} SET weight=".($weight+1)." WHERE name='video_ffmpeg_helper'"); + $form['video_ffmpeg_helper_ffmpeg_path'] = array( '#type' => 'textfield', '#title' => t('FFmpeg executable path'), '#description' => t('Set the full path to the ffmpeg executable here.'), '#default_value' => variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg'), ); - - + + $form['video_ffmpeg_helper_auto_resolution'] = array( '#type' => 'checkbox', '#title' => t('Enable resolution helper'), - '#description' => t('Use ffmpeg Helper to automaticcally get the resolution from the video.'), + '#description' => t('Use ffmpeg Helper to automatically get the resolution from the video.'), '#default_value' => variable_get('video_ffmpeg_helper_auto_resolution', false), ); - + $form['video_ffmpeg_helper_auto_playtime'] = array( '#type' => 'checkbox', '#title' => t('Enable playtime helper'), '#description' => t('Use ffmpeg Helper to automaticcally get the playtime from the video.'), '#default_value' => variable_get('video_ffmpeg_helper_auto_playtime', false), ); - + $form['autothumb'] = array( '#type' => 'fieldset', '#title' => t('Automatic video thumbnailing'), '#collapsible' => TRUE, '#collapsed' => TRUE ); - $form['autothumb']['video_ffmpeg_helper_auto_thumbnail'] = array( - '#type' => 'checkbox', - '#title' => t('Auto thumbnail for videos'), - '#description' => t('If set up correctly, this will auto-generate a thumbnail for each video created.'), - '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail', false), - ); - $form['autothumb']['video_ffmpeg_helper_auto_thumbnail_only'] = array( - '#type' => 'checkbox', - '#title' => t('Use auto-thumbnailer exclusively for video images'), - '#description' => t('If checked, this will disable the file upload box for the user-supplied thumbnail. Only check this if you have checked to be sure that auto-thumbnailing works. Auto thumbnail must be selected for this to be enabled.'), - '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail_only', false), - '#disabled' => !variable_get('video_ffmpeg_helper_auto_thumbnail', false), - ); $form['autothumb']['video_ffmpeg_helper_thumbnailer_options'] = array( '#type' => 'textfield', '#title' => t('Video thumbnailer options'), @@ -134,12 +158,6 @@ function video_ffmpeg_helper_admin_settings() { '#description' => t('Time in seconds to seek into video before extracting the thumbnail'), '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail_seek', 2), ); - $form['autothumb']['video_ffmpeg_helper_auto_thumbnail_debug'] = array( - '#type' => 'checkbox', - '#title' => t('Debug auto-thumbnail process'), - '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail_debug', false), - ); - // automatic video conversion settings $form['autoconv'] = array( '#type' => 'fieldset', @@ -147,10 +165,16 @@ function video_ffmpeg_helper_admin_settings() { '#collapsible' => TRUE, '#collapsed' => TRUE ); + $form['autoconv']['video_ffmpeg_helper_auto_cvr_cron'] = array( + '#type' => 'checkbox', + '#title' => t('Use drupal cron for autoconversion'), + '#description' => t('Click this if you want to execute the video_scheduler.php from the standard drupal cron. If you want to use distributed encodings you might want to disable this.'), + '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_cron', true), + ); $form['autoconv']['video_ffmpeg_helper_auto_conversion'] = array( '#type' => 'checkbox', '#title' => t('Auto conversion for videos'), - '#description' => t('If set up correctly, this will auto-convert each uploaded video to the configured format.') . '<br />' . t("IMPORTANT: you will need the video_render.php correctly configured and run by cron. See README.txt for more informations."), + '#description' => t('If set up correctly, this will auto-convert each uploaded video to the configured format.') . '<br />' . t("IMPORTANT: you will need the video_render.php correctly configured and run by cron. See README.txt in the video_ffmpeg_helper folder for more informations."), '#default_value' => variable_get('video_ffmpeg_helper_auto_conversion', false), ); $form['autoconv']['video_ffmpeg_helper_auto_cvr_width'] = array( @@ -164,24 +188,18 @@ function video_ffmpeg_helper_admin_settings() { $form['autoconv']['video_ffmpeg_helper_auto_cvr_video_bitrate'] = array( '#type' => 'textfield', '#title' => t('Video bitrate'), - '#description' => t('The video bitrate in kbit/s of the converted video.'), - '#size' => 3, - '#maxlength' => 4, - '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_video_bitrate', 200), + '#description' => t('The video bitrate in bit/s of the converted video.'), + '#size' => 10, + '#maxlength' => 10, + '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_video_bitrate', 200000), ); $form['autoconv']['video_ffmpeg_helper_auto_cvr_audio_bitrate'] = array( '#type' => 'textfield', '#title' => t('Audio bitrate'), - '#description' => t('The audio bitrate in kbit/s of the converted video.'), - '#size' => 3, - '#maxlength' => 4, - '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_audio_bitrate', 64), - ); - $form['autoconv']['video_ffmpeg_helper_auto_cvr_busy_video_path'] = array( - '#type' => 'textfield', - '#title' => t('Busy video path'), - '#description' => t('Provide the relative path to a video displayed when the video is being rendered.'), - '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_busy_video_path', 'busy.flv'), + '#description' => t('The audio bitrate in bit/s of the converted video.'), + '#size' => 10, + '#maxlength' => 10, + '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_audio_bitrate', 64000), ); $form['autoconv']['advanced'] = array( '#type' => 'fieldset', @@ -197,8 +215,8 @@ function video_ffmpeg_helper_admin_settings() { '<li>'.t('%convertfile (a newly created file to store the converted file)'). '<li>'.t('%size (video resolution of the converted file)'). '</ul>'. - t('For further informations refer to the !ffmpegdoc', array('!ffmpegdoc' => l(t('Official FFMpeg documentation.'), 'http://ffmpeg.mplayerhq.hu/ffmpeg-doc.html', NULL, NULL, TRUE))), - '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate %convertfile'), + t('For further informations refer to the !ffmpegdoc', array('!ffmpegdoc' => l(t('Official FFMpeg documentation.'), 'http://ffmpeg.mplayerhq.hu/ffmpeg-doc.html', array('fragment' => TRUE)))), + '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate -qscale 1 %convertfile'), ); return system_settings_form($form); } @@ -207,8 +225,10 @@ function video_ffmpeg_helper_admin_settings() { /** * Implementation of hook_form_alter() */ -function video_ffmpeg_helper_form_alter($form_id, &$form) { +function video_ffmpeg_helper_form_alter(&$form, &$form_state, $form_id) { + $node = $form['#node']; + //print_r($form); if($form_id == 'video_node_form') { @@ -216,19 +236,16 @@ function video_ffmpeg_helper_form_alter($form_id, &$form) { _image_check_settings(); $form['#attributes'] = array("enctype" => "multipart/form-data"); - if (variable_get('video_ffmpeg_helper_auto_thumbnail_only', false)) { - // delete the video image parts - $form['image'] = NULL; - } } - if(variable_get('video_ffmpeg_helper_auto_resolution', false) || variable_get('video_ffmpeg_helper_auto_convert', false)) { - $form['video']['videox'] = NULL; - $form['video']['videoy'] = NULL; - } - if(variable_get('video_ffmpeg_helper_auto_playtime', false)) { - $form['video']['playtime'] = NULL; + if($node->vtype == 'upload' && user_access('bypass automatic video conversion') && variable_get('video_ffmpeg_helper_auto_conversion', false)) { + $form['video']['video_ffmpeg_helper_convertion_bypass'] = array( + '#type' => 'checkbox', + '#title' => t('Bypass automatic video conversion'), + '#description' => t('Check this if you want that your video is submitted as it is, without being converted.'), + '#default_value' => $node->video_ffmpeg_helper_convertion_bypass, // for node previews + ); } } @@ -237,42 +254,80 @@ function video_ffmpeg_helper_form_alter($form_id, &$form) { /** * Implementation of hook_nodeapi() + * + * NOTE: video_ffmpeg nodeapi is executed after video_player rendering */ function video_ffmpeg_helper_nodeapi(&$node, $op, $teaser) { - if($node->type == 'video') { - + if($node->type == 'video' && $node->vtype == 'upload') { switch ($op) { - case 'load': - ; // for future uses - break; - - case 'submit': + case 'load': + // let's check if we have a valid encoded video + if(isset($node->serial_data['video_encoded_fid']) && + is_numeric($node->serial_data['video_encoded_fid']) && + $node->serial_data['video_encoded_fid'] > 0) { + // this video have an encoded version. let's use it insted of the original one. We can safely do this as video_ffmpeg_helper will be scheduled by Drupal after video and video_upload modules + $output = array(); + $file = _video_upload_get_file($node->serial_data['video_encoded_fid']); + $output['current_video_rendered_file'] = $file; + $output['vidfile'] = file_create_url($file->filepath); + // set the filesize + $output['size'] = $file->filesize; + + return $output; + } + //print $node->serial_data['video_encoded_fid']; die; + if(variable_get('video_ffmpeg_helper_auto_resolution', false) || variable_get('video_ffmpeg_helper_auto_playtime', false)) { _video_ffmpeg_helper_get_video_info($node); } - break; - - case 'insert': + + case 'submit': + break; + + case 'update': + /* delete the already existing batch script, we'll recreate it below */ if(variable_get('video_ffmpeg_helper_auto_conversion', false)) { + db_query('DELETE FROM {video_rendering} WHERE vid = %d AND nid = %d', $node->vid, $node->nid); + } + /* FALLTHROUGH */ + case 'insert': + if(variable_get('video_ffmpeg_helper_auto_conversion', false) && $node->new_video_upload_file_fid > 0 && !$node->video_ffmpeg_helper_convertion_bypass) { // add rendering job to queue _video_ffmpeg_helper_add_rendering($node); } - + break; - + case 'prepare': ; // for future uses break; case 'view': - ; // for future uses + if($teaser == FALSE) { + if(_video_ffmpeg_helper_is_being_processed($node)) { + // if the video is still being processed we display a "rendering in progress" message + $node->content['video_player']['#value'] = theme('video_ffmpeg_helper_inprogress', $node); + } + else if($node->serial_data['video_encoded_fid'] == -1) { // conversion failed + $node->content['video_player']['#value'] = theme('video_ffmpeg_helper_encoding_failed', $node); + } + } + //print_r($node); die; break; + case 'alter': + ; // for future uses + break; + case 'delete': db_query('DELETE FROM {video_rendering} WHERE vid = %d AND nid = %d', $node->vid, $node->nid); + if($node->serial_data['video_encoded_fid'] > 0) { + $file = _video_upload_get_file($node->serial_data['video_encoded_fid']); + _video_upload_delete_file($file); + } break; - + } } } @@ -282,14 +337,29 @@ function video_ffmpeg_helper_nodeapi(&$node, $op, $teaser) { * Add a video conversion rendering process to the queue */ function _video_ffmpeg_helper_add_rendering(&$node) { - $file = $_SESSION['video_upload_file_stored']->filepath; + $file = _video_upload_get_file($node->new_video_upload_file_fid); //print_r($node); die; - db_query('INSERT INTO {video_rendering} (vid, nid, origfile, pid, status, started, completed) VALUES (%d, %d, "%s", %d, %d, %d, %d)', $node->vid, $node->nid, $file, 0, VIDEO_RENDERING_PENDING, 0, 0); + db_query('INSERT INTO {video_rendering} (vid, nid, origfile, pid, status, started, completed) VALUES (%d, %d, "%s", %d, %d, %d, %d)', $node->vid, $node->nid, $file->filepath, 0, VIDEO_RENDERING_PENDING, 0, 0); + + drupal_set_message(t('Video submission queued for processing. Please wait: our servers are preparing your video for web displaying.')); // let's add the rendering in progress video $node->vidfile = variable_get('video_ffmpeg_helper_auto_cvr_busy_video_path', 'busy.flv'); db_query('UPDATE {video} SET vidfile = "%s" WHERE nid=%d AND vid=%d', $node->vidfile, $node->nid, $node->vid); - + +} + + +/** + * Returns true if the video is being encoded or queeded +*/ +function _video_ffmpeg_helper_is_being_processed($node) { + $result = db_query("SELECT status FROM {video_rendering} WHERE vid = %d AND nid = %d", $node->vid, $node->nid); + $status = db_result($result); + if($status == VIDEO_RENDERING_PENDING || $status == VIDEO_RENDERING_ACTIVE) { // video is still being converted + return TRUE; + } + return FALSE; } @@ -297,62 +367,94 @@ function _video_ffmpeg_helper_add_rendering(&$node) { /** * Get some informations from the video file */ -function _video_ffmpeg_helper_get_video_info(&$node) { +function _video_ffmpeg_helper_get_video_info(&$node, $value=null) { + static $ffmpeg_info; + + if (isset($value)) { + $ffmpeg_info[$node->nid] = $value; + return; + } + + $fileobj = $node->new_video_upload_file ? $node->new_video_upload_file : _video_upload_get_file($node->new_video_upload_file_fid); + + // check if we have some info in the cache for the given node + if(isset($ffmpeg_info[$fileobj->filename])) { + return $ffmpeg_info[$fileobj->filename]; + } + // escape file name for safety - $file = escapeshellarg($_SESSION['video_upload_file']->filepath); + $file = escapeshellarg($fileobj->filepath); // create the full command to execute $command = variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg') . ' -i ' . $file; - - drupal_set_message('executing' . $command); - + //execute the command ob_start(); passthru($command." 2>&1", $command_return); $command_output = ob_get_contents(); ob_end_clean(); - // print $command_output; + // cache the result for further calls + $ffmpeg_info[$node->nid] = $command_output; + return $command_output; +} + + +/** + * Return the video resolution + */ +function _video_ffmpeg_helper_auto_resolution(&$node) { + if(!$node->new_video_upload_file && !$node->new_video_upload_file_fid) { // no new files uploaded. skipping auto resolution process + return null; + } + if(variable_get('video_ffmpeg_helper_auto_resolution', false)) { + + // call ffmpeg -i + $ffmpeg_output = _video_ffmpeg_helper_get_video_info($node); + // get resolution - $pattern = '/[0-9]{2,4}x[0-9]{2,4}/'; - preg_match_all($pattern, $command_output, $matches, PREG_PATTERN_ORDER); - $resolution = $matches[0][0]; - $xy = explode("x", $resolution); - - // store resolution information to the node object - $node->videox = $xy[0]; - $node->videoy = $xy[1]; + $pattern = '/Video: .*, ([0-9]{2,4}x[0-9]{2,4})/'; + preg_match_all($pattern, $ffmpeg_output, $matches, PREG_PATTERN_ORDER); + $resolution = $matches[1][0]; + + return explode("x", $resolution); } - - + return null; +} + + +/** + * Return the playtime seconds of a video +*/ +function _video_ffmpeg_helper_auto_playtime(&$node) { + if(variable_get('video_ffmpeg_helper_auto_playtime', false)) { - // get playtime - $pattern = '/[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]/'; - preg_match_all($pattern, $command_output, $matches, PREG_PATTERN_ORDER); - $playtime = $matches[0][0]; - // ffmpge return lenght as 00:00:31.1 Let's get playtime from that - $hmsmm = explode(":", $playtime); + // call ffmpeg -i + $ffmpeg_output = _video_ffmpeg_helper_get_video_info($node); + // get playtime + $pattern = '/Duration: ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9])/'; + preg_match_all($pattern, $ffmpeg_output, $matches, PREG_PATTERN_ORDER); + $playtime = $matches[1][0]; + + // ffmpeg return lenght as 00:00:31.1 Let's get playtime from that + $hmsmm = explode(":", $playtime); + $tmp = explode(".", $hmsmm[2]); $seconds = $tmp[0]; - + $hours = $hmsmm[0]; $minutes = $hmsmm[1]; - - $node->playtime_seconds = $seconds + ($hours * 3600) + ($minutes * 60); + return $seconds + ($hours * 3600) + ($minutes * 60); } - - //print_r($node); die; - } - - -/* Generates a thumbnail from the video file +/** + * Generates a thumbnail from the video file * * @param $node * object with node information @@ -361,54 +463,103 @@ function _video_ffmpeg_helper_get_video_info(&$node) { * a drupal file object */ function _video_ffmpeg_helper_auto_thumbnail(&$node) { - if(empty($_SESSION['video_upload_file']) || - !$_SESSION['video_upload_file']->newfile || - $node->iid || $_SESSION['video_upload_file']->iid || - $_SESSION['video_upload_file']->thumbnailed) { - if (variable_get('video_image_auto_thumbnail_debug', false)) { - if (empty($_SESSION['video_upload_file'])) - drupal_set_message(t('no video has been uploaded: make sure that video_image weight is greater than video_upload weight; make sure that the video file is not too large to be uploaded.')); - } - return null; + if (!$node->new_video_upload_file || + ($node->new_video_upload_file && count($_POST) && $_POST['new_video_upload_file_fid'])) { + // we have already thumbnailed this new upload file + return NULL; } - $debug = variable_get('video_image_auto_thumbnail_debug', false); - $videofile = escapeshellarg($_SESSION['video_upload_file']->filepath); + if (!$node->new_video_upload_file && $node->current_video_upload_file_fid) { // no new files uploaded. skipping thumnailing stuff + _video_image_thumbnail_debug(t('No new files to thumbnail')); + return NULL; + } + // gets the newly uploaded file object + $uploaded_file = $node->new_video_upload_file; + + // are we debugging? + // escape the filename for safety + $videofile = escapeshellarg($uploaded_file->filepath); + // let's create a temp filename into the drupal temp directory $thumbfile = tempnam(file_directory_temp(), 'tnail-thumb'); - $seek = variable_get('video_image_auto_thumbnail_seek', 2); + // get ffmpeg configurations + $seek = variable_get('video_ffmpeg_helper_auto_thumbnail_seek', 2); $tnail = variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg'); $options = preg_replace(array('/%videofile/', '/%thumbfile/', '/%seek/'), array($videofile, $thumbfile, $seek), variable_get('video_image_thumbnailer_options', '-i %videofile -an -y -f mjpeg -ss %seek -vframes 1 %thumbfile')); + // executes the command $command = "$tnail $options"; ob_start(); passthru($command." 2>&1", $tnail_return); $tnail_output = ob_get_contents(); ob_end_clean(); + _video_ffmpeg_helper_get_video_info($node, $tnail_output); - if ($debug) { - drupal_set_message(t('Thumbnailer command: ').$command); - drupal_set_message(t('Thumbnailer output: ')."<pre>\n$tnail_output\n</pre>"); - } + _video_image_thumbnail_debug(t('Thumbnailer command: ').$command); + _video_image_thumbnail_debug(t('Thumbnailer output: ')."<pre>\n$tnail_output\n</pre>"); if (!file_exists($thumbfile)) { - drupal_set_message(t('video_image_auto_thumbnail: file %file does not exist', array('%file' => $thumbfile)), 'error'); + $error_param = array( + '%file' => $thumbfile, + '%cmd' => $command, + '%out' => $tnail_output, + ); + $error_msg = t("error generating thumbnail for video: generated file %file does not exist.<br />Command Executed:<br />%cmd<br />Command Output:<br />%out", $error_param); + // let's log this + watchdog('video_ffmpeg_helper',$error_msg); + return false; } $file = array( - 'filename' => $_SESSION['video_upload_file']->filename . ".video-thumb.jpg", + 'filename' => $uploaded_file->filename . ".video-thumb.jpg", 'filemime' => 'image/jpeg', 'filesize' => filesize($thumbfile), 'filepath' => $thumbfile, 'nid' => $node->nid, ); - $_SESSION['video_upload_file']->thumbnailed = TRUE; - if ($debug) { - if ($tnail_return) { - drupal_set_message(t('Failed to thumbnail video')); - } else { - drupal_set_message(t('Successfully thumbnailed video')); - } + + if ($tnail_return) { + _video_image_thumbnail_debug(t('Failed to thumbnail video')); + return $false; } + _video_image_thumbnail_debug(t('Successfully thumbnailed video')); return (object)$file; } +function _video_ffmpeg_helper_check_exe_path($path=NULL) { + if (!$path) { + $path = variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg'); + } + if (function_exists('is_executable')) { + $test = 'is_executable'; + } else { + $test = 'file_exists'; + } + return $test($path); +} + +/** + * Displays a "encoding in progress message" +*/ +function theme_video_ffmpeg_helper_inprogress($node) { + return '<div class="video-ffmpeg-helper-inprogress">'. t('This video is currently being processed. Please wait.') . '</div>'; +} + +/** + * Display an "encoding failed" message" +*/ +function theme_video_ffmpeg_helper_encoding_failed($node) { + return '<div class="video-ffmpeg-helper-encoding-failed">'. t('The video conversion process has failed. You might want to submit a simpler video format like <em>mpeg</em> or <em>divx avi</em>.<br />If the problem persists please contact website administrators.') . '</div>'; +} +/** + * Implementation of hook_theme(). + */ +function video_ffmpeg_helper_theme() { + return array( + 'video_ffmpeg_helper_encoding_failed' => array( + 'arguments' => array('node' => NULL), + ), + 'video_ffmpeg_helper_inprogress' => array( + 'arguments' => array('node' => NULL), + ), + ); +} diff --git a/plugins/video_ffmpeg_helper/video_render.php b/plugins/video_ffmpeg_helper/video_render.php index a1747a3..bba9220 100644 --- a/plugins/video_ffmpeg_helper/video_render.php +++ b/plugins/video_ffmpeg_helper/video_render.php @@ -1,12 +1,18 @@ <?php -// $Id$ /** * @file * Renders a video. This script is called concurrently by video_scheduler.php * This script has to be launched with "php video_render.php nid vid" + * If you are not using sites/default/settings.php as your settings file, + * add an optional parameter for the drupal site url: + * "php video_render.php nid vid http://example.com/" or + * "php video_render.php nid vid http://example.org/drupal/" * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ @@ -19,7 +25,7 @@ define('VIDEO_RENDERING_FFMPEG_PATH', '/usr/bin/ffmpeg'); // set to the temp file path. //IMPORTANT: the user who runs this script must have permissions to create files there. If this is not the case the default php temporary folder will be used. -define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video'); +define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video'); // number of conversion jobs active at the same time define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5); @@ -36,12 +42,18 @@ define('VIDEO_RENDERING_NICE', 'nice -n 19'); /** * Define some constants */ -define('VIDEO_RENDERING_PENDING', 0); +define('VIDEO_RENDERING_PENDING', 1); define('VIDEO_RENDERING_ACTIVE', 5); define('VIDEO_RENDERING_COMPLETE', 10); +define('VIDEO_RENDERING_FAILED', 20); +if (isset($_SERVER['argv'][3])) { + $url = parse_url($_SERVER['argv'][3]); + $_SERVER['SCRIPT_NAME'] = $url['path']; + $_SERVER['HTTP_HOST'] = $url['host']; +} -include_once './includes/bootstrap.inc'; +module_load_include('/includes/bootstrap.inc', 'video_render', 'includes/bootstrap'); // disable error reporting for bootstrap process error_reporting(E_ERROR); // let's bootstrap: we will be able to use drupal apis @@ -52,8 +64,8 @@ error_reporting(E_ALL); // allow execution only from the command line! if(empty($_SERVER['REQUEST_METHOD'])) { - if($_SERVER['argc'] != 3) { // check for command line arguments - watchdog('video_render', t('Incorrect parameters to the video_render.php script.', WATCHDOG_ERROR)); + if($_SERVER['argc'] < 3) { // check for command line arguments + watchdog('video_render', 'Incorrect parameters to the video_render.php script.', WATCHDOG_ERROR); print t('Incorrect parameters'); } else { @@ -69,29 +81,36 @@ print("\n"); function video_render_main() { + // get parameters passed from command line + $nid = $_SERVER['argv'][1]; + $vid = $_SERVER['argv'][2]; + // set the status to active - _video_render_job_change_status($_SERVER['argv'][1], $_SERVER['argv'][2], VIDEO_RENDERING_ACTIVE); - $job = _video_render_load_job($_SERVER['argv'][1], $_SERVER['argv'][2], VIDEO_RENDERING_ACTIVE); + _video_render_job_change_status($nid, $vid, VIDEO_RENDERING_ACTIVE); + // load the job object + $job = _video_render_load_job($nid, $vid, VIDEO_RENDERING_ACTIVE); if($job == NULL) { - watchdog('video_render', t('video_render.php has been called with an invalid job resource. exiting.')); + watchdog('video_render', 'video_render.php has been called with an invalid job resource. exiting.'); die; } $command = _video_render_get_command($job); - - //print('executing ' . $command); - watchdog('video_render', t('executing: ') . $command); - + + //print('executing ' . $command); die; + watchdog('video_render', 'executing: ' . $command); + //execute the command ob_start(); passthru($command." 2>&1", $command_return); $command_output = ob_get_contents(); ob_end_clean(); - + //print $command_output; - - if (!file_exists($job->convfile)) { - watchdog('video_render', t('video conversion failed. ffmpeg reported the following output: ' . $command_output, WATCHDOG_ERROR)); + + if (!file_exists($job->convfile) || !filesize($job->convfile)) { + watchdog('video_render', 'video conversion failed. ffmpeg reported the following output: ' . $command_output, WATCHDOG_ERROR); + _video_render_set_video_encoded_fid($job->nid, $job->vid, -1); + _video_render_job_change_status($job->nid, $job->vid, VIDEO_RENDERING_FAILED); } else { // move the video to the definitive location @@ -106,31 +125,65 @@ function video_render_main() { $file = ((object) $file); //print_r($file); - $dest_dir = variable_get('video_upload_default_path', 'videos') .'/'; + //$dest_dir = variable_get('video_upload_default_path', 'videos') .'/'; + // the above no more works as token supports - use dirname + $dest_dir = dirname($job->origfile) . '/'; - if (file_copy($file, file_directory_path() . '/' . $dest_dir)) { + if (file_copy($file, $dest_dir)) { $file->fid = db_next_id('{files}_fid'); //print_r($file); db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", $file->fid, $job->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize); - - db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $job->vid, $file->list, $file->description); - - // set vidfile to "" to let video_upload overwrite it with the latest uploaded file + + db_query("INSERT INTO {upload} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $job->vid, $file->list, $file->description); + + // update the video table db_query('UPDATE {video} SET vidfile = "%s", videox = %d, videoy = %d WHERE nid=%d AND vid=%d', "", $job->calculatedx, $job->calculatedy, $job->nid, $job->vid); + + // update the video_encoded_fid in video serial data + _video_render_set_video_encoded_fid($job->nid, $job->vid, $file->fid); _video_render_job_change_status($job->nid, $job->vid, VIDEO_RENDERING_COMPLETE); - // delete the vile + watchdog('video_render', 'successfully converted %orig to %dest', array('%orig' => $job->origfile, '%dest' => $file->filepath)); + + // delete the temp file unlink($job->convfile); } else { - watchdog('video_scheduler', t('error moving video to the final directory. Check folder permissions.'), WATCHDOG_ERROR); + // get the username of the process owner + $ownerarray = posix_getpwuid(posix_getuid()); + $owner=$ownerarray['name']; + // get the username of the destination folder owner + $fownerarray = posix_getpwuid(fileowner($dest_dir)); + $fowner=$fownerarray['name']; + // get destination folder permissions + $perms = substr(sprintf('%o', fileperms($dest_dir)), -4); + watchdog('video_render', 'error moving video %vid_file with nid = %nid to %dir the final directory. Check folder permissions.<br />The script was run by %uname .<br />The folder owner is %fowner .<br />The folder permissions are %perms .', array('%vid_file' => $job->origfile, '%nid' => $job->nid, '%dir' => $dest_dir, '%uname' => $owner, '%fowner' => $fowner, '%perms' => $perms), WATCHDOG_ERROR); + + _video_render_set_video_encoded_fid($job->nid, $job->vid, -1); + _video_render_job_change_status($job->nid, $job->vid, VIDEO_RENDERING_FAILED); } } } /** + * Set the video_encoded_fid in the video table + * We store -1 as video_encoded_fid if the encoding failed +*/ +function _video_render_set_video_encoded_fid($nid, $vid, $encoded_fid) { + db_lock_table('video'); + $node = db_fetch_object(db_query("SELECT serialized_data FROM {video} WHERE nid = %d AND vid = %d", $nid, $vid)); + $node->serial_data = unserialize($node->serialized_data); + $node->serial_data['video_encoded_fid'] = $encoded_fid; + $node->serialized_data = serialize($node->serial_data); + db_query("UPDATE {video} SET serialized_data = '%s' WHERE nid = %d AND vid = %d", $node->serialized_data, $nid, $vid); + db_unlock_tables(); +} + + + +/** * Get a string cointaining the command to be executed including options */ function _video_render_get_command(&$job) { @@ -140,14 +193,14 @@ function _video_render_get_command(&$job) { $audiobitrate = variable_get('video_ffmpeg_helper_auto_cvr_audio_bitrate', 64); $videobitrate = variable_get('video_ffmpeg_helper_auto_cvr_video_bitrate', 200); $size = _video_render_get_size($job); - + $converter = VIDEO_RENDERING_FFMPEG_PATH; - $options = preg_replace(array('/%videofile/', '/%convertfile/', '/%audiobitrate/', '/%size/', '/%videobitrate/'), array($videofile, $convfile, $audiobitrate, $size, $videobitrate), variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate %convertfile')); - + $options = preg_replace(array('/%videofile/', '/%convertfile/', '/%audiobitrate/', '/%size/', '/%videobitrate/'), array($videofile, $convfile, $audiobitrate, $size, $videobitrate), variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate -qscale 1 %convertfile')); + // set to the converted file output $job->convfile = $convfile; - + return VIDEO_RENDERING_NICE . " $converter $options"; } @@ -161,10 +214,17 @@ function _video_render_get_size(&$job) { $def_width = variable_get('video_ffmpeg_helper_auto_cvr_width', 400); $height = $def_width * ($job->videoy / $job->videox); // do you remember proportions?? :-) - + + + $height = round($height); + // add one if odd + if($height % 2) { + $height++; + } + $job->calculatedx = $def_width; $job->calculatedy = $height; - + return $def_width . 'x' . $height; } @@ -174,7 +234,7 @@ function _video_render_get_size(&$job) { */ function _video_render_load_job($nid, $vid, $status) { $result = db_query('SELECT * FROM {video_rendering} vr INNER JOIN {node} n ON vr.vid = n.vid INNER JOIN {video} v ON n.vid = v.vid WHERE n.nid = v.nid AND vr.nid = n.nid AND vr.status = %d AND n.nid = %d AND n.vid = %d', $status, $nid, $vid); - + return db_fetch_object($result); } diff --git a/plugins/video_ffmpeg_helper/video_scheduler.php b/plugins/video_ffmpeg_helper/video_scheduler.php index 4803dc2..7faf446 100644 --- a/plugins/video_ffmpeg_helper/video_scheduler.php +++ b/plugins/video_ffmpeg_helper/video_scheduler.php @@ -1,14 +1,20 @@ <?php -// $Id$ /** * @file * Implement video rendering scheduling. + * If you are not using sites/default/settings.php as your settings file, + * add an optional parameter for the drupal site url: + * "php video_scheduler.php http://example.com/" or + * "php video_scheduler.php http://example.org/drupal/" * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ - - + + /** * video_scheduler.php configuration */ @@ -18,7 +24,7 @@ define('VIDEO_RENDERING_FFMPEG_PATH', '/usr/bin/ffmpeg'); // set to the temp file path. //IMPORTANT: the user who runs this script must have permissions to create files there. If this is not the case the default php temporary folder will be used. -define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video'); +define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video'); // number of conversion jobs active at the same time define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5); @@ -31,12 +37,18 @@ define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5); /** * Define some constants */ -define('VIDEO_RENDERING_PENDING', 0); +define('VIDEO_RENDERING_PENDING', 1); define('VIDEO_RENDERING_ACTIVE', 5); define('VIDEO_RENDERING_COMPLETE', 10); +define('VIDEO_RENDERING_FAILED', 20); +if (isset($_SERVER['argv'][1])) { + $url = parse_url($_SERVER['argv'][1]); + $_SERVER['SCRIPT_NAME'] = $url['path']; + $_SERVER['HTTP_HOST'] = $url['host']; +} -include_once './includes/bootstrap.inc'; +module_load_include('/includes/bootstrap.inc', 'video_scheduler', 'includes/bootstrap'); // disable error reporting for bootstrap process error_reporting(E_ERROR); // let's bootstrap: we will be able to use drupal apis @@ -60,14 +72,14 @@ else { * Main for video_scheduler.php */ function video_scheduler_main() { - + if($jobs = video_scheduler_select()) { foreach ($jobs as $job) { video_scheduler_start($job); } } else { - watchdog('video_scheduler', t('no video conversion jobs to schedule.')); + watchdog('video_scheduler', 'no video conversion jobs to schedule.'); } } @@ -76,7 +88,8 @@ function video_scheduler_main() { * Starts rendering for a job */ function video_scheduler_start($job) { - exec("php video_render.php $job->nid $job->vid > /dev/null &"); + $url = (isset($_SERVER['argv'][1])) ? escapeshellarg($_SERVER['argv'][1]) : ''; + exec("php video_render.php $job->nid $job->vid $url > /dev/null &"); } @@ -88,9 +101,10 @@ function video_scheduler_start($job) { function video_scheduler_select() { $result = db_query('SELECT * FROM {video_rendering} vr INNER JOIN {node} n ON vr.vid = n.vid INNER JOIN {video} v ON n.vid = v.vid WHERE n.nid = v.nid AND vr.nid = n.nid AND vr.status = %d ORDER BY n.created', VIDEO_RENDERING_PENDING); - + // TODO: order jobs by priority - + + // TODO: use db_query_range $jobs = array(); $i = 0; $count = db_num_rows($result); @@ -98,7 +112,7 @@ function video_scheduler_select() { $jobs[] = db_fetch_object($result); $i++; } - + return $jobs; } diff --git a/plugins/video_image/video_image.info b/plugins/video_image/video_image.info index 40677b2..8840ccd 100644 --- a/plugins/video_image/video_image.info +++ b/plugins/video_image/video_image.info @@ -1,5 +1,6 @@ -; $Id$ name = Video Image description = Enable thumbnails support for video module. -dependencies = image video +dependencies[] = image +dependencies[] = video package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_image/video_image.module b/plugins/video_image/video_image.module index 992795a..705ceba 100644 --- a/plugins/video_image/video_image.module +++ b/plugins/video_image/video_image.module @@ -1,37 +1,39 @@ <?php -// $Id$ /** * @file * Enable image support for video module. * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ /** * Implementation of hook_help(). */ -function video_image_help($section) { - switch ($section) { +function video_image_help($path, $arg) { + switch ($path) { case 'admin/modules#description': - return t('Enable thumbnails support for video module.'); + return t('Enable thumbnail support for video module.'); } } /** * Implementation of hook_menu() */ -function video_image_menu($may_cache) { +function video_image_menu() { $items = array(); + $may_cache=true; if ($may_cache) { - $items[] = array( - 'path' => 'admin/content/video/image', - 'title' => t('Video image'), - 'description' => t('Administer video_image module settings'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('video_image_admin_settings'), - 'access' => user_access('administer site configuration'), + $items['admin/settings/video/image'] = array( + 'title' => 'Video image', + 'description' => 'Administer video_image module settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('video_image_admin_settings'), + 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); } @@ -40,14 +42,21 @@ function video_image_menu($may_cache) { /** + * Implementation of hook_perm + */ +function video_image_perm() { + $array = array('override autothumbnailing using uploaded image'); + return $array; +} + + +/** * Settings form */ function video_image_admin_settings() { - if (module_exists('video_upload')) { - if (variable_get('video_image_auto_thumbnail', 0)) { - $upload_weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_upload'")); - db_query("UPDATE {system} SET weight=".($upload_weight+1)." WHERE name='video_image'"); - } + if (module_exists('video_upload') && variable_get('video_image_auto_thumbnail', 0)) { + $upload_weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_upload'")); + db_query("UPDATE {system} SET weight=".($upload_weight+1)." WHERE name='video_image'"); } $form = array(); $form['video_image_publish_thumbnail'] = array( @@ -61,14 +70,68 @@ function video_image_admin_settings() { '#title' => t('Promote the thumbnails to the front page'), '#default_value' => _video_image_promote_thumbnails(), ); - + $form['autothumb'] = array( + '#type' => 'fieldset', + '#title' => t('Automatic video thumbnailing'), + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#description' => t('This feature requires the \'video_ffmpeg_helper\' module'), + ); + $auto_thumb_disable = !module_exists('video_ffmpeg_helper'); + $form['autothumb']['video_image_auto_thumbnail'] = array( + '#type' => 'checkbox', + '#title' => t('Auto thumbnail for videos'), + '#description' => t('If set up correctly, this will auto-generate a thumbnail for each video created.'), + '#default_value' => variable_get('video_image_auto_thumbnail', false) && !$auto_thumb_disable, + '#disabled' => $auto_thumb_disable, + ); + /* + $form['autothumb']['video_image_auto_thumbnail_only'] = array( + '#type' => 'checkbox', + '#title' => t('Use auto-thumbnailer exclusively for video images'), + '#description' => t('If checked, this will disable the file upload box for the user-supplied thumbnail. Only check this if you have checked to be sure that auto-thumbnailing works. Auto thumbnail must be selected for this to be enabled.'), + '#default_value' => variable_get('video_image_auto_thumbnail_only', false), + '#disabled' => !variable_get('video_image_auto_thumbnail', false), + ); + */ + $form['autothumb']['video_image_auto_thumbnail_debug'] = array( + '#type' => 'checkbox', + '#title' => t('Debug automatic thumbnail process'), + '#default_value' => variable_get('video_image_auto_thumbnail_debug', false), + '#description' => t('Automatic thumbnailing of videos is dependent on the actual video types. Some video types may not be able to be automatically thumbnailed. Setting this option will allow messages to be show when posting and editing of videos that can be automatically thumbnailed.'), + '#disabled' => $auto_thumb_disable, + ); + + return system_settings_form($form); } +function video_image_admin_settings_validate($form, &$form_state) { + if (module_exists('video_ffmpeg_helper')) { + if ($form_state['values']['video_image_auto_thumbnail']) { + $path_ok = _video_ffmpeg_helper_check_exe_path(); + if (!$path_ok) { + drupal_set_message(t('The path for \'ffmpeg\' is not valid. Please check settings on the !ffmpeg_settings_page', array('!ffmpeg_settings_page' => l(t('Video ffmpeg helper settings page'), 'admin/settings/video/ffmpeg_helper'))), 'error'); + } + } + } +} + + +/** + * Return true if the video support authothumbnailing +*/ +function video_image_is_autothumbable($node) { + $info = video_get_type_info($node->vtype); + $has_hook = module_hook('video_' . $node->vtype, 'v_auto_thumbnail'); + return $has_hook && isset($info[$node->vtype]['#autothumbable']) && $info[$node->vtype]['#autothumbable']; +} + + /** * Implementation of hook_form_alter() */ -function video_image_form_alter($form_id, &$form) { +function video_image_form_alter(&$form, &$form_state, $form_id) { if($form_id == 'video_node_form') { @@ -76,18 +139,37 @@ function video_image_form_alter($form_id, &$form) { $value = ($node->new_image) ? '#value' : '#default_value'; $form['iid'] = array('#type' => 'hidden', $value => $node->iid); - if (function_exists('_image_check_settings')) { - _image_check_settings(); + if (!is_array($node->tempimage['fids'])) { + $fids = array('_original' => 0); + foreach (_image_get_sizes() as $size) { + $fids[$size['label']] = 0; + } + $node->tempimage['fids'] = $fids; + } + $form['tempimage']['#tree'] = true; + foreach ($node->tempimage['fids'] as $label => $fid) { + $form['tempimage']['fids'][$label] = array('#type' => 'hidden', $value => $fid); + } + + $auto_thumbable = video_image_is_autothumbable($node); + + if(!$auto_thumbable || user_access('override autothumnailing using uploaded images')) { + // let's be sure that image directories are ready + if (function_exists('_image_check_settings')) { + _image_check_settings(); + } + // needed for uploading $form['#attributes'] = array("enctype" => "multipart/form-data"); - - $form['image'] = array('#type' => 'fieldset', '#title' => t('Image thumbnails'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -17, '#description' => t('Use this form to upload an image.')); - + + $form['image'] = array('#type' => 'fieldset', '#title' => t('Image thumbnails'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -17, '#description' => t('Upload an image to be used as the thumbnail for this video.')); + $form['image']['image'] = array('#type' => 'file', '#title' => t('Image')); - $form['image']['image_title'] = array('#type' => 'textfield', '#title' => t('Image title'), '#default_value' => $node->image->image_title); + } + if ($node->nid && $auto_thumbable) { + $form['regenerate_thumbnail'] = array('#type' => 'checkbox', '#title' => t('Auto regenerate thumbnail'), '#default_value' => 0); } } - } @@ -95,67 +177,31 @@ function video_image_form_alter($form_id, &$form) { * Implementation of hook_nodeapi() */ function video_image_nodeapi(&$node, $op, $teaser) { + //print_r($op); + //exit; if($node->type == 'video') { switch ($op) { - case 'load': - $output['iid'] = $node->serial_data['iid']; - return $output; - case 'submit': - if (variable_get('video_image_auto_thumbnail_debug', false) && variable_get('video_image_auto_thumbnail', false)) { - drupal_set_message(t('video_image_nodeapi: prepare: ready to thumbnail image')); - } - $field_name = file_check_upload('image'); - $image->uid = $node->uid; - $image->name = $node->name; - $image->created = $node->created; - $image->type = 'image'; - //$image->status = _video_image_publish_thumbnails(); - //$image->promote = _video_image_promote_thumbnails(); - if (!$field_name && module_exists('video_ffmpeg_helper') && variable_get('video_ffmpeg_helper_auto_thumbnail', false)) { - $image->title = $_SESSION['video_upload_file']->filename; - $field_name = _video_ffmpeg_helper_auto_thumbnail($node); - } - else { - $image->title = $_POST['edit']['image_title']; - $field_name = 'image'; - } - image_prepare($image, $field_name); - if ($image->images) { - node_validate($image); - if (!form_get_errors()) { - $image = node_submit($image); - node_save($image); - - // needed to set the correct status and promote values if the user does not have enought permissions. Is there a better solution??? - db_query('UPDATE {node} SET status = %d, promote = %d WHERE nid = %d AND vid = %d', _video_image_publish_thumbnails(), _video_image_promote_thumbnails(), $image->nid, $image->vid); - - $node->iid = $node->serial_data['iid'] = $image->nid; - $_SESSION['video_upload_file']->iid = $image->nid; - $node->new_image = TRUE; - } - } - else if (isset($_SESSION['video_upload_file']->iid)) { - $node->iid = $_SESSION['video_upload_file']->iid; - } + case 'load': + //exit; + return _video_image_load($node); - $node->serial_data['iid'] = $node->iid; - break; case 'prepare': - ; - break; + //exit; + _video_image_prepare($node); + break; + + case 'presave': + //exit; + _video_image_submit($node); + break; case 'view': - if ($node->iid) { - if($teaser) { - $node->content['video_image_thumbnail'] = array('#value' => theme('video_image_teaser', $node)); - } - else { - $node->content['video_image_thumbnail'] = array('#value' => theme('video_image_body', $node)); - } - } + //exit; + _video_image_view($node, $teaser); break; case 'delete': - node_delete(array('nid' => $node->iid)); + //exit; + _video_image_delete($node); break; } } @@ -163,51 +209,279 @@ function video_image_nodeapi(&$node, $op, $teaser) { /** - * Render the output for the node teaser. + * Renders thumbnail node with a link to the video node to be used on video teasers. * - * @param $node - * object with node information + * @param $image + * object with image node information + * @param $video + * the video node associated with image * * @return * string of content to display */ -function theme_video_image_teaser($node) { - if($node->serial_data['iid']) { - $image = node_load($node->serial_data['iid']); - $image = image_display($image, 'thumbnail', array('class' => 'video_image_teaser')); +function theme_video_image_teaser($image, $video) { + + $image_html = NULL; + + if($image != NULL && $image->type == 'image') { + $image_html = image_display($image, 'thumbnail', array('class' => 'video_image_teaser')); } - else { // only for backward compatibility - $image = theme('image', $node->serial_data['image_teaser'], $node->title, $node->title, array('class' => 'video_image_teaser'), FALSE); + else if($image_node == NULL && $video->serial_data['image_teaser']){ // only for backward compatibility + $image_html = theme('image', $video->serial_data['image_teaser'], $video->title, $video->title, array('class' => 'video_image_teaser'), FALSE); + } + + if($image) { + //Create a link with an image in it. + $output .= l($image_html, "node/$video->nid", array('html' => TRUE)); + $output .= '<br class="video_image_clear" />'; } - $output .= l($image, "node/$node->nid", array(), NULL, NULL, FALSE, TRUE); //Create a link with an image in it. - $output .= '<br class="video_image_clear" />'; return $output; } -/** - * Generates the image HTML displayed in the Node body. - * - * @param $node - * object with node information - * - * @return - * string of content to display - */ -function theme_video_image_body($node) { - if(variable_get('video_playinbody', 0) == 0){ - if($node->serial_data['iid']) { - $image = node_load($node->serial_data['iid']); - $image = image_display($image, 'thumbnail'); +/* nodeapi split out hooks */ +function _video_image_load(&$node) { + $output['iid'] = $node->serial_data['iid']; + return $output; +} + +function _video_image_prepare(&$node) { + // let's check that we have a valid image + //print_r($node); + //exit; + if (count($_POST)) { + + $validators = array( + 'file_validate_is_image' => array() + ); + + $field_name = file_save_upload('image', $validators); + if (!$field_name && video_image_is_autothumbable($node)) { + _video_image_thumbnail_debug(t('video_image_nodeapi: prepare: ready to thumbnail video')); + $field_name = module_invoke('video_' . $node->vtype, 'v_auto_thumbnail', $node); + if ($field_name === false && count($_POST)) { + drupal_set_message(t('The thumbnailing process of your video failed for some reason. Video thumbnail will not be available.'), 'error'); + } } - else { // only for backward compatibility - $image = theme('image', $node->serial_data['image_view'], $node->title, $node->title, array('class' => 'video_image_view'), FALSE); //Create image HTML + } + if ($field_name) { + $node->tempimage = _video_image_temp_image_store($field_name); + $node->new_image = TRUE; + } else if (is_array($_POST['tempimage']) && + ($_POST['op'] == 'Preview' || $_POST['op'] == 'Submit')) { + $node->tempimage = (array)_video_image_temp_image_load(array_values($_POST['tempimage']['fids'])); + } +} + +function _video_image_submit(&$node) { + //print_r($node); + //exit; + // ############# PREPARE ####################### + // ------------- MOVED ------------------------- + if (count($_POST)) { + + $validators = array( + 'file_validate_is_image' => array() + ); + + $field_name = file_save_upload('image', $validators); + if (!$field_name && video_image_is_autothumbable($node)) { + _video_image_thumbnail_debug(t('video_image_nodeapi: prepare: ready to thumbnail video')); + $field_name = module_invoke('video_' . $node->vtype, 'v_auto_thumbnail', $node); + if ($field_name === false && count($_POST)) { + drupal_set_message(t('The thumbnailing process of your video failed for some reason. Video thumbnail will not be available.'), 'error'); + } } - $output = l($image, "node/$node->nid/play", array('title' => t('play') . ' ' . $node->title), NULL, NULL, FALSE, TRUE); //Create link HTML with image in it. } - return $output; + + if ($field_name) { + /* + if($node->iid){ + + // Remove all the existing images. + $result = db_query("SELECT f.fid, f.filepath FROM {image} i INNER JOIN {files} f ON i.fid = f.fid WHERE i.nid = %d", $node->iid); + while ($file = db_fetch_object($result)) { + file_delete(file_create_path($file->filepath)); + db_query("DELETE FROM {files} WHERE fid = %d", $file->fid); + } + //db_query("DELETE FROM {image} WHERE nid = %d", $node->iid); + } + * + */ + $node->tempimage = _video_image_temp_image_store($field_name); + $node->new_image = TRUE; + //print_r($node); + //die; + } else if (is_array($_POST['tempimage']) && ($_POST['op'] == 'Preview' || $_POST['op'] == 'Submit')) { + //print_r($node); + //exit; + $node->tempimage = (array)_video_image_temp_image_load(array_values($_POST['tempimage']['fids'])); + } + + // ########################################################################### + + + if ($node->regenerate_thumbnail) { + _video_image_regenerate_thumbnail($node); + } + if (is_array($node->tempimage['fids']) && $node->tempimage['fids']['_original']) { + $image = _video_image_temp_image_load(array_values($node->tempimage['fids'])); + //print_r($image); + //exit; + db_query("DELETE FROM {files} WHERE fid in (%s)", + implode(',', array_values($node->tempimage['fids']))); + // initialize standard node fields + //print_r($image); + //exit; + $image->uid = $node->uid; + $image->created = time(); + $image->title = t('Video thumbnail for !title', array('!title' => $node->title)); + $image = node_submit($image); + $image->uid = $node->uid; + $image->status = _video_image_publish_thumbnails(); + $image->promote = _video_image_promote_thumbnails(); + // This is a messages hack (we don't want to see what happens under the covers) + _video_image_pause_messages(true); + if ($node->iid) { + + $oldimage = node_load($node->iid); + $oldimage->images = $image->images; + + // delete the old images? + $oldimage->new_image = 1; + node_save($oldimage); + $node->iid = $oldimage->nid; + $node->serial_data['iid'] = $node->iid; + } else { + node_save($image); + + //print_r($image); + //exit; + //image_insert($image); + $node->iid = $image->nid; + // store the iid into the serial_data + $node->serial_data['iid'] = $node->iid; + //print_r($node); + //die; + // needed to set the correct status and promote values even if the user does not have enough permissions. Is there a better solution??? + // db_query('UPDATE {node} SET status = %d, promote = %d WHERE nid = %d AND vid = %d', _video_image_publish_thumbnails(), _video_image_promote_thumbnails(), $image->nid, $image->vid); + } + _video_image_pause_messages(); + } + else { + $node->serial_data['iid'] = $node->iid; + } +} + +function _video_image_view(&$node, $teaser) { + if (is_array($node->tempimage['fids']) && $node->tempimage['fids']['_original']) { + $image = _video_image_temp_image_load(array_values($node->tempimage['fids'])); + } else if ($node->iid) { + $image = node_load($node->iid); + } else { + $image = NULL; // this is for backward compatibility + } + + if($teaser) { + $node->content['video_image_thumbnail'] = array('#value' => theme('video_image_teaser', $image, $node)); + } } +function _video_image_regenerate_thumbnail(&$node) { + $field_name = module_invoke('video_' . $node->vtype, 'v_auto_thumbnail', $node); + if ($field_name) { + $node->tempimage = _video_image_temp_image_store($field_name); + $node->new_image = TRUE; + } +} + +function _video_image_delete(&$node) { + _video_image_pause_messages(true); + node_delete(array('nid' => $node->iid)); + _video_image_pause_messages(); +} + +/* At times, when doing sub-node processing (creating/deleting thumbnail nodes) + * we don't really want to show all the messages through to the end user or it + * gets a little bit confusing (image created messages when creating a video) + * so we suppress the messages with this procedure. + */ +function _video_image_pause_messages($snapshot = false) { + static $messages = null; + if ($snapshot) { + $messages = drupal_get_messages(); + } else if (is_array($messages)) { + $_SESSION['messages'] = $messages; + $messages = null; + } +} + +/* debugging framework for troublesome thumbnailing */ +function _video_image_thumbnail_debug($msg) { + static $debug = NULL; + if ($debug == NULL) { + $debug = variable_get('video_image_auto_thumbnail_debug', false); + } + if ($debug) { + $t = debug_backtrace(); + $l = array_shift($t); + drupal_set_message(basename($l['file'], '.module').': '.$msg); + } +} + +function _video_image_temp_image_store(&$file) { + $image = new stdClass(); + $image->images[IMAGE_ORIGINAL] = $file->filepath; + $image->images =_image_build_derivatives($image); + $image->type = 'image'; + $image->uid = 1; + $image->created = time(); + $image->title = t('video image thumbnail'); + // We're good to go. + + $image->rebuild_images = FALSE; + $image->new_file = TRUE; + + + //print_r($image); + //exit; + if ($image->images) { + node_validate($image); + if (!form_get_errors()) { + // save the images in the files table + foreach ($image->images as $l => $f) { + $info = image_get_info($f); + $file->fid = db_last_insert_id('files','fid'); + if($l=="_original"){ + db_query("INSERT INTO {files} (fid, filename, filepath, filemime, filesize) VALUES (%d, '%s', '%s', '%s', '%s')", + $fid, "video_image_temp.$l", $f, $info['mime_type'], $info['file_size']); + } + $image->fids[$l] = $file->fid; + } + } + } + //print_r($image); + //exit; + return (array)$image; +} + +/* Create a fake node object that acts like an image node + * by looking up each file in the array $fids and loading + * them into the images array. + */ +function _video_image_temp_image_load($fids) { + $image = new stdClass(); + $image->type = 'image'; + $image->new_file = 1; + $fids = implode(',', $fids); + $results = db_query("SELECT fid, filename, filepath FROM {files} WHERE fid IN (%s)", $fids); + while ($file = db_fetch_object($results)) { + $label = substr($file->filename, 17); + $image->images[$label] = $file->filepath; + $image->fids[$label] = $file->fid; + } + return $image; +} /* If the user has set a promote preference, use that, otherwise return * if 'promote' is set in the drupal content type settings @@ -238,4 +512,42 @@ function _video_image_publish_thumbnails() { } return $settings_override; } -?> + + +/** + * Create an image file object from a given image url +*/ +function _video_image_get_thumb_file_object($thumbnail_url, $id) { + + if($thumbnail_url && $thumbnail_url != '' && $image = image_gd_open($thumbnail_url, 'jpeg')) { + // save image to temp directory for processing + $location = file_directory_temp() .'/'. $id .'.jpg'; + image_gd_close($image, $location, 'jpeg'); + + + // get info and build a file object + $filepath = file_create_path($location, file_directory_temp()); + $info = image_get_info($filepath); + + $file = new stdClass(); + $file->filepath = realpath($filepath); + $file->filename = basename($file->filepath); + $file->filesize = $info['file_size']; + $file->filemime = $info['mime_type']; + + return $file; + } + + return null; +} + +/** + * Implementation of hook_theme(). + */ +function video_image_theme() { + return array( + 'video_image_teaser' => array( + 'arguments' => array('image' => NULL,'video' => NULL), + ), + ); +} diff --git a/plugins/video_multidownload/video_multidownload.info b/plugins/video_multidownload/video_multidownload.info index 6d7a365..eac3f33 100644 --- a/plugins/video_multidownload/video_multidownload.info +++ b/plugins/video_multidownload/video_multidownload.info @@ -1,5 +1,5 @@ -; $Id$ name = Video Multidownload description = Enable multiple file download in video module. -dependencies = video +dependencies[] = video package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_multidownload/video_multidownload.module b/plugins/video_multidownload/video_multidownload.module index 992b852..1d3a245 100644 --- a/plugins/video_multidownload/video_multidownload.module +++ b/plugins/video_multidownload/video_multidownload.module @@ -1,19 +1,20 @@ <?php -// $Id$ - /** * @file * Enable multiple file download in video module. * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ /** * Implementation of hook_help(). */ -function video_multidownload_help($section) { - switch ($section) { +function video_multidownload_help($path, $arg) { + switch ($path) { case 'admin/modules#description': return t('Enable multiple file download in video module.'); } @@ -29,16 +30,36 @@ function video_multidownload_help($section) { * @return * array of menu information */ -function video_multidownload_menu($may_cache) { +function video_multidownload_menu() { $items = array(); +/* TODO + Non menu code that was placed in hook_menu under the '!$may_cache' block + so that it could be run during initialization, should now be moved to hook_init. + Previously we called hook_init twice, once early in the bootstrap process, second + just after the bootstrap has finished. The first instance is now called boot + instead of init. + + In Drupal 6, there are now two hooks that can be used by modules to execute code + at the beginning of a page request. hook_boot() replaces hook_boot() in Drupal 5 + and runs on each page request, even for cached pages. hook_boot() now only runs + for non-cached pages and thus can be used for code that was previously placed in + hook_menu() with $may_cache = FALSE: + + Dynamic menu items under a '!$may_cache' block can often be simplified + to remove references to arg(n) and use of '%<function-name>' to check + conditions. See http://drupal.org/node/103114. + + The title and description arguments should not have strings wrapped in t(), + because translation of these happen in a later stage in the menu system. +*/ + $may_cache=true; if ($may_cache) { - $items[] = array( - 'path' => 'admin/content/video/multidownload', - 'title' => t('Multidownload'), - 'description' => t('Administer video_multidownload module settings'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('video_multidownload_settings_form'), - 'access' => user_access('administer site configuration'), + $items['admin/content/video/multidownload'] = array( + 'title' => 'Multidownload', + 'description' => 'Administer video_multidownload module settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('video_multidownload_settings_form'), + 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); } @@ -47,12 +68,12 @@ function video_multidownload_menu($may_cache) { if ($node = node_load(arg(1)) and $node->type == 'video') { if(isset($node->disable_multidownload) && !$node->disable_multidownload && - ($node->use_play_folder || $node->download_folder!='') - ) { - $items[] = array('path' => 'node/'.arg(1).'/multidownload', - 'title' => t('download other formats'), - 'callback' => 'video_multidownload_download', - 'access' => user_access('access video'), + ($node->use_play_folder || $node->download_folder!='') + ) { + $items['node/'.'%'.'/multidownload'] = array( + 'title' => 'download other formats', + 'page callback' => 'video_multidownload_download', + 'access arguments' => array('access video'), 'weight' => 7, 'type' => MENU_LOCAL_TASK); } @@ -78,7 +99,7 @@ function video_multidownload_settings_form() { $form = array(); $options = array(1 => 'Yes', 0 => 'No'); - + $form['multifile'] = array('#type' => 'fieldset', '#title' => t('Multi-file download options'), '#description' => t('Allows a list of files to be shown on the download page. The list is usually gotten from a specified folder. This ability is useful for providing different sizes and video types for download.')); $form['multifile']['video_multidownload'] = array( '#type' => 'radios', @@ -91,7 +112,7 @@ function video_multidownload_settings_form() { '#title' => t('File extensions to show'), '#default_value' => variable_get('video_download_ext', 'mov,wmv,rm,flv,avi,divx,mpg,mpeg,mp4,zip'), '#description' => t('The extensions of files to list from the multi-file download folder on the download page. Extensions should be comma seperated with no spaces, for example (mov,wmv,rm).')); - + return system_settings_form($form); } @@ -100,7 +121,7 @@ function video_multidownload_settings_form() { * Implementation of hook_form_alter() * We use this to add multidownload fields to the video creation form. */ -function video_multidownload_form_alter($form_id, &$form) { +function video_multidownload_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'video_node_form' && isset($form['video']) && user_access('create multi-file downloads')) { @@ -112,7 +133,7 @@ function video_multidownload_form_alter($form_id, &$form) { '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -18, - '#description' => t('These options allow you to have multiple files shown on the download page. This is useful for allowing users to download different file sizes and video formats. ') . l(t('More information.'), 'video/help', NULL, NULL, 'multi-download') + '#description' => t('These options allow you to have multiple files shown on the download page. This is useful for allowing users to download different file sizes and video formats. ') . l(t('More information.'), 'video/help', array('fragment' => 'multi-download')) ); $form['multi-file']['disable_multidownload'] = array( '#type' => 'checkbox', @@ -141,7 +162,7 @@ function video_multidownload_form_alter($form_id, &$form) { function video_multidownload_nodeapi(&$node, $op, $teaser) { if($node->type == 'video') { switch ($op) { - + case 'validate': //Validate multi-file download values. if (user_access('create multi-file downloads')) { //Make sure the user has permission. @@ -359,3 +380,14 @@ function _video_multidownload_download_goto($input_url, $vid, $base64_encoded) { drupal_goto("node/$node->nid"); //Use the nid we just loaded to go back to the node page. } } + +/** + * Implementation of hook_theme(). + */ +function video_multidownload_theme() { + return array( + 'video_multidownload_download' => array( + 'arguments' => array('node' => NULL), + ), + ); +} diff --git a/plugins/video_optmetadata/video_optmetadata.info b/plugins/video_optmetadata/video_optmetadata.info index aaa0b17..0dece56 100644 --- a/plugins/video_optmetadata/video_optmetadata.info +++ b/plugins/video_optmetadata/video_optmetadata.info @@ -1,5 +1,5 @@ -; $Id$ name = Video Opt Metadata description = Enable addition of optional metadata on video nodes created by video module. Optional metadata are Video Bitrate, Audio Bitrate, Audio Sampling Rate and Audio Channels. -dependencies = video +dependencies[] = video package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_optmetadata/video_optmetadata.module b/plugins/video_optmetadata/video_optmetadata.module index f3764d2..9967e23 100644 --- a/plugins/video_optmetadata/video_optmetadata.module +++ b/plugins/video_optmetadata/video_optmetadata.module @@ -1,19 +1,21 @@ <?php -// $Id$ /** * @file * Enable addition of optional metadata on video nodes created by video module. * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ /** * Implementation of hook_help(). */ -function video_optmetadata_help($section) { - switch ($section) { +function video_optmetadata_help($path, $arg) { + switch ($path) { case 'admin/modules#description': return t('Enable addition of optional metadata on video nodes created by video module. Optional metadata are Video Bitrate, Audio Bitrate, Audio Sampling Rate and Audio Channels.'); } @@ -34,7 +36,7 @@ function video_optmetadata_perm() { * We use this to add some fields to the video creation form. * In those fields users will be able to insert some video metadatas. */ -function video_optmetadata_form_alter($form_id, &$form) { +function video_optmetadata_form_alter(&$form, &$form_state, $form_id) { if($form_id == 'video_node_form' && isset($form['video']) && user_access('insert optional metadata')) { @@ -132,3 +134,14 @@ function theme_video_metadata($node) { } return $output; } + +/** + * Implementation of hook_theme(). + */ +function video_optmetadata_theme() { + return array( + 'video_metadata' => array( + 'arguments' => array('node' => NULL), + ), + ); +}
\ No newline at end of file diff --git a/plugins/video_params/video_params.info b/plugins/video_params/video_params.info index 1c6bc1a..222f5ac 100644 --- a/plugins/video_params/video_params.info +++ b/plugins/video_params/video_params.info @@ -1,5 +1,5 @@ -; $Id$ name = Video Params description = Enable addition of html params to object generated by video module. Useful if you need to use swf videos which needs params to be passed. -dependencies = video +dependencies[] = video package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_params/video_params.module b/plugins/video_params/video_params.module index 46fa2e3..4fa71a1 100644 --- a/plugins/video_params/video_params.module +++ b/plugins/video_params/video_params.module @@ -1,11 +1,12 @@ <?php -// $Id$ - /** * @file * Enable addition of params to object generated by video module * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ @@ -13,8 +14,8 @@ /** * Implementation of hook_help(). */ -function video_params_help($section) { - switch ($section) { +function video_params_help($path, $arg) { + switch ($path) { case 'admin/modules#description': return t('Enable addition of html params to object generated by video module. Useful if you need to use swf videos which needs params to be passed.'); } @@ -36,7 +37,7 @@ function video_params_perm() { * We use this to add a text area to the video creation form. * In the text area the user will be able to insert his param value association. */ -function video_params_form_alter($form_id, &$form) { +function video_params_form_alter(&$form, &$form_state, $form_id) { if($form_id == 'video_node_form' && isset($form['video']) && user_access('insert object params')) { |