PluginProbe
FV Player 8 / 8.1
FV Player 8 v8.1
trunk 8.0.18 8.0.19 8.0.20 8.0.21 8.0.25 8.0.27 8.1 8.1.3
fv-player / models / youtube.php

youtube.php in FV Player 8 8.1, at models/youtube.php

603 lines 21.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 class FV_Player_YouTube {
8
9 static $instance = null;
10
11 var $bYoutube = false;
12
13 var $fTimeSpent_AutoSplash = 0;
14
15 public static function _get_instance() {
16 if( !self::$instance ) {
17 self::$instance = new self();
18 }
19
20 return self::$instance;
21 }
22
23 function __construct() {
24
25 if( !is_admin() ) {
26 // Load splash via API if not provided
27 add_filter( 'fv_flowplayer_splash', array( $this, 'get__cached_splash' ), 10, 2 );
28 add_filter( 'fv_flowplayer_playlist_splash', array( $this, 'get__cached_splash' ), 10, 2 );
29 }
30
31 // Fallback YouTube splash screen if no API key provided
32 add_filter( 'fv_flowplayer_splash', array( $this, 'youtube_splash' ), 10, 2 );
33 add_filter( 'fv_flowplayer_playlist_splash', array( $this, 'youtube_splash' ), 10, 2 );
34
35 add_action( 'init', array( $this, 'disable_pro_plugin_hooks' ) );
36
37 add_action( 'admin_init', array( $this, 'admin__add_meta_boxes' ) );
38
39 //add_action( 'amp_post_template_footer', array( $this, 'amp_post_template_footer' ), 9 );
40
41 add_filter( 'fv_flowplayer_attributes', array( $this, 'player_attributes' ), 10, 3 );
42
43 add_filter( 'fv_player_item', array($this, 'player_item'), 10, 3 );
44
45 add_filter( 'fv_flowplayer_checker_time', array( $this, 'youtube_duration' ), 10, 2 );
46
47 add_filter( 'fv_flowplayer_args', array( $this, 'disable_titles_youtube') );
48
49 add_filter( 'fv_flowplayer_get_mime_type', array( $this, 'set_file_type'), 10, 2 );
50
51 add_action( 'fv_player_extensions_admin_load_assets', array( $this, 'admin_load_assets' ) );
52
53 add_filter( 'fv_flowplayer_conf', array($this, 'fv_flowplayer_conf'), 10, 2);
54
55 add_filter( 'fv_player_meta_data', array($this, 'fetch_yt_data'), 10, 3);
56
57 //add_action( 'wp_footer', array( $this, 'scripts' ), 0 );
58
59 }
60
61 function admin__add_meta_boxes() {
62 add_meta_box( 'fv_player_youtube', __('YouTube', 'fv-player-pro'), array( $this, 'fv_player_admin_youtube' ), 'fv_flowplayer_settings_hosting', 'normal' );
63 }
64
65 /*
66 * Triggered when loading the FV Player editor, we will need the
67 * editor scripts and the player scripts as well - for preview.
68 */
69 function admin_load_assets() {
70 global $fv_wp_flowplayer_ver;
71 wp_enqueue_script('fvplayer-shortcode-editor-youtube', plugins_url('js/shortcode-editor-youtube.js', dirname(__FILE__) ),array('jquery','fvwpflowplayer-shortcode-editor'), $fv_wp_flowplayer_ver );
72
73 //$this->scripts();
74 }
75
76 function amp_post_template_footer() {
77 $this->scripts();
78 }
79
80 function disable_pro_plugin_hooks() {
81 if ( function_exists( 'FV_Player_Pro' ) ) {
82 remove_filter( 'fv_flowplayer_splash', array( FV_Player_Pro(), 'youtube_splash' ), 10, 2 );
83 remove_filter( 'fv_flowplayer_playlist_splash', array( FV_Player_Pro(), 'youtube_splash' ), 10, 2 );
84 }
85 }
86
87 function disable_titles_youtube( $aArgs ) {
88 global $fv_fp;
89
90 // we don't want to avoid caption if it's set in lightbox anchor
91 if( isset($aArgs['lightbox']) && $aArgs['lightbox'] ) {
92 $aLightbox = preg_split('~[;]~', $aArgs['lightbox']);
93
94 $bUseAnchor = false;
95 foreach ($aLightbox AS $k => $i) {
96 if ($i == 'text') {
97 unset($aLightbox[$k]);
98 $bUseAnchor = true;
99 }
100 }
101
102 if( $bUseAnchor ) {
103 return $aArgs;
104 }
105 }
106
107 if( isset($aArgs['src']) && $this->is_youtube($aArgs['src']) && $fv_fp->_get_option( array('pro','youtube_titles_disable') )) {
108 $aArgs['caption'] = '';
109 }
110 return $aArgs;
111 }
112
113 function fetch_yt_data($video, $post_id = false, $videoObj = false ) {
114 global $fv_fp;
115
116 // must be url string
117 if( !is_string($video) ) {
118 return $video;
119 }
120
121 if ( $this->is_youtube($video) && $fv_fp->_get_option( array('pro','youtube_key') )) {
122
123 $fv_flowplayer_meta = false;
124 if( $post_id ) {
125 $fv_flowplayer_meta = get_post_meta($post_id, flowplayer::get_video_key($video), true);
126 if( !$fv_flowplayer_meta || !isset($fv_flowplayer_meta['date']) || ( $fv_flowplayer_meta['date'] + 24 * 3600 ) < time() || !$fv_flowplayer_meta['duration'] && ( $fv_flowplayer_meta['date'] + 60 ) < time() ) {
127 $fv_flowplayer_meta = false;
128 }
129 }
130
131 if( !$fv_flowplayer_meta ) {
132 $tStart = microtime(true);
133 $aId = $this->is_youtube($video);
134
135 $api_url = add_query_arg( array(
136 'part' => 'snippet,contentDetails,player',
137 'id' => $aId[1],
138 'key' => $fv_fp->_get_option( array('pro','youtube_key') ),
139 'maxWidth' => 1920 // This is a trick to get player->embedWidth and embedHeight to be able to tell the aspect ratio of the video
140 ), 'https://www.googleapis.com/youtube/v3/videos' );
141
142 $response = wp_remote_get( $api_url, array( 'sslverify' => false ) );
143
144 $obj = is_wp_error($response) ? false : @json_decode( wp_remote_retrieve_body($response) );
145
146 if( isset($obj->error) && !empty($obj->error->message) ) {
147 update_option('fv_player_pro_youtube_error', gmdate('r').": ".$obj->error->message, false );
148 }
149
150 if( $obj && !empty($obj->items[0]) ) {
151 $obj_item = $obj->items[0];
152
153 $fv_flowplayer_meta = array();
154 if ( !empty($obj_item->contentDetails->duration) ) {
155 $duration = $obj_item->contentDetails->duration;
156
157 if (class_exists('DateInterval')) {
158 $interval = new DateInterval($duration);
159 $fv_flowplayer_meta['duration'] = date_create('@0')->add($interval)->getTimestamp();
160 } else {
161 $fv_flowplayer_meta['duration'] = flowplayer::hms_to_seconds($duration);
162 }
163 }
164
165 $fv_flowplayer_meta['aspect_ratio'] = 0;
166 if( !empty($obj_item->player->embedWidth) && !empty($obj_item->player->embedHeight) ) {
167 $fv_flowplayer_meta['aspect_ratio'] = $obj_item->player->embedHeight/$obj_item->player->embedWidth;
168 }
169
170 $fv_flowplayer_meta['is_live'] = false;
171 if( !empty($obj_item->snippet->liveBroadcastContent) ) {
172 if( $obj_item->snippet->liveBroadcastContent == 'live' ) {
173 $fv_flowplayer_meta['is_live'] = true;
174 }
175 }
176
177 // YouTube splash screens come in various sizes and often with black borders. So we use the maxres image to determine image aspect ratio and then look for matching image
178 if( !empty($obj_item->snippet->thumbnails) ) {
179 $thumbs = $obj_item->snippet->thumbnails;
180 $ratio = isset($thumbs->maxres) && intval($thumbs->maxres->width) > 0 && intval($thumbs->maxres->height) > 0 ? $thumbs->maxres->height/$thumbs->maxres->width : false;
181 foreach( (array)$thumbs AS $k => $v ) {
182 if( !$ratio || $v->height/$v->width == $ratio ) {
183 $fv_flowplayer_meta['splash'] = $v->url;
184 if( $v->width > 600 ) break;
185 }
186 }
187 }
188
189 $fv_flowplayer_meta['caption'] = !empty($obj_item->snippet->title) ? $obj_item->snippet->title : false;
190
191 $fv_flowplayer_meta['author_thumbnail'] = false;
192 $fv_flowplayer_meta['author_name'] = false;
193 $fv_flowplayer_meta['author_url'] = false;
194
195 // get channel id
196 $channel_id = !empty($obj_item->snippet->channelId) ? $obj_item->snippet->channelId : false;
197
198 $youtube_channel_obj = false;
199
200 if( $channel_id ) {
201 $api_url = add_query_arg( array(
202 'part' => 'snippet',
203 'id' => $channel_id,
204 'key' => $fv_fp->_get_option( array('pro','youtube_key') ),
205 ), 'https://www.googleapis.com/youtube/v3/channels' );
206
207
208 $response = wp_remote_get( $api_url, array( 'sslverify' => false ) );
209
210 $youtube_channel_obj = is_wp_error($response) ? false : @json_decode( wp_remote_retrieve_body($response) );
211 }
212
213 if ( $youtube_channel_obj && ! empty( $youtube_channel_obj->items[0]->snippet ) ) {
214 $snippet = $youtube_channel_obj->items[0]->snippet;
215
216 // get 'default' thumbnail
217 $author_thumbnail_url = ! empty( $snippet->thumbnails->default->url) ? $snippet->thumbnails->default->url : false;
218
219 // get channel name
220 $author_name = ! empty( $snippet->title) ? $snippet->title : false;
221 $fv_flowplayer_meta['author_name'] = $author_name;
222
223 // get channel url
224 $author_url = ! empty( $snippet->customUrl) ? 'https://www.youtube.com/' . $snippet->customUrl : false;
225 $fv_flowplayer_meta['author_url'] = $author_url;
226
227 if( $author_thumbnail_url && $author_name ) { // download channel thumbnail to media library
228 global $FV_Player_Splash_Download, $wpdb;
229
230 // check if author name is already in media library and use its post id as attachment id
231 $youtube_channel_attachment_cache = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_fv_player_youtube_channel_id' AND meta_value = %s", $channel_id ) );
232
233 if( !empty($youtube_channel_attachment_cache) ) {
234 $fv_flowplayer_meta['author_thumbnail'] = $youtube_channel_attachment_cache;
235 } else {
236 add_filter( 'upload_dir', array( $this, 'custom_upload_path' ) );
237 $author_thumbnail_attachment_data = $FV_Player_Splash_Download->download_splash( $author_thumbnail_url, $author_name );
238 remove_filter( 'upload_dir', array( $this, 'custom_upload_path' ) );
239
240 if( !empty($author_thumbnail_attachment_data) ) {
241 $author_thumbnail_attachment_id = $author_thumbnail_attachment_data['attachment_id'];
242 $fv_flowplayer_meta['author_thumbnail'] = $author_thumbnail_attachment_id; // store attachment id in video meta
243
244 update_post_meta( $author_thumbnail_attachment_id, '_fv_player_youtube_channel_id', $channel_id ); // store splash url in attachment meta
245 }
246 }
247 }
248 }
249
250 }
251
252 $fv_flowplayer_meta['check_time'] = microtime(true) - $tStart;
253
254 if ($post_id) {
255 update_post_meta($post_id, flowplayer::get_video_key($video), $fv_flowplayer_meta);
256 }
257 }
258
259 $videoData = false;
260 if( !empty($fv_flowplayer_meta['splash']) && !empty($fv_flowplayer_meta['caption']) ) {
261 $videoData = array(
262 'name' => htmlspecialchars( str_replace( array(';','[',']'), array('\;','(',')'), $fv_flowplayer_meta['caption']) ),
263 'thumbnail' => $fv_flowplayer_meta['splash'],
264 'duration' => $fv_flowplayer_meta['duration'],
265 'aspect_ratio' => $fv_flowplayer_meta['aspect_ratio'],
266 'is_live' => $fv_flowplayer_meta['is_live'],
267 'author_thumbnail' => $fv_flowplayer_meta['author_thumbnail'],
268 'author_name' => $fv_flowplayer_meta['author_name'],
269 'author_url' => $fv_flowplayer_meta['author_url'],
270 // Note: No way of getting the actual video size unless you own the video and can use part=fileDetails
271 );
272
273 $videoData = apply_filters( 'fv_player_meta_data_youtube', $videoData, $video, $obj, $videoObj, $fv_flowplayer_meta );
274 }
275
276 if( isset($obj->items[0]->snippet->liveBroadcastContent) && $obj->items[0]->snippet->liveBroadcastContent == 'live' ) {
277 $videoData['is_live'] = true;
278 }
279
280 return $videoData;
281 } else {
282 return $video; // no vimeo or yt, pass to another filter
283 }
284 }
285
286 function fv_flowplayer_conf( $conf ) {
287 global $fv_fp;
288
289 if( $this->bYoutube || $fv_fp->should_force_load_js() || did_action('fv_player_extensions_admin_load_assets') ) {
290 $conf['youtube'] = true;
291
292 if( $fv_fp->_get_option( array('pro','youtube_cookies') ) ) {
293 $conf['youtube_cookies'] = true;
294 }
295 }
296 return $conf;
297 }
298
299 function fv_player_admin_youtube() {
300 global $fv_fp;
301
302 $value = $fv_fp->_get_option('youtube_browser_chrome', 'standard');
303 ?>
304 <style>
305 #fv_player_youtube .descriptions {
306 float: right;
307 position: relative;
308 width: 50%;
309 }
310
311 #fv_player_youtube [data-describe] {
312 display: none;
313 position: absolute;
314 top: 0;
315 }
316 </style>
317 <table class="form-table2" style="margin: 5px; ">
318 <tr>
319 <td class="first"><label>YouTube UI:</label></td>
320 <td>
321 <?php
322 $radio_butons = array();
323 $radio_butons_descriptions = array();
324
325 foreach( array(
326 'standard' => array(
327 'label' => __( 'Standard', 'fv-player' ),
328 'description' => __( 'All of the YouTube embedded player interface will show, including related videos on pause.', 'fv-player' )
329 ),
330 'reduced' => array(
331 'label' => __( 'Reduced', 'fv-player' ),
332 'description' => __( 'Show only the video title and the YouTube logo.', 'fv-player' )
333 ),
334 'none' => array(
335 'label' => __( 'None', 'fv-player' ),
336 'description' => __( 'Remove everything.', 'fv-player' )
337 )
338 ) AS $key => $field ) {
339 $id = 'youtube_browser_chrome_'.esc_attr($key);
340
341 $radio_button = '<input id="'.$id.'" type="radio" name="youtube_browser_chrome" value="'.esc_attr($key).'"';
342 if( $value === $key || wp_json_encode($value) == $key ) { // use wp_json_encode as value can be boolean
343 $radio_button .= ' checked="checked"';
344 }
345 $radio_button .= '</input>';
346 $radio_button .= '<label for="'.$id.'">'.$field['label'].'</label><br />';
347
348 $radio_butons[] = $radio_button;
349
350 if( !empty($field['description']) ) {
351 $radio_butons_descriptions[$key] = $field['description'];
352 }
353 }
354
355 echo '<div class="descriptions">';
356 foreach( $radio_butons_descriptions AS $key => $description ) {
357 echo '<p class="description" data-describe="' . esc_attr( $key ) . '">' . esc_html( $description ).'</p>';
358 }
359 echo '</div>';
360
361 echo implode( $radio_butons );
362 ?>
363 </td>
364 </tr>
365 <?php if( $fv_fp->_get_option( array('pro','youtube_titles_disable') ) ) $fv_fp->_get_checkbox(__('Disable video captions', 'fv-player-pro'), array('pro', 'youtube_titles_disable'), __('Normally the video title is parsed into the shortcode when saving the post, with this setting it won\'t appear.', 'fv-player-pro') ); ?>
366 <?php $fv_fp->_get_checkbox(__("Use YouTube Cookies", 'fv-player-pro'), array('pro', 'youtube_cookies'), __("Otherwise FV Player Pro uses the youtube-nocookie.com domain to avoid use of YouTube cookies.", 'fv-player-pro') ); ?>
367
368 <?php
369 $fv_fp->_get_input_text( array(
370 'key' => array( 'pro', 'youtube_key' ),
371 'name' => __('Google Developer Key', 'fv-player-pro'),
372 'first_td_class' => 'first',
373 'help' => __('Required for a reliable YouTube splash screen and YouTube video duration parsing. Start a new project at <a href="https://console.developers.google.com/" target="_blank">Google Developers Console</a> and make sure YouTube Data API is enabled for the project.', 'fv-player-pro'),
374 'secret' => true
375 ) );
376 ?>
377
378 <?php if( $sError = get_option('fv_player_pro_youtube_error') ) : ?>
379 <tr>
380 <td style="width: 250px"></td>
381 <td>
382 <p class="description">
383 <?php esc_html_e('Last Error', 'fv-player-pro'); ?>: <?php echo esc_html( $sError ); ?>
384 </p>
385 </td>
386 </tr>
387 <?php endif; ?>
388 <?php if( !function_exists('FV_PLayer_Pro')): ?>
389 <tr>
390 <td colspan="4">
391 <a class="fv-wordpress-flowplayer-save button button-primary" href="#" style="margin-top: 2ex;"><?php esc_html_e( 'Save', 'fv-player' ); ?></a>
392 </td>
393 </tr>
394 <?php endif; ?>
395 <?php do_action('fv_player_youtube_inputs_after'); ?>
396 </table>
397 <div class="clear"></div>
398 <script>
399 jQuery( function($) {
400 show_description_youtube_chrome();
401
402 $('[name=youtube_browser_chrome]').on( 'change', show_description_youtube_chrome );
403
404 function show_description_youtube_chrome() {
405 $( '#fv_player_youtube [data-describe]' ).hide();
406 $( '#fv_player_youtube [data-describe='+$('[name=youtube_browser_chrome]:checked').val()+']' ).show();
407 }
408 });
409 </script>
410 <?php
411 }
412
413 function get__cached_splash( $splash, $src = false ) {
414 global $post;
415
416 if( !$splash && is_string($src) ) {
417
418 $sVideoMeta = isset($post) ? get_post_meta( $post->ID, flowplayer::get_video_key($src, true ), true ) : false;
419 if( !empty($sVideoMeta['splash']) ) {
420 return $sVideoMeta['splash'];
421 }
422
423 // If we have no image we accept it if it's recent
424 if( !empty($sVideoMeta['date']) && $sVideoMeta['date'] + 3600 > time() ) {
425 return false;
426 }
427
428 if( $this->fTimeSpent_AutoSplash < 1 ) {
429 global $post;
430 if( $video_id = $this->is_youtube($src) ) {
431 $video_id = $video_id[1];
432 $type = 'youtube';
433 }
434
435 if( $video_id ) {
436 $tStart = microtime(true);
437 $splash = get_option('fv_player_'.$type.'_splash_'.$video_id);
438 if( !$splash ) {
439 $post_id = !empty($post->ID) ? $post->ID : false;
440
441 $videoData = $this->fetch_yt_data($src, $post_id);
442 if( $videoData && isset($videoData['thumbnail']) ) {
443 $this->fTimeSpent_AutoSplash += microtime(true) - $tStart;
444 update_option( 'fv_player_'.$type.'_splash_'.$video_id, $videoData['thumbnail'], false );
445 return $videoData['thumbnail'];
446 }
447
448 } else {
449 return $splash;
450
451 }
452
453 }
454 }
455 }
456
457 return $splash;
458 }
459
460 public function is_youtube( $sURL ) {
461
462 if(
463 preg_match( "~youtube.com/.*?(?:v|list)=([a-zA-Z0-9_-]+)(?:\?|$|&)~i", $sURL, $aDynamic ) ||
464 preg_match( "~youtube(?:-nocookie)?.com/(?:embed|live|shorts)/([a-zA-Z0-9_-]+)(?:\?|$|&)~i", $sURL, $aDynamic ) ||
465 preg_match( "~youtu.be/([a-zA-Z0-9_-]+)(?:\?|$|&)~i", $sURL, $aDynamic )
466 ) {
467 $this->bYoutube = true;
468 return $aDynamic;
469 }
470 return false;
471 }
472
473 function player_attributes( $aAttributes, $media, $fv_fp ) {
474 global $fv_fp;
475
476 $aArgs = func_get_args();
477
478 if( isset($aArgs[2]->aCurArgs['src']) && $this->is_youtube($aArgs[2]->aCurArgs['src']) ) {
479 $aAttributes['data-engine'] = 'fvyoutube';
480 $fv_fp->aCurArgs['engine'] = 'fvyoutube';
481 if( stripos($aAttributes['class'],' is-youtube') === false ) {
482 $aAttributes['class'] .= ' is-youtube';
483 }
484 }
485
486 return $aAttributes;
487 }
488
489 function player_item($aItem, $index) {
490 global $fv_fp;
491
492 if( isset($aItem['sources'][0]['src']) && $this->is_youtube($aItem['sources'][0]['src']) ) {
493 $video = $fv_fp->current_video();
494
495 if( !$video ) {
496 return $aItem;
497 }
498
499 $attachment_id = $video->getMetaValue('author_thumbnail', true);
500 $author_name = $video->getMetaValue('author_name', true);
501 $author_url = $video->getMetaValue('author_url', true);
502
503 if( $attachment_id) {
504 // get attachment url from attachment id
505 $attachment_url = wp_get_attachment_url( $attachment_id );
506
507 if( $attachment_url ) {
508 $aItem['author_thumbnail'] = $attachment_url;
509 }
510 }
511
512 if( $author_name ) {
513 $aItem['author_name'] = $author_name;
514 }
515
516 if( $author_url ) {
517 $aItem['author_url'] = $author_url;
518 }
519
520 }
521
522 return $aItem;
523 }
524
525 function scripts() {
526 global $post;
527
528 // todo: something better for video checker
529 /*if( isset($GLOBALS['fv_fp_scripts']) && isset($GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media']) && count($GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media']) ) {
530 foreach( $GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media'] AS $key => $item ) {
531 if( !is_array($item[0]) && ( FV_Player_Pro_Vimeo()->is_vimeo(stripslashes($item[0])) || $this->is_youtube(stripslashes($item[0])) ) || apply_filters('fv_player_video_checker_exclude',false,$item[0]) ) {
532 unset( $GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media'][$key] );
533 }
534 }
535 }*/
536
537 // Was there any player or do we expect any to load in Ajax?
538 if(
539 isset($GLOBALS['fv_fp_scripts']) ||
540 $this->should_force_load_js()
541 ) {
542
543 // If we expect players to load in Ajax, YouTube API needs to
544 // be there at all times
545 if( $this->should_force_load_js() ) $this->bYoutube = 1;
546
547 $aOptions = array(
548 'youtube' => $this->bYoutube,
549 );
550
551 // TODO: Put bYouTube into fv_flowplayer_conf
552 }
553 }
554
555 function set_file_type( $type ) {
556 $args = func_get_args();
557 if( isset($args[1]) ) {
558 if( $this->is_youtube($args[1]) ) {
559 $type = "video/youtube";
560 }
561 }
562 return $type;
563 }
564
565 function youtube_duration( $iTime ) {
566 return $iTime;
567
568 $aArgs = func_get_args();
569
570 if( $iTime == 0 && $aId = $this->is_youtube($aArgs[1]) ) {
571 $response = wp_remote_get( 'http://gdata.youtube.com/feeds/api/videos/'.$aId[1].'?v=2&alt=jsonc', array( 'sslverify' => false ) );
572 $obj = is_wp_error($response) ? false : @json_decode( wp_remote_retrieve_body($response) );
573
574 if( $obj && isset($obj->data->duration) ) {
575 $iTime = $obj->data->duration;
576 }
577
578 }
579
580 return $iTime;
581 }
582
583 function youtube_splash( $splash, $src = false ) {
584 if( !$splash && is_string($src) && $res = $this->is_youtube($src) ) {
585 return "https://i.ytimg.com/vi/".$res[1]."/maxresdefault.jpg#auto";
586 }
587 return $splash;
588 }
589
590 public function custom_upload_path( $upload_dir ) {
591 $upload_dir['path'] = $upload_dir['basedir'].'/fv-player-youtube-channels';
592 $upload_dir['url'] = $upload_dir['baseurl'].'/fv-player-youtube-channels';
593 return $upload_dir;
594 }
595
596 }
597
598 function FV_Player_YouTube() {
599 return FV_Player_YouTube::_get_instance();
600 }
601
602 FV_Player_YouTube();
603