* * @todo */ /** * Let's include views logic if views module is enabled */ if (module_exists('views')) { module_load_include('inc', 'video', 'views_video'); } /******************************************************************** * 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 = '

'. t('The Video Module is used to create and administrator Video nodes for Drupal') .'

'; 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, ); if (arg(0) == 'node' && is_numeric(arg(1))) { if ($node = node_load(arg(1)) and $node->type == 'video') { //enable the download tab only if it is supported if (video_support_download($node)) { $menu_type = (variable_get('video_displaydownloadmenutab', 1)) ? MENU_LOCAL_TASK : MENU_CALLBACK; $items['node/'.$node->nid.'/download'] = array( 'title' => 'Download', 'page callback' => 'video_download', 'page arguments' => array($node), 'access arguments' => array('access video') && node_access('view', $node, $user->uid), 'weight' => 5, 'type' => $menu_type); } } } return $items; } /** * 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 .= '
' . 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'); 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, ); } $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_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') ); $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.') ); $form['flash'] = array( '#type' => 'fieldset', '#title' => t('Flash settings'), '#collapsible' => TRUE, '#collapsed' => 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.') ); $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 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 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://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 = '
'. l($infos['#name'], "node/add/video/$vtype", array('HTML'=>TRUE, 'attributes' => array('title' => 'Add a '. $infos['#name']))) .'
'; $out .= '
'. $infos['#description'] .'
'; $items[$vtype] = $out; } // let's order by type name ksort($items); return t('Choose from the following available video types:') .'
'. implode('', $items) .'
'; } } /** * 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 // 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.
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' => _video_get_resolution_selected_option($node), '#required' => true, ); } 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.
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_presave(&$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; } // we should have a good value (checked by Form API) else { $res = explode('x', variable_get('video_resolution_' . $node->vresolution . '_value', '')); $node->videox = $res[0]; $node->videoy = $res[1]; } } 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) { $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); } } 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($node) { // $node as been loaded by video_menu print_r($node); exit; if ($node) { 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 '
'. $node->body .'
'; } /** * 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
\n" . $output; $output .= "

\n". t('Problems viewing videos?'); $output .= "
\n"; $output .= l($link_text, $url, array('attributes' => array('title' => $title), 'absolute' => TRUE)); return $output ."\n

\n
\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 .= "
" . check_plain($field['title']) . ' ' . check_plain($field['body']) . "
\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 .= '\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++; } return $options; } /** * Get the selected resolution id from the videox and videoy fields */ function _video_get_resolution_selected_option($node) { $value = $node->videox . "x" . $node->videoy; $i = 1; while($i <= 4) { if(variable_get('video_resolution_'.$i.'_value', '') == $value) { return $i; } $i++; } } /** * Scale a video to match the desired width */ function _video_scale_video(&$node) { $def_width = (int) variable_get("video_resolution_width", 400); if (!$node->videox || !$node->videoy) { $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), ), ); }