You are here

video.module in Video 6.2

video.module

@author Heshan Wanigasooriya <heshan at heidisoft dot com> <heshanmw at gmail dot com> @author Glen Marianko Twitter@demoforum <glenm at demoforum dot com> @todo

File

video.module
View source
<?php

/**
 * @file video.module
 *
 * @author Heshan Wanigasooriya <heshan at heidisoft dot com>
 *                              <heshanmw at gmail dot com>
 * @author Glen Marianko Twitter@demoforum <glenm at demoforum dot com>
 * @todo
 */

// the id in the select field for manually assign resolution values. See functions below.
define("VIDEO_MANUALLY_SET_VIDEO_RESOLUTION_SELECT_ID", 30);

/** GMM: Views 2
 *  Implementation of hook_views_api()
 */
function video_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'video') . '/views',
  );
}

/**
 *  Implementation of hook_views_handlers()
 */
function video_views_handlers() {
  return array(
    'info' => array(
      'path' => drupal_get_path('module', 'video') . '/views',
    ),
    'handlers' => array(
      'video_views_handler_field_playtime_seconds' => array(
        'parent' => 'views_handler_field',
      ),
      'video_views_handler_field_download' => array(
        'parent' => 'views_handler_field',
      ),
      'video_views_handler_field_play' => array(
        'parent' => 'views_handler_field',
      ),
      'video_views_handler_field_image' => array(
        'parent' => 'views_handler_field',
      ),
    ),
  );
}

/********************************************************************
 * General Hooks
 ********************************************************************/

/**
 * Help hook
 * Implementation of hook_help
 * @param $section
 *   string of the area of Drupal where help was requested
 *
 * @return
 *   string of help information
 */
function video_help($path, $arg) {
  switch ($path) {
    case 'admin/help#video':
      $output = '<p>' . t('The Video Module is used to create and administrator Video nodes for Drupal') . '</p>';
      return $output;
  }
}

/**
 * Implementation of hook_menu().
 *
 * @param $may_cache
 *   boolean indicating whether cacheable menu items should be returned
 *
 * @return
 *   array of menu information
 */
function video_menu() {
  global $user;
  $items = array();
  $items['video'] = array(
    'title' => 'videos',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'video_page',
    ),
    'access arguments' => array(
      'access video',
    ),
    'type' => MENU_SUGGESTED_ITEM,
  );
  $items['video/feed'] = array(
    'title' => 'videos feed',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'video_feed',
    ),
    'access arguments' => array(
      'access video',
    ),
    'type' => MENU_CALLBACK,
  );
  $items["node/add/video"] = array(
    'title' => 'Video',
    'description' => 'Allow a variety of video formats to be posted as nodes in your site',
    'page callback' => 'video_add',
    'access arguments' => array(
      'create video',
    ),
  );
  $items['admin/settings/video'] = array(
    'title' => 'Video',
    'description' => 'Configure different aspects of the video module and its plugins',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'video_settings_form',
    ),
    'access arguments' => array(
      'administer video',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  $items['node/%/download'] = array(
    'title' => 'Download',
    'page callback' => 'video_download',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'video_download_access',
    'access arguments' => array(
      'access video',
    ),
    'weight' => 5,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

// GMM: Access Callback to check if user has rights to download page, throw access denied rather
//      than blank page (in case /download appended to URL some non-video node)
function video_download_access() {
  if (arg(0) == 'node' && is_numeric(arg(1))) {
    $node = node_load(arg(1));
    if ($node->type == 'video' && $node->vidfile && user_access('access video')) {

      //If the video is of type youtube and multi-file downloads aren't turned on don't show the download tab.
      if (video_support_download($node) && $node->disable_multidownload != 1) {
        return true;
      }
    }
  }
  return false;
}

/**
 * Internal Drupal links hook
 *
 * @param $type
 *   string type of link to show
 *
 * @param $node
 *   object of node information
 *
 * @return
 *   array of link information
 */
function video_link($type, $node = NULL) {
  $link = array();

  // Node links for a video
  if ($type == 'node' && $node->type == 'video' && $node->vidfile && user_access('access video')) {

    //If the video is of type youtube and multi-file downloads aren't turned on don't show the download link.
    if (!video_support_download($node) || $node->disable_multidownload == 1) {
      $display_download_link = 0;
    }
    else {
      $display_download_link = variable_get('video_displaydownloadlink', 1);
    }
    if ($display_download_link == 1) {
      $link['video_download'] = array(
        'title' => t('download'),
        'href' => "node/{$node->nid}/download",
        'attributes' => array(
          'class' => 'outgoing',
          'title' => t('download @link', array(
            '@link' => $node->title,
          )),
        ),
      );
    }
    if (variable_get('video_displayplaytime', 1) && $node->playtime_seconds > 0) {

      // hide the duration if the admin hided it or we don't have playtime informations
      $link['playtime'] = array(
        'title' => format_interval($node->playtime_seconds),
      );
    }
    if (variable_get('video_displayfilesize', 1) && $node->size != 0) {
      $link['size'] = array(
        'title' => format_size($node->size),
      );
    }
    if (variable_get('video_playcounter', 1) && user_access('view play counter')) {
      $link['play_counter'] = array(
        'title' => format_plural($node->play_counter, '1 play', '@count plays'),
      );
    }
    if (variable_get('video_downloadcounter', 1) && user_access('view download counter') && video_support_download($node)) {
      $link['download_counter'] = array(
        'title' => format_plural($node->download_counter, '1 download', '@count downloads'),
      );
    }
    return $link;
  }
  return array();
}

/**
 * Displays a Drupal page containing recently added videos
 *
 * @return
 *   string HTML output
 */
function video_page() {
  theme('video_page', NULL);
}

/**
 * Displays a Drupal page containing recently added videos
 *
 * @return
 *   string HTML output
 */
function theme_video_page() {
  $output = '';
  if (arg(1) != 'help') {

    //We are not reading help so output a list of recent video nodes.
    $result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'video' AND n.status = 1 ORDER BY n.created DESC"), variable_get('default_nodes_main', 10));
    while ($node = db_fetch_object($result)) {
      $output .= node_view(node_load($node->nid), 1);
    }
    $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));

    // adds feed icon and link
    drupal_add_link(array(
      'rel' => 'alternate',
      'type' => 'application/rss+xml',
      'title' => variable_get('site_name', 'drupal') . ' ' . t('videos'),
      'href' => url('video/feed/'),
    ));
    $output .= '<br />' . theme('feed_icon', url('video/feed'), t('Syndicate'));
  }
  return $output;
}

/**
 * Generate an RSS feed for videos
 *
 * @return
 *   feed
 */
function video_feed() {
  $channel = array(
    'title' => variable_get('site_name', 'drupal') . ' ' . t('videos'),
    'description' => t('Latest videos on') . ' ' . variable_get('site_name', 'drupal'),
    'link' => url('video', array(
      'absolute' => TRUE,
    )),
  );
  $result = db_fetch_object(db_query('SELECT n.nid FROM {node} n WHERE n.type = "video" AND n.status = 1 ORDER BY n.created DESC'));
  node_feed($result, $channel);
}

/**
 * Permissions hook
 *
 * @return
 *   array of permissions
 */
function video_perm() {
  $array = array(
    'create video',
    'access video',
    'administer video',
    'play video',
    'download video',
    'view play counter',
    'view download counter',
    'edit own video',
    'edit all video nodes',
    'manually set video resolution',
  );
  return $array;
}

/**
 * Settings Hook
 *
 * @return
 *   string of form content or error message
 */
function video_settings_form() {
  global $base_url;
  $form = array();
  $form['menu'] = array(
    '#type' => 'fieldset',
    '#title' => t('General behavior'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $vtypes = video_get_types_infos();
  if ($vtypes) {

    // no vtype available
    $video_types = array();
    foreach ($vtypes as $vtype => $info) {
      $video_types[$vtype] = $info['#name'];
    }
    $video_types[0] = t('No default type');
    $form['menu']['video_default_video_type'] = array(
      '#type' => 'select',
      '#title' => t('Choose default video type'),
      '#default_value' => variable_get('video_default_video_type', 0),
      '#description' => t('For installations that have more than one video type available, this sets the default video type when a user visits node/add/video'),
      '#options' => $video_types,
    );
  }

  // GMM: No longer supported, non-standard use of tab - use download link under video

  /*
    $form['menu']['video_displaydownloadmenutab'] = array(
      '#type' => 'checkbox',
      '#title' => t('Display download menu tab'),
      '#default_value' => variable_get('video_displaydownloadmenutab', 1),
      '#description' => t('Toggle display of menu tab to download video from the node page.')
    );
  */
  $form['menu']['video_in_teaser'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display video in node teaser'),
    '#default_value' => variable_get('video_in_teaser', FALSE),
    '#description' => t('Display the video in the node teaser. For instance, when shown on the front page feed'),
  );
  $form['menu']['video_show_help_text'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show help text below video'),
    '#default_value' => variable_get('video_show_help_text', TRUE),
    '#description' => t('Enabling this may help users play the video.'),
  );
  $form['menu']['video_displaydownloadlink'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display download link'),
    '#default_value' => variable_get('video_displaydownloadlink', 1),
    '#description' => t('Toggle display of "download" link (below the node content in most themes).'),
  );
  $form['menu']['video_displayplaytime'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display playtime'),
    '#default_value' => variable_get('video_displayplaytime', 1),
    '#description' => t('Toggle the display of the playtime for a video.'),
  );
  $form['menu']['video_displayfilesize'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display filesize'),
    '#default_value' => variable_get('video_displayfilesize', 1),
    '#description' => t('Toggle the display of the filesize for a video.'),
  );
  $form['menu']['video_autoplay'] = array(
    '#type' => 'checkbox',
    '#title' => t('Automatically start video on page load'),
    '#default_value' => variable_get('video_autoplay', TRUE),
    '#description' => t('Start the video when the page and video loads'),
  );
  $form['resolutions'] = array(
    '#type' => 'fieldset',
    '#title' => t('Video resolutions'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['resolutions']["video_resolution_width"] = array(
    '#type' => 'textfield',
    '#title' => t("Default width"),
    '#default_value' => variable_get("video_resolution_width", 400),
    '#description' => t('The width which will be used to scale video during playing. This let all videos on the website look the same. <strong>NOTE:</strong> You can disable video scaling making this field blank.'),
  );
  $i = 1;
  while ($i <= 4) {
    $form['resolutions']["video_resolution_{$i}_name"] = array(
      '#type' => 'textfield',
      '#title' => t("Resolution {$i} name"),
      '#default_value' => variable_get("video_resolution_{$i}_name", ''),
    );
    $form['resolutions']["video_resolution_{$i}_value"] = array(
      '#type' => 'textfield',
      '#title' => t("Resolution {$i} value"),
      '#default_value' => variable_get("video_resolution_{$i}_value", ''),
      '#description' => t('The resolution: two numbers representing width and height separated by an "x"'),
    );
    $i++;
  }

  // statistics stuff
  $form['counters'] = array(
    '#type' => 'fieldset',
    '#title' => t('Statistics counters'),
    '#description' => t('To allow users to view counters visit: ') . l(t('access control'), 'admin/user/permissions'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['counters']['video_playcounter'] = array(
    '#type' => 'checkbox',
    '#title' => t('Count play hits'),
    '#default_value' => variable_get('video_playcounter', 1),
    '#description' => t('Counts a hit everytime someone views the play page.'),
  );
  $form['counters']['video_downloadcounter'] = array(
    '#type' => 'checkbox',
    '#title' => t('Count downloads'),
    '#default_value' => variable_get('video_downloadcounter', 1),
    '#description' => t('Counts a hit everytime someone downloads a video.'),
  );

  // Flash Settings
  $form['flash'] = array(
    '#type' => 'fieldset',
    '#title' => t('Flash settings'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );

  // check flowplayer commercial module is in active
  $form['flash']['video_flowplayer_module'] = array(
    '#type' => 'checkbox',
    '#title' => t('Use flowplayer module'),
    '#default_value' => variable_get('video_flowplayer_module', FALSE) && module_exists('flowplayer'),
    '#description' => t('You can use flowplayer module. <a href="@link">Download flowplayer module.</a> This is currently recommended for you.', array(
      '@link' => url('http://drupal.org/project/flowplayer'),
    )),
    '#disabled' => module_exists('flowplayer') ? FALSE : TRUE,
  );
  $form['flash']['video_flvplayerloader'] = array(
    '#type' => 'textfield',
    '#title' => t('Filename of Flash loader'),
    '#default_value' => variable_get('video_flvplayerloader', 'FlowPlayer.swf'),
    '#description' => t('The name of the Shockwave file that manages loading the FLV movie. This is relative to the website root. This settings will override if flowplayer module is installed and enabled. Mainly we focus by this settings to add custom flv player support to the video module See includes/common.inc theme_video_play_flash() for further developments.'),
  );
  $form['ogg'] = array(
    '#type' => 'fieldset',
    '#title' => t('Ogg Theora settings'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['ogg']['video_cortado'] = array(
    '#type' => 'textfield',
    '#title' => t('Filename of Cortado Java Applet'),
    '#default_value' => variable_get('video_cortado', $base_url . '/cortado.jar'),
    '#description' => t('The path to the Cortado Applet to play Ogg Theora Files.'),
  );
  return system_settings_form($form);
}

/**
 * Form API callback to validate the upload settings form.
 *
 * Keeps the use from showing the play tab or the play link
 * if they have chosen to display the video in the node body.
 *
 * @param $form_id
 *   The identifier of the form
 *
 * @param $form_values
 *   form values from the settings page
 *
 */
function video_settings_form_validate($form, &$form_state) {

  //print_r($form_state['values']); die;
  if ($form_state['values']['video_flowplayer_module']) {
    if (!module_exists('flowplayer')) {
      form_set_error("video_flowplayer_module", t('You have not installed flowplayer module. <a href="@link">Download and install flowplayer module.</a>', array(
        '@link' => url('http://drupal.org/project/flowplayer'),
      )));
    }
  }

  // if admin set a name for a resolution he also have to set its value
  while ($i <= 4) {
    if ($form_state['values']["video_resolution_{$i}_name"] != '' && $form_state['values']["video_resolution_{$i}_value"] == '') {
      form_set_error("video_resolution_{$i}_value", t('You have to set a value for resolution %res_num if you want to enable it.', array(
        '%res_num' => $i,
      )));
    }
    if ($form_state['values']["video_resolution_{$i}_value"] != '' && !preg_match('/^[0-9]{2,4}x[0-9]{2,4}$/', $form_state['values']["video_resolution_{$i}_value"])) {

      // check valid resolution value
      form_set_error("video_resolution_{$i}_value", t('You have to set valid value for resolution %res_num if you want to enable it. A valid value is 400x300', array(
        '%res_num' => $i,
      )));
    }
    $i++;
  }

  // for future use
}

/******************************************************************************
 * Node Hooks
 ******************************************************************************/

/**
 * Implementation of _node_info().
 *
 * @return
 *   array
 */
function video_node_info() {
  return array(
    'video' => array(
      'name' => t('Video'),
      'module' => 'video',
      'description' => t('Allow a variety of video formats to be posted as nodes in your site'),
    ),
  );
}

/**
 * access hook
 */
function video_access($op, $node, $account) {
  if ($op == 'create') {
    return user_access('create video', $account);
  }
  if ($op == 'update' || $op == 'delete') {
    return user_access('edit own video', $account) && $account->uid == $node->uid || user_access('edit all video nodes', $account);
  }
}

/**
 * Implementation of hook_nodeapi().
 * We use this to append <enclosure> tags to the RSS feeds Drupal generates.
 */
function video_nodeapi($node, $op, $arg) {
  switch ($op) {
    case 'rss item':
      if ($node->type == 'video') {

        // RSS Enclosure http://cyber.law.harvard.edu/rss/rss.html#ltenclosuregtSubelementOfLtitemgt
        $attributes['url'] = _video_get_fileurl($node->vidfile);
        $attributes['length'] = $node->size;
        $mime_type = _video_get_mime_type($node);
        if ($mime_type) {
          $attributes['type'] = $mime_type;
          $enclosure = array(
            'key' => 'enclosure',
            'attributes' => $attributes,
          );
        }

        // MRSS media:content http://search.yahoo.com/mrss
        $media['url'] = $attributes['url'];
        if ($attributes['length'] > 1) {
          $media['fileSize'] = $attributes['length'];
        }
        if ($mime_type) {
          $media['type'] = $mime_type;
        }
        if (isset($node->playtime_seconds) && $node->playtime_seconds > 0) {
          $media['duration'] = $node->playtime_seconds;
        }
        if (isset($node->video_bitrate) && $node->video_bitrate > 0) {
          $media['bitrate'] = $node->video_bitrate;
        }
        if (isset($node->videox) && isset($node->videoy) && $node->videox > 0) {
          $media['width'] = $node->videox;
          $media['height'] = $node->videoy;
        }
        if (isset($node->audio_sampling_rate) && $node->audio_sampling_rate > 0) {
          $media['samplingrate'] = $node->audio_sampling_rate;
        }
        $mrss = array(
          'key' => 'media:content',
          'attributes' => $media,
        );

        // work around for http://drupal.org/node/157709
        static $been_here = FALSE;
        if (!$been_here) {
          $mrss['namespace'] = array(
            'xmlns:media' => 'http://video.search.yahoo.com/mrss',
          );
          $been_here = TRUE;
        }
      }
      return array(
        $enclosure,
        $mrss,
      );
    case 'revision delete':
      db_query('DELETE FROM {video} WHERE vid = %d', $node->vid);
      break;
  }
}

/**
 * Create video submission page. Let the user select the actived video types
 * or display the video form for the selected video type
*/
function video_add() {
  global $user;
  $edit = isset($_POST['edit']) ? $_POST['edit'] : '';

  // If a video type has been specified, validate its existence.
  $vtypes = video_get_types();
  if (arg(3) && in_array(arg(3), $vtypes)) {

    // is a valid video type
    $type = arg(3);

    // Initialize settings:
    module_load_include('inc', 'node', 'node.pages');
    $node = (object) array(
      'uid' => $user->uid,
      'name' => $user->name,
      'type' => 'video',
      'vtype' => $type,
    );
    $output = drupal_get_form('video_node_form', $node);
    drupal_set_title(t('Submit %name video', array(
      '%name' => $type,
    )));
  }
  else {
    if (count($vtypes) == 1) {

      // only one vtype active. redirect the user to the active type form
      // Initialize settings:
      $node = (object) array(
        'uid' => $user->uid,
        'name' => $user->name,
        'type' => 'video',
        'vtype' => $vtypes[0],
      );
      module_load_include('inc', 'node', 'node.pages');
      $output = drupal_get_form('video_node_form', $node);
      drupal_set_title(t('Submit %name video', array(
        '%name' => $vtypes[0],
      )));
    }
    else {
      if ($vtype = variable_get('video_default_video_type', 0)) {

        // Initialize settings:
        $node = (object) array(
          'uid' => $user->uid,
          'name' => $user->name,
          'type' => 'video',
          'vtype' => $vtype,
        );
        module_load_include('inc', 'node', 'node.pages');
        $output = drupal_get_form('video_node_form', $node);
        drupal_set_title(t('Submit %name video', array(
          '%name' => $vtype,
        )));
      }
      else {
        $output = video_types_page();
      }
    }
  }
  return $output;
}

/**
 * Display a video types selection page
*/
function video_types_page() {
  drupal_set_title(t('Submit Video'));

  // we have to set a titl ebecause the node module will not do it for us as we are using a callback video_add()
  $vtypes = video_get_types_infos();
  if (!$vtypes) {

    // no vtype available
    return t('There are no Video types enabled.');
  }
  else {
    $items = array();
    foreach ($vtypes as $vtype => $infos) {
      $out = '<dt>' . l($infos['#name'], "node/add/video/{$vtype}", array(
        'HTML' => TRUE,
        'attributes' => array(
          'title' => 'Add a ' . $infos['#name'],
        ),
      )) . '</dt>';
      $out .= '<dd>' . $infos['#description'] . '</dd>';
      $items[$vtype] = $out;
    }

    // let's order by type name
    ksort($items);
    return t('Choose from the following available video types:') . '<dl>' . implode('', $items) . '</dl>';
  }
}

/**
 *  Return an array containing enabled Video Types
 */
function video_get_types() {
  return array_keys(video_get_types_infos());
}

/**
 *  Return an array containing informations on enabled Video Types
 */
function video_get_types_infos() {
  static $infos = NULL;
  if (!is_array($infos)) {
    $infos = module_invoke_all('v_info');
  }
  return $infos;
}

/**
 * Return the informations for a given video type
*/
function video_get_type_info($type) {
  return module_invoke('video_' . $type, 'v_info');
}

/**
 * Return true if a given video type is downloadable
*/
function video_support_download($node) {
  $info = video_get_type_info($node->vtype);
  return $info[$node->vtype]['#downloadable'];
}

/**
 * Hook, displays the contents of the node form page for creating and editing nodes.
 *
 * @param $node
 *   object
 *
 * @return
 *   string value of form content
 */
function video_form($node) {

  //We must unserialize the array for display in the forms.
  if ($node->serial_data) {
    $node->serial_data = unserialize($node->serialized_data);
  }
  $form = array();

  // default node stuff
  $type = node_get_types('type', $node);
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => check_plain($type->title_label),
    '#size' => 60,
    '#maxlength' => 128,
    '#required' => TRUE,
    '#default_value' => $node->title,
    '#weight' => -20,
  );
  if ($type->has_body) {
    $form['body_filter']['body'] = array(
      '#type' => 'textarea',
      '#title' => check_plain($type->body_label),
      '#required' => $type->min_word_count > 0,
      '#rows' => 10,
      '#default_value' => $node->body,
    );
    $form['body_filter']['format'] = filter_form($node->format);
  }

  // set an hidden field to store video type
  $form['vtype'] = array(
    '#type' => 'hidden',
    '#value' => $node->vtype,
  );

  // kjh: set an hidden field to store encoded fid
  if ($node->serial_data && isset($node->serial_data['video_encoded_fid'])) {
    $form['video_encoded_fid'] = array(
      '#type' => 'hidden',
      '#value' => $node->serial_data['video_encoded_fid'],
    );
  }
  $form['video'] = array(
    '#type' => 'fieldset',
    '#title' => t('Video Information'),
    '#weight' => -19,
  );
  if (!video_support_autoresolution($node)) {

    // this vtype doesn't support autoresolution
    $selected_option = _video_get_resolution_selected_option($node);

    // let's display the resolution selection
    $form['video']['vresolution'] = array(
      '#type' => 'select',
      '#title' => t('Resolution'),
      '#description' => t("Select the approriate resolution (aspect ratio) for your video.<br />If you don't know what to choose then the default value will probably be ok for you."),
      '#options' => _video_get_resolution_options(),
      '#default_value' => $selected_option,
      '#required' => true,
    );

    // manual resolution form logic
    $form['video']['manual_resolution'] = array(
      '#type' => 'fieldset',
      '#title' => t('Manual resolution'),
    );
    $is_manually_set = $selected_option == VIDEO_MANUALLY_SET_VIDEO_RESOLUTION_SELECT_ID;
    $width = $is_manually_set ? $node->videox : NULL;
    $height = $is_manually_set ? $node->videoy : NULL;
    $form['video']['manual_resolution']['manual_resolution_width'] = array(
      '#type' => 'textfield',
      '#title' => t('Width'),
      '#size' => 4,
      '#maxlength' => 4,
      '#default_value' => $width,
      '#description' => t('Video width expressed in pixels.'),
    );
    $form['video']['manual_resolution']['manual_resolution_height'] = array(
      '#type' => 'textfield',
      '#title' => t('Height'),
      '#size' => 4,
      '#maxlength' => 4,
      '#default_value' => $height,
      '#description' => t('Video height expressed in pixels.'),
    );
  }
  else {

    // set an hidden field to store video resolution
    $form['hvresolution'] = array(
      '#type' => 'hidden',
      '#value' => $node->videox . 'x' . $node->videoy,
    );
  }
  if (!video_support_autoplaytime($node)) {

    // this vtype doesn't support autoplaytime
    $form['video']['playtime'] = array(
      '#type' => 'fieldset',
      '#title' => t('Playtime'),
      '#collapsible' => true,
      '#collapsed' => $node->playtime_seconds ? false : true,
      // display expanded if we have values inserted by the user
      '#description' => t('Insert here the duration of the video.<br />Values may be entered in excess of their normal "clock maximum" (the seconds field may be 3600 to represent 1 hour), however each value will be summed for a total of all three.'),
    );
    $playtime = _video_sec2hms($node->playtime_seconds);
    $form['video']['playtime']['playtime_hours'] = array(
      '#type' => 'textfield',
      '#title' => t('Hours'),
      '#size' => 11,
      '#maxlength' => 11,
      '#default_value' => $playtime['hours'],
    );
    $form['video']['playtime']['playtime_minutes'] = array(
      '#type' => 'textfield',
      '#title' => t('Minutes'),
      '#size' => 11,
      '#maxlength' => 11,
      '#default_value' => $playtime['minutes'],
    );
    $form['video']['playtime']['playtime_seconds'] = array(
      '#type' => 'textfield',
      '#title' => t('Seconds'),
      '#required' => FALSE,
      '#size' => 11,
      '#maxlength' => 11,
      '#default_value' => $playtime['seconds'],
    );
  }
  else {

    // set an hidden field to store video length
    $form['playtime_seconds'] = array(
      '#type' => 'hidden',
      '#value' => $node->playtime_seconds,
    );

    // we need to store file size too
    $form['hsize'] = array(
      '#type' => 'hidden',
      '#value' => $node->size,
    );
  }

  // Get the video-type-specific bits.
  $form = module_invoke('video_' . $node->vtype, 'v_form', $node, $form);
  return $form;
}

/**
 * Implementation of hook_validate
 */
function video_validate($node, $form = array()) {
  if (!video_support_autoresolution($node) || $node->vresolution) {

    // we have some resolution value
    // form api checked for good values of vresolution
    if (variable_get("video_{$node->vresolution}_value", '') == '') {
    }
  }
  module_invoke('video_' . $node->vtype, 'v_validate', $node);
}

/**
 * Implementation of hook submit
 */
function video_submit(&$node) {
  if (video_support_autoresolution($node) && $node->new_video_upload_file_fid) {

    // vtype support autoresolution getting
    $xy = module_invoke('video_' . $node->vtype, 'v_auto_resolution', $node);
    if ($xy) {
      $node->videox = $xy[0];
      $node->videoy = $xy[1];
    }
  }
  else {

    // if you have a existing value from hidden field
    if ($node->hvresolution) {
      $res = explode('x', $node->hvresolution);
      $node->videox = $res[0];
      $node->videoy = $res[1];
      $node->size = $node->hsize;
    }
    else {
      if ($node->vresolution < VIDEO_MANUALLY_SET_VIDEO_RESOLUTION_SELECT_ID) {
        $res = explode('x', variable_get('video_resolution_' . $node->vresolution . '_value', ''));
        $node->videox = $res[0];
        $node->videoy = $res[1];
      }
      else {
        if ($node->vresolution == VIDEO_MANUALLY_SET_VIDEO_RESOLUTION_SELECT_ID) {

          // this is a manually set video resolution
          $node->videox = $node->manual_resolution_width;
          $node->videoy = $node->manual_resolution_height;
        }
      }
    }
  }
  if (video_support_autoplaytime($node) && $node->new_video_upload_file_fid) {

    // vtype support auto playtime
    $node->playtime_seconds = module_invoke('video_' . $node->vtype, 'v_auto_playtime', $node);
  }
  else {

    // vtype does not support auto_playtime
    $node->playtime_seconds += $node->playtime_hours * 3600 + $node->playtime_minutes * 60;
  }
}

/**
 * Implementation of hook_insert.
 * Create video record in the video table
 *
 * @return
 *   TRUE on success, FALSE on error
 */
function video_insert($node) {

  // set the required properties of the video node
  //  video_presave($node);
  $node->serialized_data = serialize($node->serial_data);

  //Serialize the data for insertion into the database.
  return db_query("INSERT INTO {video} (vid, nid, vtype, vidfile, size, videox, videoy, video_bitrate, audio_bitrate, audio_sampling_rate, audio_channels, playtime_seconds, disable_multidownload, download_folder, use_play_folder, serialized_data) VALUES (%d, %d, '%s', '%s', %d, %d, %d, %d, %d, %d, '%s', %d, %d, '%s', %d, '%s')", $node->vid, $node->nid, $node->vtype, $node->vidfile, $node->size, $node->videox, $node->videoy, $node->video_bitrate, $node->audio_bitrate, $node->audio_sampling_rate, $node->audio_channels, $node->playtime_seconds, $node->disable_multidownload, $node->download_folder, $node->use_play_folder, $node->serialized_data);
}

/**
 * Hook
 *
 * @return
 *   TRUE on success, FALSE on error
 */
function video_update($node) {
  if ($node->revision) {

    //If a new node revision is being added then insert a new row.
    return video_insert($node);
  }
  else {

    // set the required properties of the video node

    //video_presave($node);

    // GMM: make sure to save the encoded_fid
    if (!isset($node->serial_data['video_encoded_fid']) && $node->video_encoded_fid) {
      $node->serial_data['video_encoded_fid'] = $node->video_encoded_fid;
    }
    $node->serialized_data = serialize($node->serial_data);

    //Serialize the data for insertion into the database.
    return db_query("UPDATE {video} SET vidfile='%s', size=%d, videox=%d, videoy=%d, video_bitrate=%d, audio_bitrate=%d, audio_sampling_rate=%d, audio_channels='%s', playtime_seconds=%d, disable_multidownload=%d, download_folder='%s', use_play_folder=%d, serialized_data='%s' WHERE vid = %d", $node->vidfile, $node->size, $node->videox, $node->videoy, $node->video_bitrate, $node->audio_bitrate, $node->audio_sampling_rate, $node->audio_channels, $node->playtime_seconds, $node->disable_multidownload, $node->download_folder, $node->use_play_folder, $node->serialized_data, $node->vid);
  }
}

/**
 * Implementation of hook_delete
 */
function video_delete($node) {
  db_query("DELETE FROM {video} WHERE nid = %d", $node->nid);
}

/**
 * Implementation of hook_load()
 *
 * @param $node
 *   object or boolean FALSE on error
 */
function video_load($node) {
  if (is_numeric($node->vid)) {
    $node = db_fetch_object(db_query("SELECT * FROM {video} WHERE vid = %d", $node->vid));

    // load serialized data for plug-ins
    $node->serial_data = unserialize($node->serialized_data);
    return $node;
  }
  else {
    return false;
  }
}

/**
 * Implementation of hook_view().
 */
function video_view(&$node, $teaser = FALSE, $page = FALSE) {

  // include the video css file
  drupal_add_css(drupal_get_path('module', 'video') . '/video.css');

  //Run the body through the standard filters.
  $node = node_prepare($node, $teaser);

  //print_r($node);

  //exit;

  // theme the teaser
  $node->teaser = theme('video_teaser', $node, $teaser, $page);

  // if we are viewing the page, run the body through the theme
  if ($page || variable_get('video_in_teaser', FALSE)) {
    $output = '';
    if (user_access('play video')) {
      $node->content['video_player'] = array(
        '#value' => theme('video_player', $node),
        '#weight' => -1,
      );
    }
    else {
      $output .= l(t('login'), "user/login", array(
        'class' => 'outgoing',
        'title' => t('login to your account'),
      ));
      $output .= ' ' . t('or') . ' ';
      $output .= l(t('register'), "user/register", array(
        'class' => 'outgoing',
        'title' => t('create a new account'),
      ));
      $output .= ' ' . t('to play video');
      $node->content['video_player'] = array(
        '#value' => $output,
        '#weight' => -1,
      );
    }
  }

  //  print_r($node);
  //  exit;
  return $node;
}

/********************************************************************
 * Block display functions
 ********************************************************************/

/**
 * Hook block. Does all the interaction with the drupal block system. Uses video_block_list() for DB queries.
 *
 * @param $op
 *   string type of block
 *
 * @param $delta
 *   integer 0 for latest, 1 for played+downloaded, 2 for most played, 3 for most downloaded.
 *
 * @param $edit
 *   array holds the data submitted by the configure forms.
 *
 * @return
 *   array
 */
function video_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0]['info'] = t('Latest videos');
    $blocks[1]['info'] = t('Top videos');
    $blocks[2]['info'] = t('Most played videos');
    $blocks[3]['info'] = t('Most downloaded');
    $blocks[4]['info'] = t('Random video');
    return $blocks;
  }
  else {
    if ($op == 'view') {
      switch ($delta) {
        case 0:
          return array(
            'subject' => variable_get('video_block_title_0', t('Latest videos')),
            'content' => video_block_list($delta),
          );
        case 1:
          return array(
            'subject' => variable_get('video_block_title_1', t('Top videos')),
            'content' => video_block_list($delta),
          );
        case 2:
          return array(
            'subject' => variable_get('video_block_title_2', t('Most played videos')),
            'content' => video_block_list($delta),
          );
        case 3:
          return array(
            'subject' => variable_get('video_block_title_3', t('Most downloaded')),
            'content' => video_block_list($delta),
          );
        case 4:
          return array(
            'subject' => variable_get('video_block_title_4', t('Random video')),
            'content' => video_block_list($delta),
          );
      }
    }
    else {
      if ($op == 'configure') {
        switch ($delta) {

          //Get the default title of the block incase the variable is not set yet.
          case 0:
            $default_title = t('Latest videos');
            break;
          case 1:
            $default_title = t('Top videos');
            break;
          case 2:
            $default_title = t('Most played videos');
            break;
          case 3:
            $default_title = t('Most downloaded');
            break;
          case 4:
            $default_title = t('Random video');
        }
        $form['video_block_title'] = array(
          '#type' => 'textfield',
          '#title' => t('Block display title'),
          '#default_value' => variable_get("video_block_title_{$delta}", $default_title),
        );
        $form['video_block_limit'] = array(
          '#type' => 'select',
          '#title' => t('Number of videos to list in block'),
          '#default_value' => variable_get("video_block_limit_{$delta}", 10),
          '#options' => drupal_map_assoc(array(
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
          )),
        );
        return $form;
      }
      else {
        if ($op == 'save') {
          variable_set("video_block_title_{$delta}", $edit['video_block_title']);
          variable_set("video_block_limit_{$delta}", $edit['video_block_limit']);
        }
      }
    }
  }
}

/**
 * Query DB for block content
 *
 * @param $delta
 *   int 0, 1, 2, or 3. Determines which type of block is being accessed.
 *
 * @return
 *   string HTML content for a block
 */
function video_block_list($delta = 0) {
  $count = variable_get("video_block_limit_{$delta}", 10);
  switch ($delta) {
    case 0:
      $orderby = 'n.created';
      break;
    case 1:
      $orderby = 'v.download_counter + v.play_counter';
      break;
    case 2:
      $orderby = 'v.play_counter';
      break;
    case 3:
      $orderby = 'v.download_counter';
      break;
    case 4:
      $count = 1;
      $orderby = 'RAND()';
      break;
  }
  return node_title_list(db_query_range(db_rewrite_sql("SELECT n.nid, n.title, {$orderby} FROM {node} n INNER JOIN {video} v ON n.vid = v.vid WHERE n.type = 'video' AND n.status = 1 AND n.moderate = 0 ORDER BY {$orderby} DESC"), 0, $count));
}

/****************************************************
 * Menu callback functions
 ****************************************************/

/**
 * Redirects to download the video file.
 */
function video_download($nodeid) {

  // $node as been loaded by video_menu

  //print_r($node);

  //exit;
  if ($node = node_load($nodeid) and $node->type == 'video') {
    if (node_access('view', $node, $user->uid)) {
      if (video_support_download($node) && _video_allow_download($node)) {

        //Make sure the video type is not youtube before downloading.
        _video_download_goto($node);
      }
      else {

        //If video is type youtube then it can't be downloaded.
        drupal_set_message(t('There are no files to download for this video.'), 'error');
        print theme('page', '');
      }
    }
    else {
      drupal_not_found();
    }
  }
}

/**
 * Return true if the video is downloadable, false otherwise
*/
function _video_allow_download($node) {

  // TODO: now videos are downloadable by default. why not implementing a feature to let users choose if they want their videos to be downloadable?
  return true;
}

/**
 * Theme the teaser
 *
 * This is just in place for site admins and theme developers
 * who need to adjust how the teaser is themed.
 *
 * @param $node
 *   The node to be displayed.
 * @param $teaser
 *   Whether we are to generate a "teaser" or summary of the node, rather than display the whole thing.
 * @param $page
 *   Whether the node is being displayed as a standalone page. If this is TRUE, the node title should not be displayed, as it will be printed automatically by the theme system. Also, the module may choose to alter the default breadcrumb trail in this case.
 *
 * @return
 *   html
 */
function theme_video_teaser($node, $teaser = FALSE, $page = FALSE) {
  return $node->teaser;
}

/**
 * theme the view of the page to include the video
 * assumes that body was put through prepare in hook_view
 *
 * @param $node
 *   The node to be displayed.
 * @param $teaser
 *   Whether we are to generate a "teaser" or summary of the node, rather than display the whole thing.
 * @param $page
 *   Whether the node is being displayed as a standalone page. If this is TRUE, the node title should not be displayed, as it will be printed automatically by the theme system. Also, the module may choose to alter the default breadcrumb trail in this case.
 *
 * @return
 *   html
 */
function theme_video_view($node, $teaser = FALSE, $page = FALSE) {
  return '<div id="video_body">' . $node->body . '</div>';
}

/**
* theme function to control which player is presented
*
* @param $node
*   node object
*
* @return
*   html
*/
function theme_video_player($node) {

  // include video.js file for Internet Explorer fixes

  //theme('video_get_script');
  drupal_add_js(drupal_get_path('module', 'video') . '/video.js');
  if (variable_get('video_playcounter', 1)) {
    db_query("UPDATE {video} SET play_counter = play_counter + 1 where vid = %d", $node->vid);

    //Increment play counter.
  }
  _video_scale_video($node);
  $output = module_invoke('video_' . $node->vtype, 'v_play', $node);
  return $output;
}

/**
 * Cut down on redundant link text
 *
 * @param $url
 *   string URL to link to
 *
 * @param $title
 *   string title of link to show on mouseover
 *
 * @param $link_text
 *   string text of the link
 *
 * @return
 *   string HTML link
 */
function theme_video_format_play($output, $url, $title, $link_text) {
  $output = "\n<div id=\"video-player\">\n" . $output;
  if (variable_get('video_show_help_text', TRUE)) {
    $output .= "<p>\n" . t('Problems viewing videos?');
    $output .= "<br />\n";
    $output .= l($link_text, $url, array(
      'attributes' => array(
        'title' => $title,
      ),
      'absolute' => TRUE,
    ));
    $output .= "\n</p> \n ";
  }
  return $output . "</div>\n";
}

/**
 * Takes an associative array of $fields with 'title' and 'body' keys and outputs the HTML.
 * This theme function allows the same HTML code to generate all the custom and metadata fields.
 *
 * @param $fields
 *   array with 'title' and 'body' keys
 *
 * @return
 *   string of content to display
 */
function theme_video_fields($fields) {
  $output = '';
  $odd_even = 'odd';
  foreach ($fields as $field) {
    $output .= "<div class=\"{$odd_even}\"><b>" . check_plain($field['title']) . '</b> ' . check_plain($field['body']) . "</div>\n";
    $odd_even = $odd_even == 'odd' ? 'even' : 'odd';

    //Always switch its value.
  }
  return $output;
}

/**
 * Import the video.js script
 */
function theme_video_get_scripvt() {
  drupal_add_js(drupal_get_path('module', 'video') . '/video.js');
}

/******************************************************************************
 * End theme functions
 ******************************************************************************
 * Start private functions created for this module.
 ******************************************************************************/

/**
 * Pull the file extension from a filename
 *
 * @param $vidfile
 *   string filename to get the filetype from.
 *
 * @return
 *   string value of file type or boolean FALSE on error
 */
function _video_get_filetype($vidfile) {

  //If the filename doesn't contain a ".", "/", or "\" and is exactly 11 characters then consider it a youtube video ID.
  if (!strpos($vidfile, '.') and !strpos($vidfile, '/') and !strpos($vidfile, '\\') and strlen($vidfile) == 11) {
    $file_type = 'youtube';
  }
  else {
    if (strpos($vidfile, 'google:') === 0) {
      $file_type = 'googlevideo';
    }
    else {
      if (strstr($vidfile, '.')) {

        //If file contains a "." then get the file extension after the "."
        $file_type = end(explode('.', $vidfile));
      }
      else {
        $file_type = FALSE;
      }
    }
  }
  return strtolower($file_type);
}

/**
 * Forward user directly to the file for downloading
 *
 */
function _video_download_goto($node) {
  if (user_access('download video')) {
    if (variable_get('video_downloadcounter', 1)) {
      db_query("UPDATE {video} SET download_counter = download_counter + 1 where vid = %d", $node->vid);

      //Increment download counter.
    }

    // let the submodule handle the real download logic
    module_invoke('video_' . $node->vtype, 'v_download', $node);
  }
  else {

    //If the user does not have access to download videos.
    drupal_set_message(t('You do not have permission to download videos.'), 'error');
    drupal_goto("node/" . $node->nid);

    //Use the nid we just loaded to go back to the node page.
  }
}

/**
 * Convert filesize to bytes
 *
 * @return
 *   integer bytes
 */
function _video_size2bytes($node) {
  if (!empty($node->size)) {
    switch ($node->size_format) {
      case 'Kb':

        // KiloBits
        return intval($node->size * 128);
        break;
      case 'KB':

        // KiloBytes
        return intval($node->size * 1024);
        break;
      case 'Mb':

        // MegaBits
        return intval($node->size * 131072);
        break;
      case 'MB':

        // MegaBytes
        return intval($node->size * 1048576);
        break;
      case 'Gb':

        // GigaBits
        return intval($node->size * 134217728);
        break;
      case 'GB':

        // GigaBytes
        return intval($node->size * 1073741824);
        break;
      default:
        return (int) $node->size;
        break;
    }
  }
  else {
    return 0;
  }
}

/**
 * Convert seconds to hours, minutes, and seconds.
 * Derived from h:m:s example by Jon Haworth
 *
 * @link
 *   http://www.laughing-buddha.net/jon/php/sec2hms/
 *
 * @param $sec
 *   integer value of seconds.
 *
 * @return
 *   array associative with key values of hours, minutes, and seconds.
 */
function _video_sec2hms($sec = 0) {
  $hms = array();

  // 3600 seconds in an hour and trash remainder
  $hms['hours'] = intval(intval($sec) / 3600);

  // dividing the total seconds by 60 will give us
  // the number of minutes, but we're interested in
  // minutes past the hour: to get that, we need to
  // divide by 60 again and keep the remainder
  $hms['minutes'] = intval($sec / 60 % 60);
  $hms['seconds'] = intval($sec % 60);

  //keep the remainder.
  return $hms;
}

/**
 * Returns an absolute url which references
 * to the video file
 *
 * @param $video_file
 *   string containing absolute or relative URL to video.
 *
 * @return
 *   string containing absolute URL path to video file.
 */
function _video_get_fileurl($video_file) {
  global $base_url;

  //creation of absolute url
  if (preg_match("/^(http|ftp|mm|rstp)(s?):\\/\\//", $video_file)) {

    //If path is absolute
    return check_plain($video_file);
  }
  else {

    // path is relative to drupal install
    return check_plain($base_url . '/' . $video_file);
  }
}

/**
 * Returns the correct mime-type for the video. Returns false if the
 * mime-type cannot be detected.
 */
function _video_get_mime_type($node) {
  switch (_video_get_filetype($node->vidfile)) {
    case 'mov':
      return 'video/quicktime';
    case 'avi':

      // Added
      return 'video/x-msvideo';
    case 'mpg':

    // Added
    case 'mpeg':

      // Added
      return 'video/mpeg';

    // Added
    case 'divx':
      return 'video/vnd.divx';
    case 'rm':
      return 'application/vnd.rn-realmedia';
    case 'flv':
      return 'flv-application/octet-stream';
    case 'asf':
      return 'video/x-ms-asf';
    case 'wmv':
      return 'video/x-ms-wmv';
    case '3gp':
      return 'video/3gpp';
    case 'mp4':
      return 'video/mp4';
    case 'dir':
    case 'dcr':
      return 'application/x-director';

    // We can't support this sources properly, so return false.
    case 'youtube':
    case 'googlevideo':
      return false;
    case 'ogg':
      return 'application/ogg';
    default:

      // We couldn't detect the mime-type, so return false.
      return false;
  }
}

/**
 * Generates the HTML for any object parameters in an embedded video.
 *
 * @param $node the node which is being played
 *
 * @return
 *   string with the parameters in HTML form.
 */
function _video_get_parameters(&$node) {

  // call hook_v_get_params
  $param_value = module_invoke_all('v_get_params', $node);
  $output = '';
  foreach ($param_value as $param => $value) {
    $output .= '<param name="' . check_plain($param) . '" value="' . check_plain($value) . '" />\\n';
  }
  return $output;
}

/**
 * Return true if the video support auto resolution
*/
function video_support_autoresolution($node) {
  $info = video_get_type_info($node->vtype);
  $has_hook = module_hook('video_' . $node->vtype, 'v_auto_resolution');
  return $has_hook && isset($info[$node->vtype]['#autoresolution']) && $info[$node->vtype]['#autoresolution'];
}

/**
 * Return true if the video support auto playtime
*/
function video_support_autoplaytime($node) {
  $info = video_get_type_info($node->vtype);
  $has_hook = module_hook('video_' . $node->vtype, 'v_auto_playtime');
  return $has_hook && isset($info[$node->vtype]['#autoplaytime']) && $info[$node->vtype]['#autoplaytime'];
}

/**
 * Get the resolution options array to use on the video form
*/
function _video_get_resolution_options() {
  $options = array();
  $i = 1;
  while ($i <= 4) {
    if (variable_get('video_resolution_' . $i . '_value', '') != '') {

      // only if we have a value
      $options[$i] = variable_get('video_resolution_' . $i . '_name', '');
    }
    $i++;
  }
  if (user_access('manually set video resolution')) {

    // to manually insert resolution values
    $options[VIDEO_MANUALLY_SET_VIDEO_RESOLUTION_SELECT_ID] = t("manually set ");
  }
  return $options;
}

/**
 * Get the selected resolution id from the videox and videoy fields
*/
function _video_get_resolution_selected_option($node) {
  if (!isset($node->nid)) {

    // do not assign a default value if we are creating a new node
    return NULL;
  }
  $value = $node->videox . "x" . $node->videoy;
  $i = 1;
  while ($i <= 4) {
    if (variable_get('video_resolution_' . $i . '_value', '') == $value) {
      return $i;
    }
    $i++;
  }

  // we did not find the value in the presets fields
  // let's consider it as a manually set resolution (if the user have permissions)
  if (user_access('manually set video resolution')) {
    return VIDEO_MANUALLY_SET_VIDEO_RESOLUTION_SELECT_ID;
  }
}

/**
 * Scale a video to match the desired width
*/
function _video_scale_video(&$node) {
  $def_width = (int) variable_get("video_resolution_width", 400);
  if ($def_width <= 0) {

    // video scaling has been disabled
    if (!$node->videox || !$node->videoy) {

      // we shouldn't have videox or videoy null.. but this is just in case for safety
      $node->video_scaled_x = 400;
      $node->video_scaled_y = 300;
    }
    else {
      $node->video_scaled_x = $node->videox;
      $node->video_scaled_y = $node->videoy;
    }
    return;
  }
  if (!$node->videox || !$node->videoy) {

    // we shouldn't have videox or videoy null.. but this is just in case for safety
    $height = $def_width * 3 / 4;
  }
  else {
    $height = $def_width * ($node->videoy / $node->videox);

    // do you remember proportions?? :-)
  }
  $height = round($height);

  // add one if odd
  if ($height % 2) {
    $height++;
  }
  $node->video_scaled_x = $def_width;
  $node->video_scaled_y = $height;
}

/**
 * Implementation of hook_theme().
 */
function video_theme() {
  return array(
    'video_page' => array(
      'arguments' => array(),
    ),
    'video_fields' => array(
      'arguments' => array(
        'fields' => NULL,
      ),
    ),
    'video_format_play' => array(
      'arguments' => array(
        'output' => NULL,
        'url' => NULL,
        'title' => NULL,
        'link_text' => NULL,
      ),
    ),
    'video_get_scripvt' => array(
      'arguments' => array(),
    ),
    'video_player' => array(
      'arguments' => array(
        'node' => NULL,
      ),
    ),
    'video_teaser' => array(
      'arguments' => array(
        'node' => NULL,
        'teaser' => NULL,
        'page' => NULL,
      ),
    ),
    'video_view' => array(
      'arguments' => array(
        'node' => NULL,
        'teaser' => NULL,
        'page' => NULL,
      ),
    ),
  );
}

Functions

Namesort descending Description
theme_video_fields Takes an associative array of $fields with 'title' and 'body' keys and outputs the HTML. This theme function allows the same HTML code to generate all the custom and metadata fields.
theme_video_format_play Cut down on redundant link text
theme_video_get_scripvt Import the video.js script
theme_video_page Displays a Drupal page containing recently added videos
theme_video_player theme function to control which player is presented
theme_video_teaser Theme the teaser
theme_video_view theme the view of the page to include the video assumes that body was put through prepare in hook_view
video_access access hook
video_add Create video submission page. Let the user select the actived video types or display the video form for the selected video type
video_block Hook block. Does all the interaction with the drupal block system. Uses video_block_list() for DB queries.
video_block_list Query DB for block content
video_delete Implementation of hook_delete
video_download Redirects to download the video file.
video_download_access
video_feed Generate an RSS feed for videos
video_form Hook, displays the contents of the node form page for creating and editing nodes.
video_get_types Return an array containing enabled Video Types
video_get_types_infos Return an array containing informations on enabled Video Types
video_get_type_info Return the informations for a given video type
video_help Help hook Implementation of hook_help
video_insert Implementation of hook_insert. Create video record in the video table
video_link Internal Drupal links hook
video_load Implementation of hook_load()
video_menu Implementation of hook_menu().
video_nodeapi Implementation of hook_nodeapi(). We use this to append <enclosure> tags to the RSS feeds Drupal generates.
video_node_info Implementation of _node_info().
video_page Displays a Drupal page containing recently added videos
video_perm Permissions hook
video_settings_form Settings Hook
video_settings_form_validate Form API callback to validate the upload settings form.
video_submit Implementation of hook submit
video_support_autoplaytime Return true if the video support auto playtime
video_support_autoresolution Return true if the video support auto resolution
video_support_download Return true if a given video type is downloadable
video_theme Implementation of hook_theme().
video_types_page Display a video types selection page
video_update Hook
video_validate Implementation of hook_validate
video_view Implementation of hook_view().
video_views_api GMM: Views 2 Implementation of hook_views_api()
video_views_handlers Implementation of hook_views_handlers()
_video_allow_download Return true if the video is downloadable, false otherwise
_video_download_goto Forward user directly to the file for downloading
_video_get_filetype Pull the file extension from a filename
_video_get_fileurl Returns an absolute url which references to the video file
_video_get_mime_type Returns the correct mime-type for the video. Returns false if the mime-type cannot be detected.
_video_get_parameters Generates the HTML for any object parameters in an embedded video.
_video_get_resolution_options Get the resolution options array to use on the video form
_video_get_resolution_selected_option Get the selected resolution id from the videox and videoy fields
_video_scale_video Scale a video to match the desired width
_video_sec2hms Convert seconds to hours, minutes, and seconds. Derived from h:m:s example by Jon Haworth
_video_size2bytes Convert filesize to bytes

Constants