You are here

scald_video.module in Scald: Media Management made easy 7

Scald Video is a Scald Atom Provider for video files.

File

modules/providers/scald_video/scald_video.module
View source
<?php

/**
 * @file
 * Scald Video is a Scald Atom Provider for video files.
 */

/*******************************************************************************
 * SCALD HOOK IMPLEMENTATIONS
 */

/**
 * Implements hook_scald_atom_providers().
 */
function scald_video_scald_atom_providers() {
  return array(
    'video' => 'Upload Video file',
  );
}

/**
 * Implements hook_scald_add_form().
 */
function scald_video_scald_add_form(&$form, &$form_state) {
  scald_video_get_video_file_form($form['file']);
  $form['file']['#title'] = 'Video';
}

/**
 * Implements hook_scald_add_atom_count().
 */
function scald_video_scald_add_atom_count(&$form, &$form_state) {
  if (is_array($form_state['values']['file'])) {
    return max(count($form_state['values']['file']), 1);
  }
  return 1;
}

/**
 * Implements hook_scald_add_form_fill().
 */
function scald_video_scald_add_form_fill(&$atoms, $form, $form_state) {
  $dir_video_thumb = 'public://atoms/video/thumb';
  foreach ($atoms as $delta => $atom) {

    // Delta is used only with multifile field:
    if (is_array($form_state['values']['file'])) {

      // plupload infos:
      $file_infos = $form_state['values']['file'][$delta];
    }
    else {

      // This will be a fid:
      $file_infos = $form_state['values']['file'];
    }
    $file = scald_video_get_video_file($file_infos, $form['file']['#upload_location']);
    $atom->base_id = $file->fid;
    $atom->file_source = $file->uri;
    $atom->data['video_file'] = $file->uri;
    $atom->data['video_id'] = $file->fid;
    $atom->title = $file->filename;

    // @TODO : find lib to get metadatas from video files
  }
}

/**
 * Implements hook_scald_fetch().
 */
function scald_video_scald_fetch($atom, $type) {
  $file_items = field_get_items('scald_atom', $atom, 'scald_thumbnail');
  if (!empty($file_items)) {
    $file_item = current($file_items);
    if (file_exists($file_item['uri'])) {
      $atom->thumbnail_source = $file_item['uri'];
    }
  }
  $atom->file_source = $atom->data['video_file'];
}

/**
 * Implements hook_scald_atom_insert().
 */
function scald_video_scald_atom_insert($atom) {
  if ($atom->provider == 'scald_video') {
    $file = file_load($atom->data['video_id']);
    if ($file) {
      $file->status = FILE_STATUS_PERMANENT;
      file_save($file);
      file_usage_add($file, 'scald_video', 'scald_atom', $atom->sid);
    }
  }
}

/**
 * Implements hook_scald_prerender().
 */
function scald_video_scald_prerender($atom, $context, $options, $mode) {
  $video_datas = array();
  $video_datas[] = array(
    'path' => file_create_url($atom->file_source),
    'mime_type' => file_get_mimetype($atom->file_source),
  );

  // Loading alternative video sources:
  if (isset($atom->data['alternative_video_sources']) && count($atom->data['alternative_video_sources'])) {
    foreach ($atom->data['alternative_video_sources'] as $key => $video_file) {
      $video_datas[] = array(
        'path' => file_create_url($video_file->uri),
        'mime_type' => $video_file->filemime,
      );
    }
  }
  $video_sources = array();
  foreach ($video_datas as $key => $video) {
    $video_sources[] = array(
      'path' => $video['path'],
      'mime_type' => $video['mime_type'],
    );
  }
  if ($mode == 'atom') {
    $atom->rendered->player = theme('scald_video_player', array(
      'vars' => array(
        'atom' => $atom,
        'video_sources' => $video_sources,
        'video_width' => check_plain($atom->data['video_width']),
        'video_height' => check_plain($atom->data['video_height']),
        'thumbnail' => $atom->thumbnail_source,
        'class' => 'scald_video',
        'context' => $context,
      ),
    ));
  }
}

/**
 * Implements hook_theme().
 */
function scald_video_theme() {
  return array(
    'scald_video_player' => array(
      'variables' => array(
        'vars' => NULL,
      ),
      'template' => 'scald_video_player',
    ),
  );
}

/**
 * Implements hook_file_mimetype_mapping_alter().
 */
function scald_video_file_mimetype_mapping_alter(&$mapping) {
  if (!in_array('video/webm', $mapping['mimetypes'])) {
    $mapping['mimetypes'][] = 'video/webm';
    $mapping['extensions']['webm'] = count($mapping['mimetypes']) - 1;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function scald_video_form_scald_atom_add_form_options_alter(&$form, &$form_state) {

  // We check for multiple atoms on the form:
  if (isset($form_state['scald']['atom'])) {
    $atoms = array(
      $form_state['scald']['atom'],
    );
  }
  else {
    $atoms = $form_state['scald']['atoms'];
  }

  // Set one atom's form options. This can be called multiple times in case
  // a multifile field is used.
  foreach ($atoms as $key => $atom) {
    $form["atom{$key}"]['#tree'] = TRUE;
    if ($atom->provider !== 'scald_video') {
      break;
    }
    $width = '';
    $height = '';
    if (isset($atom->sid)) {
      if (isset($atom->data['video_width'])) {
        $width = $atom->data['video_width'];
      }
      if (isset($atom->data['video_height'])) {
        $height = $atom->data['video_height'];
      }
    }
    else {

      // Retrieve informations of Video by ffmpeg
      // http://ffmpeg-php.sourceforge.net/doc/api/ffmpeg_movie.php
      if (class_exists('ffmpeg_movie')) {
        $ffmpeg_video = new ffmpeg_movie(drupal_realpath($atom->file_source), FALSE);
        $ffmpeg_width = (int) $ffmpeg_video
          ->getFrameWidth();
        if ($ffmpeg_width > 0) {
          $width = check_plain($ffmpeg_width);
        }
        $ffmpeg_height = (int) $ffmpeg_video
          ->getFrameHeight();
        if ($ffmpeg_height > 0) {
          $height = check_plain($ffmpeg_height);
        }

        /* Does not work : page reset, but no error... (php and ffmpeg 5.4 from Linux Mint)
           $title = $ffmpeg_video->getTitle();
           if ($title != '') {
             $form['title']['#default_value'] = check_plain($title);
           }*/
      }
    }
    $form["atom{$key}"]['width'] = array(
      '#type' => 'textfield',
      '#title' => t('Width'),
      '#size' => 10,
      '#element_validate' => array(
        'element_validate_integer_positive',
      ),
      '#required' => TRUE,
      '#default_value' => $width,
    );
    $form["atom{$key}"]['height'] = array(
      '#type' => 'textfield',
      '#title' => t('Height'),
      '#size' => 10,
      '#element_validate' => array(
        'element_validate_integer_positive',
      ),
      '#required' => TRUE,
      '#default_value' => $height,
    );

    // Multi sources support: (https://drupal.org/node/2074349):
    $form["atom{$key}"]['uploaded_video_sources'] = array(
      '#tree' => TRUE,
    );
    $uploaded_videos_form =& $form["atom{$key}"]['uploaded_video_sources'];
    $uploaded_videos_form['description']['#markup'] = '<label>Alternative video sources</label>';
    $uploaded_videos_form['description']['#markup'] .= 'Alternative sources will be used as additional source tags within the video.<br/>';
    if (isset($atom->data['alternative_video_sources']) && count($atom->data['alternative_video_sources'])) {
      $uploaded_videos_form['description']['#markup'] .= 'Uncheck to remove additional source file from the atom.';
      foreach ($atom->data['alternative_video_sources'] as $source_key => $video_file) {
        $uploaded_videos_form[$source_key] = array(
          '#type' => 'checkbox',
          '#title' => l($video_file->filename, file_create_url($video_file->uri)),
          '#default_value' => 1,
        );
      }
    }
    scald_video_get_video_file_form($form["atom{$key}"]['alternative_video_sources']);
  }
  $form['#submit'][] = 'scald_video_form_scald_atom_add_form_options_submit';
}

/**
 * Atom's form save and edit submit callback.
 */
function scald_video_form_scald_atom_add_form_options_submit($form, &$form_state) {

  // We check for multiple atoms on the form:
  if (isset($form_state['scald']['atom'])) {
    $atoms = array(
      $form_state['scald']['atom'],
    );
  }
  else {
    $atoms = $form_state['scald']['atoms'];
  }
  foreach ($atoms as $key => $atom) {
    if ($atom->provider !== 'scald_video') {
      break;
    }
    $atom->data['video_width'] = $form_state['values']["atom{$key}"]['width'];
    $atom->data['video_height'] = $form_state['values']["atom{$key}"]['height'];

    // Updating uploaded alternative sources:
    if (isset($atom->data['alternative_video_sources']) && count($atom->data['alternative_video_sources'])) {
      foreach ($atom->data['alternative_video_sources'] as $source_key => $source) {

        // Removing unchecked sources:
        if (!$form_state['values']["atom{$key}"]['uploaded_video_sources'][$source_key]) {
          unset($atom->data['alternative_video_sources'][$source_key]);
        }
      }
    }
    if (isset($form["atom{$key}"]['alternative_video_sources'])) {
      $atom_form = $form["atom{$key}"]['alternative_video_sources'];
      $atom_form_state = $form_state['values']["atom{$key}"]['alternative_video_sources'];

      // Check for new alternative sources from plupload:
      if (is_array($atom_form_state)) {
        foreach ($atom_form_state as $source_key => $video_source) {
          $file = scald_video_get_video_file($atom_form_state[$source_key], $atom_form['#upload_location']);
          $atom->data['alternative_video_sources'][] = $file;
        }
      }
      else {
        $file = scald_video_get_video_file($atom_form_state, $atom_form['#upload_location']);
        if ($file !== FALSE) {
          $atom->data['alternative_video_sources'][] = $file;
        }
      }
    }
    scald_atom_save($atom);
  }
}

/**
 * Returns a video file form element compatible with plupload.
 * This function avoid repetitions over the multiple places
 * a file upload field is needed in scald_video.
 * 
 * @param $form_element
 *   The form element we want to set to video file field.
 *
 */
function scald_video_get_video_file_form(&$form_element) {
  if (module_exists('plupload')) {
    $form_element = array(
      '#type' => 'plupload',
      '#plupload_settings' => array(
        'runtimes' => 'html5',
        'chunk_size' => '1mb',
      ),
    );
  }
  else {
    $defaults = scald_atom_defaults('video');
    $form_element['#type'] = $defaults->upload_type;
  }
  $form_element['#upload_validators'] = array(
    'file_validate_extensions' => array(
      'webm mp4 ogv',
    ),
  );
  $form_element['#upload_location'] = variable_get('scald_video_upload_location', 'public://atoms/video/');
}

/**
 * Saves a video file from a form's file value.
 */
function scald_video_get_video_file($file_form_value, $location = NULL) {
  if (is_null($location)) {
    $location = variable_get('scald_video_upload_location', 'public://atoms/video/');
  }
  if (is_array($file_form_value) && module_exists('plupload')) {
    module_load_include('inc', 'scald', 'includes/scald.plupload');
    $file = scald_plupload_save_file($file_form_value['tmppath'], $location . $file_form_value['name']);
  }
  else {
    $file = file_load($file_form_value);
  }
  return $file;
}

/**
 * Implements hook_wysiwyg_editor_settings_alter().
 *
 * This is a patch for using CKEditor 4.x with the WYSIWYG module.
 * Without this patch, all works fine except the video preview in the WYSIWYG editor.
 * This patch allow <video> and <source> tags.
 */
function scald_video_wysiwyg_editor_settings_alter(&$settings, $context) {
  if ($context['profile']->editor == 'ckeditor') {
    $settings['extraAllowedContent'] = array(
      'video[controls,height,width,id,preload]',
      'source[src,type]',
    );
  }
}