Index: ffmpeg_converter_theme.inc =================================================================== RCS file: /cvs/drupal/contributions/modules/ffmpeg_converter/ffmpeg_converter_theme.inc,v retrieving revision 1.1 diff -u -r1.1 ffmpeg_converter_theme.inc --- ffmpeg_converter_theme.inc 26 Jan 2009 23:40:30 -0000 1.1 +++ ffmpeg_converter_theme.inc 22 Jul 2009 16:37:13 -0000 @@ -15,22 +15,22 @@ * The form element array. */ function theme_ffmpeg_converter_widget($element) { - - drupal_add_css(drupal_get_path('module', 'ffmpeg_converter'). '/ffmpeg_converter.css', 'module'); - + + drupal_add_css(drupal_get_path('module', 'ffmpeg_converter') .'/ffmpeg_converter.css', 'module'); + $field_name = $element['#field_name']; $field = content_fields($field_name); - + $output = ''; $render_fields = array(); $file_fields = array( 'empty' => array(), 'original' => array(), ); - + // Examine field instances. foreach (element_children($element) as $key) { - + if (is_int($key)) { if (!empty($element[$key]['#default_value']['fid'])) { if (empty($element[$key]['#default_value']['data']['ffmpeg_converter_file'])) { @@ -47,15 +47,15 @@ $render_fields[] = $key; } } - + // Determine which field instance to render. $file_fields = array_merge($file_fields['original'], $file_fields['empty']); $output .= drupal_render($element[array_shift($file_fields)]); - + // Render other form fields. foreach ($render_fields as $key) { $output .= drupal_render($element[$key]); } - + return $output; } Index: ffmpeg_converter.info =================================================================== RCS file: /cvs/drupal/contributions/modules/ffmpeg_converter/ffmpeg_converter.info,v retrieving revision 1.2 diff -u -r1.2 ffmpeg_converter.info --- ffmpeg_converter.info 7 Dec 2008 23:56:02 -0000 1.2 +++ ffmpeg_converter.info 22 Jul 2009 16:37:13 -0000 @@ -2,4 +2,5 @@ name = FFmpeg Converter description = This module lets you setup automatic media file conversions with FFmpeg. dependencies[] = ffmpeg_wrapper +dependencies[] = job_queue core=6.x Index: ffmpeg_converter.admin.inc =================================================================== RCS file: /cvs/drupal/contributions/modules/ffmpeg_converter/ffmpeg_converter.admin.inc,v retrieving revision 1.3 diff -u -r1.3 ffmpeg_converter.admin.inc --- ffmpeg_converter.admin.inc 4 Mar 2009 19:47:19 -0000 1.3 +++ ffmpeg_converter.admin.inc 22 Jul 2009 16:37:13 -0000 @@ -14,24 +14,24 @@ $form = array(); $form['ffmpeg_converter_presets'] = array( '#value' => t('Use this page to create FFmpeg configuration presets which you can use to process media files automatically.'), - '#tree' => true, + '#tree' => TRUE, ); if (module_exists('filefield')) { - $form['ffmpeg_converter_presets']['#value'] .= ' ' . t('Your presets will appear on file field configurations pages (see the Content types page), which allows you to have all media files that are uploaded through a certain file field processed automatically.', array('@content_types', url('admin/content/types'))); + $form['ffmpeg_converter_presets']['#value'] .= ' '. t('Your presets will appear on file field configurations pages (see the Content types page), which allows you to have all media files that are uploaded through a certain file field processed automatically.', array('@content_types', url('admin/content/types'))); } else { - $form['ffmpeg_converter_presets']['#value'] .= ' ' . t('If you install and enable the FileField module, your presets will appear on file field configurations pages, which allows you to have all media files that are uploaded through a certain file field processed automatically.'); + $form['ffmpeg_converter_presets']['#value'] .= ' '. t('If you install and enable the FileField module, your presets will appear on file field configurations pages, which allows you to have all media files that are uploaded through a certain file field processed automatically.'); } - $form['ffmpeg_converter_presets']['#value'] .= ' ' . t('Third party modules may make this functionality available in their own specific contexts.'); - + $form['ffmpeg_converter_presets']['#value'] .= ' '. t('Third party modules may make this functionality available in their own specific contexts.'); + $presets = ffmpeg_converter_options(); - + // Add a separate fieldset for each configuration. foreach ($presets as $key => $preset) { $form['ffmpeg_converter_presets'][$key] = array( '#type' => 'fieldset', - '#collapsible' => false, - '#tree' => true + '#collapsible' => FALSE, + '#tree' => TRUE ); $form['ffmpeg_converter_presets'][$key]['name'] = array( '#type' => 'textfield', @@ -40,12 +40,12 @@ '#default_value' => $preset['name'], '#size' => 20, ); - + // Add FFmpeg Wrapper's configuration form. $form['ffmpeg_converter_presets'][$key] += ffmpeg_wrapper_configuration_form($preset['ffmpeg_wrapper'], "edit-ffmpeg-converter-presets-$key-ffmpeg-wrapper-"); - $form['ffmpeg_converter_presets'][$key]['ffmpeg_wrapper']['#collapsible'] = true; - $form['ffmpeg_converter_presets'][$key]['ffmpeg_wrapper']['#collapsed'] = true; - $form['ffmpeg_converter_presets'][$key]['ffmpeg_wrapper']['#tree'] = true; + $form['ffmpeg_converter_presets'][$key]['ffmpeg_wrapper']['#collapsible'] = TRUE; + $form['ffmpeg_converter_presets'][$key]['ffmpeg_wrapper']['#collapsed'] = TRUE; + $form['ffmpeg_converter_presets'][$key]['ffmpeg_wrapper']['#tree'] = TRUE; $form['ffmpeg_converter_presets'][$key]['process_same_format'] = array( '#type' => 'checkbox', @@ -55,24 +55,24 @@ ); $form['ffmpeg_converter_presets'][$key]['delete_preset'] = array( '#type' => 'submit', - '#value' => t('Delete this preset') . ' (TODO)', + '#value' => t('Delete this preset') .' (TODO)', '#submit' => '', ); if (count($presets) < 2) { - $form['ffmpeg_converter_presets'][$key]['delete_preset']['#disabled'] = true; + $form['ffmpeg_converter_presets'][$key]['delete_preset']['#disabled'] = TRUE; } // TODO: delete this line once this button is implemented. - $form['ffmpeg_converter_presets'][$key]['delete_preset']['#disabled'] = true; + $form['ffmpeg_converter_presets'][$key]['delete_preset']['#disabled'] = TRUE; } - + $form['add_preset'] = array( '#type' => 'submit', - '#value' => t('Add new preset') . ' (TODO)', + '#value' => t('Add new preset') .' (TODO)', '#submit' => '', ); // TODO: delete this line once this button is implemented. - $form['add_preset']['#disabled'] = true; - + $form['add_preset']['#disabled'] = TRUE; + return system_settings_form($form); } @@ -82,13 +82,13 @@ */ function ffmpeg_converter_admin_debug() { $form = array(); - + $form['ffmpeg_converter_debug'] = array( '#type' => 'checkbox', '#title' => t('Save debug messages to the log'), '#description' => t('If you enable this, the options used when invoking ffmpeg will be logged each time a file is converted.'), '#default_value' => variable_get('ffmpeg_converter_debug', 0), ); - + return system_settings_form($form); } Index: ffmpeg_converter.module =================================================================== RCS file: /cvs/drupal/contributions/modules/ffmpeg_converter/ffmpeg_converter.module,v retrieving revision 1.39 diff -u -r1.39 ffmpeg_converter.module --- ffmpeg_converter.module 20 Apr 2009 21:11:45 -0000 1.39 +++ ffmpeg_converter.module 22 Jul 2009 16:37:13 -0000 @@ -35,7 +35,7 @@ 'access arguments' => array('administer ffmpeg wrapper'), 'file' => 'ffmpeg_converter.admin.inc', ); - + return $items; } @@ -95,20 +95,20 @@ * @param $form_state */ function ffmpeg_converter_field_settings(&$form, $form_state) { - - $form_item_id = 'ffmpeg_converter_' . $form['#field']['field_name']; - - $presets = array('disabled' => '<' . t('Disabled') . '>'); + + $form_item_id = 'ffmpeg_converter_'. $form['#field']['field_name']; + + $presets = array('disabled' => '<'. t('Disabled') .'>'); $presets = array_merge($presets, ffmpeg_converter_presets()); - + $default_field_setting = variable_get($form_item_id, array('preset' => 'disabled', 'hide_original' => 1)); - + $form['field'][$form_item_id] = array( '#type' => 'fieldset', '#title' => 'Automatic FFmpeg conversion', '#description' => t('Use these options to automatically process media files that are uploaded to this field.'), - '#collapsible' => true, - '#tree' => true, + '#collapsible' => TRUE, + '#tree' => TRUE, ); $form['field'][$form_item_id]['preset'] = array( '#type' => 'select', @@ -117,7 +117,13 @@ '#options' => $presets, '#default_value' => $default_field_setting['preset'], ); - // TODO: Add option to hide original files. + $form['field'][$form_item_id]['hide_original'] = array( + '#type' => 'radios', + '#options' => array(t('Show All'), t('Hide Original')), + '#title' => t('Display'), + '#weight' => 10, + '#default_value' => $default_field_setting['hide_original'], + ); $form['#validate'][] = 'ffmpeg_converter_fieldconfig_validate'; $form['#submit'][] = 'ffmpeg_converter_fieldconfig_submit'; @@ -128,20 +134,20 @@ * validate submitted field configuration forms. */ function ffmpeg_converter_fieldconfig_validate($form, &$form_state) { - $form_item_id = 'ffmpeg_converter_' . $form['#field']['field_name']; + $form_item_id = 'ffmpeg_converter_'. $form['#field']['field_name']; if ($form_state['values'][$form_item_id]['preset'] != 'disabled') { if ($form_state['values']['multiple'] != 1 && $form_state['values']['multiple'] < 5) { form_set_error('multiple', t('In order to use a FFmpeg Converter preset with this field, the Multiple value has to be at least 5 or Unlimited. You must either change the Multiple value or disable the FFmpeg Converter setting.')); } } } - + /** * Handle submitted field configuration forms and save FFmpeg field setting. */ function ffmpeg_converter_fieldconfig_submit($form, &$form_state) { - $form_item_id = 'ffmpeg_converter_' . $form['#field']['field_name']; + $form_item_id = 'ffmpeg_converter_'. $form['#field']['field_name']; variable_set($form_item_id, $form_state['values'][$form_item_id]); // TODO: Add option to hide original files. } @@ -149,7 +155,7 @@ /** * Alter node forms that have file fields that are enabled for this module. - * We can't alter the output of each file field instance here, so we save the + * We can't alter the output of each file field instance here, so we save the * values we need in the $form array and pick them up later. * * @param $form @@ -160,37 +166,37 @@ // Define custom form attributes. $form['#ffmpeg_converter_files'] = array(); $form['#ffmpeg_converter_selected_snapshots'] = array(); - + foreach ($form['#field_info'] as $field_def) { $preset_key = ffmpeg_converter_preset_by_field($field_def['field_name']); if ($preset_key) { $field = &$form[$field_def['field_name']]; - + // Define custom theme function for this form field. $field['#theme'] = 'ffmpeg_converter_widget'; // Wrap the field in a fieldset. $prefix = '
'; - $prefix .= '' . t('!title:', array('!title' => $field['#title'])) . "\n"; + $prefix .= ''. t('!title:', array('!title' => $field['#title'])) ."\n"; $field['#prefix'] = empty($field['#prefix']) ? '' : $field['#prefix']; $field['#prefix'] = $prefix . $field['#prefix']; $field['#suffix'] = empty($field['#suffix']) ? '' : $field['#suffix']; $field['#suffix'] .= "
\n"; - + // Examine the existing files in this field. $form['#ffmpeg_converter_files'][$field_def['field_name']] = array(); - foreach($field as $field_instance => &$file) { + foreach ($field as $field_instance => &$file) { if (is_numeric($field_instance)) { if (isset($file['#default_value']['data']['ffmpeg_converter_file'])) { // Override the filefield widget for this instance. This will // hide the file completely. We pick up and save the default // values in ffmpeg_converter_nodeform_validate(). $file['#type'] = 'value'; - + // Save custom file information. $form['#ffmpeg_converter_files'][$field_def['field_name']][$field_instance] = $file['#default_value']['data']['ffmpeg_converter_file']; - + // Save snapshot data. (No longer needed?) if (!empty($file['#default_value']['data']['ffmpeg_converter_snapshot_selected'])) { $form['#ffmpeg_converter_selected_snapshots'][$field_def['field_name']] = $field_instance; @@ -198,10 +204,10 @@ } } } - + // Add options to clear converted files and select one of the tree snapshot images. if (!empty($form['nid']['#value'])) { - + if (ffmpeg_converter_file_is_queued($form['nid']['#value'], $field_def['field_name'])) { $field['ffmpeg_converter_queued'] = array( '#type' => 'markup', @@ -228,7 +234,7 @@ $h = 100; $w = round($i['width'] / $i['height'] * 100); } - $snapshots[$instance] = theme('image', $field[$instance]['#default_value']['filepath'], '', '', array('width' => $w, 'height' => $h), false); + $snapshots[$instance] = theme('image', $field[$instance]['#default_value']['filepath'], '', '', array('width' => $w, 'height' => $h), FALSE); } else { $snapshots[$instance] = $field[$instance]['#default_value']['filename']; @@ -309,9 +315,9 @@ * If $key is specified, an array of options for the specific preset. * If not, a nested array containing options for all presets. */ -function ffmpeg_converter_options($key = null) { +function ffmpeg_converter_options($key = NULL) { static $presets; - + if (!isset($presets)) { $presets = variable_get('ffmpeg_converter_presets', array( 'preset-1' => array( @@ -334,7 +340,7 @@ $preset['ffmpeg_wrapper'] = $options; } } - + if (!empty($key)) { return $presets[$key]['ffmpeg_wrapper']; } @@ -356,13 +362,13 @@ 'ffmpeg_audio_advanced' => 0, 'ffmpeg_audio_ab' => 64, 'ffmpeg_audio_ar' => 22050, - 'ffmpeg_audio_acodec' => null, + 'ffmpeg_audio_acodec' => NULL, 'ffmpeg_video_advanced' => 0, 'ffmpeg_video_size' => '320x240', 'ffmpeg_video_size_other' => '', 'ffmpeg_video_fps' => 25, 'ffmpeg_video_br' => 384, - 'ffmpeg_video_vcodec' => null, + 'ffmpeg_video_vcodec' => NULL, 'ffmpeg_time_advanced' => 0, 'ffmpeg_time' => 300, 'ffmpeg_video_custom' => 0, @@ -370,7 +376,7 @@ 'ffmpeg_video_wm' => 0, 'ffmpeg_video_wm_file' => '', 'ffmpeg_output_perms' => '0644', - ); + ); } @@ -386,7 +392,7 @@ foreach ($presets as $key => $preset) { $preset_names[$key] = $preset['name']; } - + return $preset_names; } @@ -397,15 +403,15 @@ * @param $field * The name of the file field. * @return - * A preset key if the field has one assigned, false otherwise. + * A preset key if the field has one assigned, FALSE otherwise. */ function ffmpeg_converter_preset_by_field($field) { - $setting = variable_get('ffmpeg_converter_' . $field, array('preset' => 'disabled')); + $setting = variable_get('ffmpeg_converter_'. $field, array('preset' => 'disabled')); if (!empty($setting['preset']) && $setting['preset'] != 'disabled') { return $setting['preset']; } else { - return false; + return FALSE; } } @@ -415,9 +421,8 @@ */ function ffmpeg_converter_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { if (in_array($op, array('insert', 'update', 'view'))) { - $view_messages = array(); - + // Get this node type's fields and look for FFmpeg Converter files. if (function_exists('content_fields')) { $fields = content_fields(); @@ -428,7 +433,7 @@ // Examine files (we assume this is a file field). $original = array(); $converted = array(); - foreach($node->$field['field_name'] as $field_instance => $file) { + foreach ($node->$field['field_name'] as $field_instance => $file) { // $file may be an array with empty values. if (!empty($file['fid'])) { if (!empty($file['data']['ffmpeg_converter_file'])) { @@ -444,36 +449,62 @@ case 'insert': case 'update': // Look for new files. - if (!empty($original) && empty($converted) && !ffmpeg_converter_file_is_queued($node->nid, $field['field_name'])) { + if (!empty($original) && empty($converted)) { list($field_instance, $file) = array_pop($original); - if (ffmpeg_converter_check_file($file['filename'], $preset_key)) { - // Queue file for processing. - ffmpeg_converter_queue_filefield($node->nid, $field['field_name'], 0, $preset_key); - drupal_set_message(t('The file %file was added to the job queue.', array('%file' => check_plain($file['filename'])))); + $snapshot = FALSE; + $convert = FALSE; + $message = 'The file %file was added to the job queue to'; + if (!ffmpeg_converter_file_is_queued($node->nid, $field['field_name']) && ffmpeg_converter_check_file($file['filename'], $preset_key)) { + $convert = TRUE; + $message .= ' convert the file'; + } + if (!ffmpeg_converter_snapshots_are_queued($node->nid, $field['field_name']) && ffmpeg_converter_check_snapshots($node, $field['field_name'])) { + $snapshot = TRUE; + if ($convert) { + $message .= ' and '; + } + $message .= ' create snapshots of the file'; + } + $message .= '.'; + if ($convert || $snapshot) { + ffmpeg_converter_queue($node->nid, $field['field_name'], 0, $preset_key, $convert, $snapshot); + drupal_set_message(t($message, array('%file' => check_plain($file['filename'])))); } } break; case 'view': - // Look for unconverted files and hide from display. - // TODO: Respect user's option to hide or show original files. - if (!empty($original) && empty($converted)) { - list($field_instance, $file) = array_pop($original); - // Make sure that original file even needs to be converted. - if(ffmpeg_converter_check_file($file['filename'], $preset_key)) { - unset($node->content[$field['field_name']]['field']['items'][$field_instance]); - // Add message to node content for files that are being converted. - $view_messages[] = array( - 'message' => t('The file %file is waiting to be converted.', array('%file' => $file['filename'])), - 'filename' => $file['filename'], - ); + // Use variable information to decide what to display during teaser or full node view. + $setting = variable_get('ffmpeg_converter_'. $field['field_name'], FALSE); + if ($setting) { + // Look for unconverted files and hide from display. + if (!empty($original) && empty($converted)) { + list($field_instance, $file) = array_pop($original); + // make sure that original file even needs to be converted. + if (ffmpeg_converter_check_file($file['filename'], $preset_key)) { + unset($node->content[$field['field_name']]['field']['items'][$field_instance]); + // Add message to node content for files that are being converted. + $view_messages[] = array( + 'message' => t('The file %file is waiting to be converted.', array('%file' => $file['filename'])), + 'filename' => $file['filename'], + ); + } + } + else if ($setting['hide_original'] == 1 && $a3 != 1) { + $all = array_merge($original, $converted); + while (count($all) > 0) { + list($field_instance, $file) = array_pop($all); + if ($file['data']['ffmpeg_converter_file'] != 'converted') { + unset($node->content[$field['field_name']]['field']['items'][$field_instance]); + } + } } } break; - } + } } } } - + if ($op = 'view' && !empty($view_messages)) { $node->content['ffmpeg_converter_messages'] = array( '#value' => theme('ffmpeg_converter_messages', $view_messages) @@ -497,22 +528,45 @@ function ffmpeg_converter_check_file($filename, $preset_key) { $presets = ffmpeg_converter_options(); $extension = array_pop(explode('.', $filename)); - + // Check if file type differs from destination type. if ($presets[$preset_key]['ffmpeg_wrapper']['ffmpeg_output_type'] != $extension) { return TRUE; } - + // Check the "process same format" setting. if ($presets[$preset_key]['process_same_format']) { return TRUE; } - + return FALSE; } /** + * Check if snapshots have been created. + * + * @param $node + * The node to check. + * @param $field_name + * The name of the field in question. + * @return $no_snapshots + * True if no snapshots exist or FALSE otherwise. + */ +function ffmpeg_converter_check_snapshots($node, $field_name) { + $no_snapshots = TRUE; + + foreach ($node->{$field_name} as $s_file) { + if ($s_file['data']['ffmpeg_converter_file'] == 'snapshot') { + $no_snapshots = FALSE; + break; + } + } + + return $no_snapshots; +} + +/** * Add a file field to the process queue. * * @param $nid @@ -524,16 +578,25 @@ * $node->{$field_name} array. * @param $preset_key * The key of the FFmpeg Converter preset to use. + * @param $convert + * If TRUE, convert source file to preset. + * @param $snapshot + * If TRUE, create snapshots of source file. * @return * FALSE if Job queue is unavailable, NULL otherwise. */ -function ffmpeg_converter_queue_filefield($nid, $field_name, $field_instance, $preset_key) { +function ffmpeg_converter_queue($nid, $field_name, $field_instance, $preset_key, $convert = FALSE, $snapshot = FALSE) { if (function_exists('job_queue_add')) { - cache_clear_all('ffmpeg_converter_queued_files', 'cache'); - return job_queue_add('ffmpeg_converter_convert_filefield', t('Convert a file field with FFmpeg.'), array($nid, $field_name, $field_instance, $preset_key)); + if ($convert) { + cache_clear_all('ffmpeg_converter_queued_files', 'cache'); + } + if ($snapshot) { + cache_clear_all('ffmpeg_converter_queued_snapshots', 'cache'); + } + return job_queue_add('ffmpeg_converter_convert_queue', t('Convert file and/or create snapshots of a file field with FFmpeg.'), array($nid, $field_name, $field_instance, $preset_key, $convert, $snapshot)); } else { - return false; + return FALSE; } } @@ -545,12 +608,12 @@ * The nid of the node containing the file. * @param $field * The name of the field containing the file. - * @return + * @return * TRUE or FALSE. */ function ffmpeg_converter_file_is_queued($nid, $field) { $cache = cache_get('ffmpeg_converter_queued_files'); - + if ($cache) { $files = $cache->data; } @@ -559,12 +622,42 @@ $files = array(); while ($job = db_fetch_array($jobs)) { $args = unserialize($job['arguments']); - $files[] = $args[0] . '-' . $args[1]; + $files[] = $args[0] .'-'. $args[1]; } cache_set('ffmpeg_converter_queued_files', $files); } - - return in_array($nid . '-' . $field, $files); + + return in_array($nid .'-'. $field, $files); +} + + +/** + * Check if a file's snapshots are already in the job queue. + * + * @param $nid + * The nid of the node containing the file. + * @param $field + * The name of the field containing the file. + * @return + * TRUE or FALSE. + */ +function ffmpeg_converter_snapshots_are_queued($nid, $field) { + $cache = cache_get('ffmpeg_converter_queued_snapshots'); + + if ($cache) { + $files = $cache->data; + } + else { + $jobs = db_query("SELECT * FROM {job_queue} WHERE function = 'ffmpeg_converter_snapshots'"); + $files = array(); + while ($job = db_fetch_array($jobs)) { + $args = unserialize($job['arguments']); + $files[] = $args[0] .'-'. $args[1]; + } + cache_set('ffmpeg_converter_queued_snapshots', $files); + } + + return in_array($nid .'-'. $field, $files); } @@ -585,7 +678,7 @@ return job_queue_add('ffmpeg_converter_convert_drupalfile', t('Convert a Drupal file with FFmpeg.'), array($fid, $nid, $preset_key, $link)); } else { - return false; + return FALSE; } } @@ -609,7 +702,7 @@ /** - * Enter description here... + * * * @param $nid * The id of the container node. @@ -620,52 +713,84 @@ * $node->{$field_name} array. * @param $preset_key * The key of the FFmpeg Converter preset to use. + * @param $convert + * If TRUE, convert source file to preset. + * @param $snapshot + * If TRUE, create snapshots of source file. */ -function ffmpeg_converter_convert_filefield($nid, $field_name, $field_instance, $preset_key) { - +function ffmpeg_converter_convert_queue($nid, $field_name, $field_instance, $preset_key, $convert, $snapshot) { $node = node_load($nid); - + + if ($convert && !empty($node)) { + $node = ffmpeg_converter_convert_filefield($node, $field_name, $field_instance, $preset_key); + } + if ($snapshot && ($node || !empty($node))) { + $node = ffmpeg_converter_snapshots($node, $field_name, $field_instance, $preset_key); + } + + // Save the node. + if ($node || !empty($node)) { + node_save($node); + } +} + + +/** + * Enter description here... + * + * @param $node + * The container node. + * @param $field_name + * The name of the field that contains the source file. + * @param $field_instance + * The field instance as an integer representing the key in the + * $node->{$field_name} array. + * @param $preset_key + * The key of the FFmpeg Converter preset to use. + */ +function ffmpeg_converter_convert_filefield($node, $field_name, $field_instance, $preset_key) { + // Clear the cached list of queued files. cache_clear_all('ffmpeg_converter_queued_files', 'cache'); - + // Check the necessary prerequisites. - if (empty($node) || empty($node->{$field_name}[$field_instance]['fid']) || !function_exists('content_fields')) { - return false; + if (empty($node->{$field_name}[$field_instance]['fid']) || !function_exists('content_fields')) { + return FALSE; } - + // Load the .inc pages that we need. module_load_include('inc', 'node', 'node.pages'); module_load_include('inc', 'filefield', 'field_file'); - + if (!function_exists('field_file_save_file')) { - return false; + return FALSE; } - + // Load the CCK field. $field = content_fields($field_name, $node->type); - + // Get preset configuration. $configuration = ffmpeg_converter_options($preset_key); - + // Setup paths. $input_file = $node->{$field_name}[$field_instance]['filepath']; $output_file = ffmpeg_converter_filename($input_file, $configuration['ffmpeg_output_type']); - $output_file = file_directory_temp() . '/' . basename($output_file); - + $output_file = file_directory_temp() .'/'. basename($output_file); + // Run conversion and check result. - $result = ffmpeg_converter_convert($input_file, $output_file, $configuration, l(t('Source node'), 'node/' . $node->nid)); + $result = ffmpeg_converter_convert($input_file, $output_file, $configuration, l(t('Source node'), 'node/'. $node->nid)); if (!$result) { - return false; + return FALSE; } - + // We don't use filefield validators for saving generated files. We could use // filefield_widget_upload_validators($field) to fetch the configured // restrictions for this field, but that might lead to situations where // conversions will fail inexplicably. $validators = array(); - + // Create the file object. - $destination_path = filefield_widget_file_path($field); + $destination_path = str_replace('/'. $node->{$field_name}[$field_instance]['filename'], '', $node->{$field_name}[$field_instance]['filepath']); $file = field_file_save_file($output_file, $validators, $destination_path); if (!is_array($file['data'])) { @@ -676,75 +801,119 @@ if (!empty($node->{$field_name}[$field_instance]['data']['description'])) { $file['data']['description'] = $node->{$field_name}[$field_instance]['data']['description']; } - + // Leave a note that this is a converted file. $file['data']['ffmpeg_converter_file'] = 'converted'; - + // Attempt to get MIME type with mimedetect. if (function_exists('mimedetect_mime')) { $file['filemime'] = mimedetect_mime($output_file); } - + // Add the file to the node. $node->{$field_name}[] = $file; - + + // Save the node. + $node = node_submit($node); + + watchdog('ffmpeg_converter', 'FFmpeg converted the file %file to @format.', + array('%file' => basename($input_file), '@format' => $configuration['ffmpeg_output_type']), + WATCHDOG_NOTICE, l(t('Source node'), 'node/'. $node->nid)); + + return $node; +} + + +/** + * Enter description here... + * + * @param $node + * The container node. + * @param $field_name + * The name of the field that contains the source file. + * @param $field_instance + * The field instance as an integer representing the key in the + * $node->{$field_name} array. + * @param $preset_key + * The key of the FFmpeg Converter preset to use. + */ +function ffmpeg_converter_snapshots($node, $field_name, $field_instance, $preset_key) { + + cache_clear_all('ffmpeg_converter_queued_snapshots', 'cache'); + + // Check the necessary prerequisites. + if (empty($node->{$field_name}[$field_instance]['fid']) || !function_exists('content_fields')) { + return FALSE; + } + + // Load the .inc pages that we need. + module_load_include('inc', 'node', 'node.pages'); + module_load_include('inc', 'filefield', 'field_file'); + + if (!function_exists('field_file_save_file')) { + return FALSE; + } + + // Get preset configuration. + $configuration = ffmpeg_converter_options($preset_key); + + // Setup paths. + $input_file = $node->{$field_name}[$field_instance]['filepath']; + // Try to get video duration and determine if this is a video file. - $duration = ffmpeg_wrapper_file_duration($input_file, false); - + $duration = ffmpeg_wrapper_file_duration($input_file, FALSE); + if ($duration) { - // Take three snapshot images of the film. - $duration = ffmpeg_wrapper_file_duration($input_file, false); + $duration = ffmpeg_wrapper_file_duration($input_file, FALSE); $offsets = array( round($duration / 4), round($duration / 2), round($duration * 3 / 4), ); - + foreach ($offsets as $offset) { // Format time code. $timecode = str_pad($offset / 3600 % 24, 2, '0', STR_PAD_LEFT); - $timecode .= ':' . str_pad($offset / 60 % 60, 2, '0', STR_PAD_LEFT); - $timecode .= ':' . str_pad($offset % 60, 2, '0', STR_PAD_LEFT); - + $timecode .= ':'. str_pad($offset / 60 % 60, 2, '0', STR_PAD_LEFT); + $timecode .= ':'. str_pad($offset % 60, 2, '0', STR_PAD_LEFT); + // Create snapshot image. $size = $configuration[$configuration['ffmpeg_video_size'] == 'other' ? 'ffmpeg_video_size_other' : 'ffmpeg_video_size']; if ($snapshot = ffmpeg_converter_create_snapshot($input_file, file_directory_temp(), $timecode, $size)) { - + // Create the snapshot file object. - $s_file = field_file_save_file($snapshot, $validators, $destination_path); - + $destination_path = str_replace('/'. $node->{$field_name}[$field_instance]['filename'], '', $node->{$field_name}[$field_instance]['filepath']); + $s_file = field_file_save_file($snapshot, array(), $destination_path); if (is_array($s_file)) { - + if (!is_array($s_file['data'])) { $s_file['data'] = array(); } - + // Copy file description from original to snapshot image. if (!empty($node->{$field_name}[$field_instance]['data']['description'])) { $s_file['data']['description'] = $node->{$field_name}[$field_instance]['data']['description']; } - + // Leave a note that this is a snapshot image file. $s_file['data']['ffmpeg_converter_file'] = 'snapshot'; - + // Add the snapshot image file to the node. $node->{$field_name}[] = $s_file; - - } } } } - - // Save the node. + $node = node_submit($node); - node_save($node); - - watchdog('ffmpeg_converter','FFmpeg converted the file %file to @format.', - array('%file' => basename($input_file), '@format' => $configuration['ffmpeg_output_type']), - WATCHDOG_NOTICE, l(t('Source node'), 'node/' . $node->nid)); + + watchdog('ffmpeg_converter', 'FFmpeg created the snapshots for %file.', + array('%file' => basename($input_file)), + WATCHDOG_NOTICE, l(t('Source node'), 'node/'. $node->nid)); + + return $node; } @@ -759,42 +928,42 @@ * @param $link * Optional HTML link tag, to the source node or similar, for log messages. * @return - * A file object on success, false on failure. + * A file object on success, FALSE on failure. */ function ffmpeg_converter_convert_drupalfile($fid, $preset_key, $link = '') { - + // Get the file object from the database. $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid); $file = db_fetch_object($result); - + $input_file = file_create_path($file->filepath); - + // Get preset configuration. $configuration = ffmpeg_converter_options($preset_key); - + // Construct output file path. $output_type = $configuration['ffmpeg_output_type']; $output_file = ffmpeg_converter_filename($input_file, $output_type); - $output_file = file_directory_temp() . '/' . basename($output_file); - + $output_file = file_directory_temp() .'/'. basename($output_file); + // Run conversion and check result. $result = ffmpeg_converter_convert($input_file, $output_file, $configuration, $link); if (!$result) { - return false; + return FALSE; } - + // Move temp file to permanent location. $permanent_path = file_destination(str_replace($file->filename, '', $file->filepath) . basename($output_file), FILE_EXISTS_RENAME); - if (!file_move($output_file, str_replace('/' . $file->filename, '', $file->filepath), FILE_EXISTS_RENAME)) { + if (!file_move($output_file, str_replace('/'. $file->filename, '', $file->filepath), FILE_EXISTS_RENAME)) { watchdog('ffmpeg_converter', 'Could not save converted file %file, keeping original.', array('%file' => $output_file), WATCHDOG_WARNING, $link); - return false; + return FALSE; } - + // Prepare new file attributes. $file->filepath = str_replace($file->filename, basename($output_file), $file->filepath); $file->filename = basename($output_file); $file->filesize = filesize($output_file); - + // Get MIME type. if (function_exists('mimedetect_mime')) { $file->filemime = mimedetect_mime($output_file); @@ -805,24 +974,26 @@ // Save changes to database. if (!db_query("UPDATE {files} SET filename = '%s', filepath = '%s', filesize = %d, filemime = '%s', timestamp = %d WHERE fid = %d", - $file->filename, $file->filepath, $file->filesize, $file->filemime, time(), $file->fid)) { + $file->filename, $file->filepath, $file->filesize, $file->filemime, time(), $file->fid)) { watchdog('ffmpeg_converter', 'Could not save converted file %file to the database, keeping original.', - array('%file' => $output_file), WATCHDOG_WARNING, $link); - return false; + array('%file' => $output_file), WATCHDOG_WARNING, $link); + + return FALSE; } content_update(&$node); - + // Clear content cache. - cache_clear_all('content:', 'cache_content', true); - - watchdog('ffmpeg_converter','FFmpeg converted the file %file to @format.', - array('%file' => basename($input_file), '@format' => $output_type), - WATCHDOG_NOTICE, $link); - + cache_clear_all('content:', 'cache_content', TRUE); + + watchdog('ffmpeg_converter', 'FFmpeg converted the file %file to @format.', + array('%file' => basename($input_file), '@format' => $output_type), + WATCHDOG_NOTICE, $link); + return $file; } + /** * Convert a file with FFmpeg Wrapper. * @@ -838,14 +1009,14 @@ * FFmpeg Wrapper result code. */ function ffmpeg_converter_convert($input_file, $output_file, $configuration, $link = '') { - + // Make sure that FFmpeg can decode the input file. if (!ffmpeg_wrapper_can_decode($input_file)) { watchdog('ffmpeg_converter', 'FFmpeg can not decode this file type: %file', array('%file' => $input_file), WATCHDOG_WARNING, $link); - return false; + return FALSE; } - + // Go through configuration and build the command line options for FFmpeg. $options = array(); @@ -869,26 +1040,26 @@ } // Make sure output size is a multiple of 2 (required by FFmpeg). - - + + // Create padded frame size. $pad = ffmpeg_converter_get_padded_size($input_file, $size, 'padding'); $size = ffmpeg_converter_get_padded_size($input_file, $size, 'size'); - + // Use a custom option string. if ($configuration['ffmpeg_video_custom']) { - $configuration['ffmpeg_video_custom_command'] = str_replace($matches[1], $size . ' ' . $pad, $configuration['ffmpeg_video_custom_command']); - $options[] = str_replace(array('%in_file', '%out_file'), array($input_file, $output_file), $configuration['ffmpeg_video_custom_command']); + $configuration['ffmpeg_video_custom_command'] = str_replace($matches[1], $size .' '. $pad, $configuration['ffmpeg_video_custom_command']); + $options[] = str_replace(array('%in_file', '%out_file'), array($input_file, $output_file), $configuration['ffmpeg_video_custom_command']); } - + // Build command line options from config options. else { - $options[] = "-i '" . $input_file . "'"; - + $options[] = "-i '". $input_file ."'"; + if ($configuration['ffmpeg_video_wm']) { - $options[] = "-vhook '" . ffmpeg_wrapper_path_to_vhook('watermark.so') . " -f " . $configuration['ffmpeg_video_wm_file'] . "'"; + $options[] = "-vhook '". ffmpeg_wrapper_path_to_vhook('watermark.so') ." -f ". $configuration['ffmpeg_video_wm_file'] ."'"; } - + if ($configuration['ffmpeg_audio_advanced']) { if ($configuration['ffmpeg_audio_acodec']) { $options[] = '-acodec '. $configuration['ffmpeg_audio_acodec']; @@ -900,12 +1071,12 @@ $options[] = '-ab '. $configuration['ffmpeg_audio_ab']; } } - + if ($configuration['ffmpeg_video_advanced']) { if ($configuration['ffmpeg_video_vcodec']) { $options[] = '-vcodec '. $configuration['ffmpeg_video_vcodec']; } - $options[] = '-s '. $size . ' ' . $pad; + $options[] = '-s '. $size .' '. $pad; if ($configuration['ffmpeg_video_br']) { $options[] = '-b '. $configuration['ffmpeg_video_br']; } @@ -914,45 +1085,45 @@ } } else { - $options[] = '-s '. $size . ' ' . $pad; + $options[] = '-s '. $size .' '. $pad; } - + if ($configuration['ffmpeg_time_advanced']) { $options[] = '-t '. $configuration['ffmpeg_time']; } - + // Replace existing files without asking any questions. (Use temp files!) $options[] = '-y'; - + $options[] = "'". $output_file ."'"; } - + $command = implode(" ", $options); // Run FFmpeg with error checking. - $output = ffmpeg_wrapper_run_command($command, true); - + $output = ffmpeg_wrapper_run_command($command, TRUE); + if (variable_get('ffmpeg_converter_debug', 0)) { watchdog('ffmpeg_converter', 'FFmpeg was invoked with these options: %command', - array('%command' => $command), WATCHDOG_DEBUG, $link); + array('%command' => $command), WATCHDOG_DEBUG, $link); } - - // false is returned on error. - if ($output == false || !file_exists($output_file) || filesize($output_file) == 0) { + + // FALSE is returned on error. + if ($output == FALSE || !file_exists($output_file) || filesize($output_file) == 0) { watchdog('ffmpeg_converter', 'Conversion of %file failed unexpectedly. The command was: %command', - array('%file' => $output_file, '%command' => $command), WATCHDOG_WARNING, $link); - return false; + array('%file' => $output_file, '%command' => $command), WATCHDOG_WARNING, $link); + return FALSE; } - return true; + return TRUE; } /** * Create a snapshot image from a video file. - * + * * Based on video_thumbnailer_create_thumb() in Video Thumbnailer. - * + * * @param $file * Path to the input video file. * @param $output_path @@ -965,11 +1136,11 @@ * Filepath if successfull, FALSE otherwise. */ function ffmpeg_converter_create_snapshot($file, $output_path, $offset, $size = '320x240') { - + // Create output file path. $output_file = explode('.', basename($file)); array_pop($output_file); - $output_file = join('.', $output_file) . '-snapshot-' . $offset . '.jpg'; + $output_file = join('.', $output_file) .'-snapshot-'. $offset .'.jpg'; $output_file = str_replace(':', '-', $output_file); $output_file = str_replace(' ', '_', $output_file); $output_file = file_create_filename($output_file, $output_path); @@ -978,7 +1149,7 @@ // source file. $pad = ffmpeg_converter_get_padded_size($file, $size, 'padding'); $size = ffmpeg_converter_get_padded_size($file, $size, 'size'); - + // Prepare FFmpeg options. $options = array(); $options[] = "-ss $offset"; @@ -986,17 +1157,17 @@ $options[] = "-vcodec mjpeg -vframes 1 -an -f rawvideo -s '$size'"; $options[] = $pad; $options[] = "'$output_file'"; - + $command = implode(" ", $options); // Run the command. $output = ffmpeg_wrapper_run_command($command); - + if (variable_get('ffmpeg_converter_debug', 0)) { watchdog('ffmpeg_converter', 'FFmpeg was invoked with these options: %command', - array('%command' => $command), WATCHDOG_DEBUG, $link); + array('%command' => $command), WATCHDOG_DEBUG, $link); } - + if (file_exists($output_file)) { return $output_file; } @@ -1008,22 +1179,22 @@ /** * Calculate an output size and a padding value for a media file. - * - * This function has been moved to FFmpeg Wrapper, and it will eventually be + * + * This function has been moved to FFmpeg Wrapper, and it will eventually be * removed. * * @param $file * Path to the file to be converted. * @param $size * The maximum dimensions of the output file, expressed as XXXxYYY. This will - * be cropped to match the original file's proportions and the remaining + * be cropped to match the original file's proportions and the remaining * space will be used to calculate the padding. * @param $return * Either 'padding' or 'size'. * @return - * Depending on the value of $return, the function returns either the size - * expressed as XXXxYYY, or the actual padding argument for FFmpeg, ie. - * "-padtop XX -padbottom XX". The result is statically cached, so you can + * Depending on the value of $return, the function returns either the size + * expressed as XXXxYYY, or the actual padding argument for FFmpeg, ie. + * "-padtop XX -padbottom XX". The result is statically cached, so you can * call it multiple times without permormance issues. */ function ffmpeg_converter_get_padded_size($file, $size, $return = 'padding') { @@ -1031,10 +1202,10 @@ if (function_exists('ffmpeg_wrapper_padded_size')) { return ffmpeg_wrapper_padded_size($file, $size, $return); } - + // Cache file proportions statically. static $file_proportions; - + if (!isset($file_proportions)) { $file_proportions = array(); } @@ -1044,7 +1215,7 @@ else { $pad = ''; - + // Determine source file's dimensions and proportions. $output = ffmpeg_wrapper_run_command("-i $file"); $pattern = "/Stream.* ([0-9]+x[0-9]+)/"; @@ -1053,18 +1224,18 @@ if (!empty($matches[0])) { list($orig_x, $orig_y) = explode('x', $matches[1]); $orig_q = $orig_x / $orig_y; - + // Determine output dimensions and proportions. list($dest_x, $dest_y) = explode('x', $size); $dest_q = $dest_x / $dest_y; - + // Calculate new output size and padding. if ($orig_q > $dest_q) { // Width is the determining factor. $dest_y_calc = round($dest_x / $orig_q); // Make sure height is divisible by 2, otherwise ffmpeg freaks out. $dest_y_calc &= ~1; - $size = $dest_x . 'x' . $dest_y_calc; + $size = $dest_x .'x'. $dest_y_calc; $padding = $dest_y - $dest_y_calc; $padoptions = '-padtop %d -padbottom %d'; } @@ -1073,11 +1244,11 @@ $dest_x_calc = round($dest_y * $orig_q); // Make sure width is divisible by 2, otherwise ffmpeg freaks out. $dest_x_calc &= ~1; - $size = $dest_x_calc . 'x' . $dest_y; + $size = $dest_x_calc .'x'. $dest_y; $padding = $dest_x - $dest_x_calc; $padoptions = '-padleft %d -padright %d'; } - + // Calculate padding on each side. Each value has to be a multiple of 2. $padding &= ~1; $padding1 = floor($padding / 2); @@ -1112,19 +1283,20 @@ /** * Preprocess CCK field template. - * If this field has an FFmpeg converter preset, we do some processing to + * If this field has an FFmpeg converter preset, we do some processing to * enable a custom view of video files. + * @param $variables */ function ffmpeg_converter_preprocess_content_field(&$variables) { $element =& $variables['element']; - + $preset_key = ffmpeg_converter_preset_by_field($element['#field_name']); if ($preset_key) { $instance_keys = element_children($element['items']); - + // This field has a preset. Check if it has been converted. if (count($instance_keys) > 1) { - + // Look for converted file and snapshot images. $converted = array(); $snapshot = array(); @@ -1142,49 +1314,47 @@ elseif (empty($snapshot)) { $snapshot = $item['#item']; } - } } } - } - + // If this is a converted video file, replace the field items with a // linked snapshot image. if (!empty($converted) && !empty($snapshot)) { - + // Set template variables. $converted_path = base_path() . $converted['#item']['filepath']; $nid = $element['#node']->nid; - + $link_href = ''; $snapshot_path = ''; $width = ''; $height = ''; - + // Check field display settings. - if (isset($element['items'][0]['#formatter'])) { - $format = $element['items'][0]['#formatter']; + $field = content_fields($element['#field_name']); + if (arg(0) == 'node' && arg(1) == $nid) { + $format = $field['display_settings']['full']['format']; } else { - $field = content_fields($element['#field_name']); - $format = $field['display_settings']['full']['format']; + $format = $field['display_settings']['teaser']['format']; } $parts = explode('_', $format); $link_style = array_pop($parts); $presetname = implode('_', $parts); - + // Define where the image should link to. switch ($link_style) { case 'nodelink': case 'linked': - $link_href = url('node/' . $nid); + $link_href = url('node/'. $nid); break; case 'imagelink': $link_href = $converted_path; break; } - + // Check if the standard image should be displayed. if ($presetname == 'image') { $configuration = ffmpeg_converter_options($preset_key); @@ -1205,7 +1375,7 @@ $snapshot_path = base_path() . $snapshot['filepath']; } - + // Check if an Imagecache preset should be used. if (empty($snapshot_path) && function_exists('imagecache_presets')) { foreach (imagecache_presets() as $preset) { @@ -1221,12 +1391,11 @@ $height = $action['data']['height']; } } - break; } } } - + if (!empty($snapshot_path)) { // Replace the field display with a custom template. $converted['#children'] = theme('ffmpeg_converter_video', $converted['#item'], $converted_path, $snapshot, $snapshot_path, check_plain($converted['#item']['data']['description']), $nid, $width, $height, $link_href); @@ -1235,4 +1404,4 @@ } } } -} +} \ No newline at end of file