-- object_youtube_player - Behavior for Youtube video player
-- (component of behavior_lib_1)
-- Template attachment: objects that need to play Youtube videos
-- Created by: Patrick Ferland
-- Created on: 08/17/2008
-- Based on Youtube Code Snippet
-- As of 2008-08-17
-- https://alpha.metaplace.com/wiki/index.php/Play_a_Youtube_video_in_UI
-- Revision History
-- 08/17/2008 P.Ferland - New script
-- 08/18/2008 P.Ferland - Cleanup and UI enhancements
-- 08/22/2008 P.Ferland - Added toggle to allow user-mode (closeable) windows
-- 08/28/2008 J.McNab - Added Radial Menu customize ui
-- 09/16/2008 P.Ferland - Changed default setting to user-mode and not world-mode
-- 10/09/2008 P.Ferland - OX friendliness pass and moved into Behavior Library
-- 10/10/2008 P.Ferland - Added compatibility check to prevent stomping video_tv and mp_video derived objects
-- Constants
YOUTUBE_SCRIPT = '12071:48'
-- Percentage of total video time to add to play time as a lag hedge
FUDGE_TIME = 0.05
-- Image for forced-play to world
PLAY_IMAGE =
{
SPRITE = '12071:446',
W = 285,
H = 244
}
-- Default tile sizes
TILE_WIDTH = 64
TILE_HEIGHT = 64
MAX_TITLE_LENGTH =
{
INPLACE = 30,
WINDOW = 42
}
-- Script properties
Define Properties()
script_description = "Youtube Video Player"
script_long_description = "This behavior allows an object to play Flash video from Youtube.com"
script_load_first = 1
video_player_url = 'http://www.youtube.com/watch?v=d6byvRceySk'
ExposeProperty('video_player_url', 'Youtube video URL')
PersistProperty('video_player_url')
video_playable_by_users = 1
ExposeProperty('video_playable_by_users', 'Video playable by normal users?', 'checkbox')
PersistProperty('video_playable_by_users')
video_play_at_tv = 0
ExposeProperty('video_play_at_tv', 'Check to play in-world (as on a TV), uncheck for closeable window', 'checkbox')
PersistProperty('video_play_at_tv')
video_window = 0
IncludeScript('13197:21') -- ui_library
IncludeScript('12071:3') -- configurable
script_load_first = 1
end
-- Commands
-- no commands
-- Triggers
Trigger use(user)
local play = 1
-- Check if the user can play the video
if (self.video_playable_by_users == 0) then
if (IsSuperuser(user) ~= 1) then
play = 0
end
end
-- Check if a video is already playing...
if (self.video_window ~= 0) then
play = 0
end
if (play == 0) then
return
end
play_youtube_by_url(self, self.video_player_url)
end
Trigger video_player_end(video_window)
local safe_video_win = UiFindWindow(video_window, 'video_tv_' .. self.id)
if (safe_video_win ~= 0) then
UiDelete(safe_video_win)
end
if (video_window == self.video_window) then
self.video_window = 0
end
end
Trigger youtubewatch_response(response, body)
-- Identify raw video URL
local query_start = "/watch_fullscreen?"
local query_end = "';"
local query_start_pos = string.find(body, query_start)
if (query_start_pos == nil) then
return
end
query_start_pos = query_start_pos + string.len(query_start)
query_end_pos = string.find(body, query_end, query_start_pos)
if (query_end_pos== nil) then
return
end
local query_string = string.sub(body, query_start_pos, query_end_pos - 1)
local video_url = "http://www.youtube.com/get_video?" .. query_string
-- Identify video length
query_start = '", "l": '
query_end = ', "'
local query_start_pos = string.find(body, query_start)
if (query_start_pos == nil) then
return
end
query_start_pos = query_start_pos + string.len(query_start)
query_end_pos = string.find(body, query_end, query_start_pos)
if (query_end_pos== nil) then
return
end
query_string = string.sub(body, query_start_pos, query_end_pos - 1)
local video_length = tonumber(query_string)
if ( (video_length == nil) or (video_length < 1) ) then
video_length = 29
end
video_length = video_length + 1 + math.ceil(FUDGE_TIME * video_length)
-- Identify video title
query_start = ''
local query_start_pos = string.find(body, query_start)
if (query_start_pos == nil) then
return
end
query_start_pos = query_start_pos + string.len(query_start)
query_end_pos = string.find(body, query_end, query_start_pos)
if (query_end_pos== nil) then
return
end
local video_title = string.sub(body, query_start_pos, query_end_pos - 1)
if (video_title == nil) then
video_title = ''
end
play_video(self, video_url, video_length, video_title)
end
-- Added 08/28/2008 - J.McNab
Trigger customize_tv_radial_init(caller, user_id)
if(HasScriptById(self, '12071:3') == 0) then
AttachScriptById(self, '12071:3')
end
SendTo(self, 'configure_behavior_properties', 0, self.id, user_id, '14070:33')
end
Trigger custom_config(caller, user_id, script_id, offset)
if(script_id == '14070:33') then
local user = GetObjectById(user_id)
if(user == nil) then
return
end
-- Create Main Window
local window_w = 320
local window_h = 300
local custom_window = config_window(self, user_id, script_id, window_w, window_h)
local url_video = {'http://www.youtube.com/watch?v=tZiB_JcRH_s',
'http://www.youtube.com/watch?v=d6byvRceySk',
'http://www.youtube.com/watch?v=WanLLnVixC4',
'http://www.youtube.com/watch?v=V5BxymuiAxQ'}
local url_img = {'http://i1.ytimg.com/vi/tZiB_JcRH_s/default.jpg',
'http://i1.ytimg.com/vi/ljMODw-fXaI/default.jpg',
'http://i4.ytimg.com/vi/WanLLnVixC4/default.jpg',
'http://i2.ytimg.com/vi/9BxNJRxGbgE/default.jpg'}
local url_name = {'Metaplace (BBC)', 'Corn Cat', 'Pork and Beans', 'I Love The Whole World'}
local preset_label = UiMultiLabel(custom_window.id, 'customize_tv_radial_preset_label', 2, 22, window_w - 12, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
UiText(preset_label, 'Select a video to display...')
local icon_size = 64
local padding = (custom_window.width - (icon_size * #url_video))/#url_video
local icon_x = padding/2
local icon_y = 45
for index, img in pairs(url_img) do
local img_icon = UiImageRef(custom_window.id, 'customize_tv_radial_preset_' .. index, icon_x, icon_y, icon_size, icon_size, url_img[index])
local img_btn = UiImageButton(img_icon, 'customize_tv_radial_preset_' .. index .. '_btn', 0, 0, icon_size, icon_size, '12071:84', '12071:84', '12071:84', string.format('/event set_tv_url %d %d %s %d %s', self.id, user_id, script_id, offset, url_video[index], user.id))
UiColor(img_btn, 0, 0, 0, 0)
local img_tag = UiMultiLabel(img_icon, 'customzie_tv_radial_preset_' .. index .. '_tag', 0, icon_size - 3, icon_size, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2)
UiText(img_tag, string.format('%s', url_name[index]))
icon_x = icon_x + padding + icon_size
end
local url_input_label = UiMultiLabel(custom_window.id, 'customize_tv_radial_url_input_label', 6, custom_window.height - 60, custom_window.width - 12, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
UiText(url_input_label, '...or input your own url')
local url_input = UiTextField(custom_window.id, 'customzie_tv_radial_url_input', 6, custom_window.height - 40, custom_window.width - 12, 15, 0, 0, 0, 255, 255, 255, 1, string.format('/event set_tv_url %d %d %s %d', self.id, user_id, script_id, offset), self['video_player_url'])
end
end
Trigger set_tv_url(caller, user_id, script_id, offset, url)
self['video_player_url'] = url
SendTo(self, 'custom_config', 0, self.id, user_id, script_id, offset)
end
Trigger set_tv_url_final(caller, url, user_id)
local user = GetObjectById(user_id)
self['video_player_url'] = url
if(user ~= nil) then
UiDelete(user.smart_object_window)
user.smart_object_window = 0
end
end
-- Local functions
function play_youtube_by_url(self, youtubeURL)
local request = {}
request.url = youtubeURL
request.method = "GET"
request.trigger = "youtubewatch_response"
request.body = ""
request.headers = {}
WebRequest(self, request)
end
function play_video(self, video_url, video_length, video_title)
if (self.video_window ~= 0) then
UiDelete(self.video_window)
self.video_window = 0
end
if (self.video_play_at_tv == 1) then
if (string.len(video_title) > MAX_TITLE_LENGTH.INPLACE) then
video_title = string.sub(video_title, 1, MAX_TITLE_LENGTH.INPLACE) .. '...'
end
local x, y = calc_xy(self, PLAY_IMAGE.W, PLAY_IMAGE.H)
self.video_window = UiImage(0, 'video_tv_' .. self.id, x, y, PLAY_IMAGE.W, PLAY_IMAGE.H, PLAY_IMAGE.SPRITE)
local video_win_title = UiMultiLabel(self.video_window, 'video_win_title_' .. self.id,
16, -2, 224, 24,
230, 230, 230, 255, 255, 255, 0,
0, 0, 0)
UiText(video_win_title, '' .. video_title .. '')
local video_bg = UiRect(self.video_window, 'video_bg_' .. self.id, 21, 20, 244, 184)
UiColor(video_bg, 160, 160, 160, 1)
local video_playing = UiLabel(self.video_window, 'video_playing_' .. self.id, 60, 60, 'Loading video...')
UiColor(video_playing, 0, 0, 0, 1)
local video_player = UiVideoRef(self.video_window, 'video_player_' .. self.id, 23, 23, 240, 180, video_url)
UiAttachObject(self, self.video_window)
UiVisible(self.video_window, 1)
SendTo(self, 'video_player_end', 1000 * video_length, self.video_window)
else
if (string.len(video_title) > MAX_TITLE_LENGTH.WINDOW) then
video_title = string.sub(video_title, 1, MAX_TITLE_LENGTH.WINDOW) .. '...'
end
local obj = 0
local p = GetPlace()
for _, obj in ipairs(p.users) do
play_video_user(self, video_url, video_length, video_title, obj)
end
end
end
function play_video_user(self, video_url, video_length, video_title, user)
local video_window = ui_default_window(0, 'video_tv_' .. self.id, 0, 0, 340, 280)
local video_win_title = UiMultiLabel(video_window, 'video_win_title_' .. self.id,
0, 0, 310, 24,
0, 0, 0, 255, 255, 255, 0,
0, 0, 0)
UiText(video_win_title, '' .. video_title .. '')
local video_player = UiVideoRef(video_window, 'video_player_' .. self.id, 10, 30, 320, 240, video_url)
UiAlign(video_window, 0, 0, 'center', 'scale_none')
UiAttachUser(user, video_window)
UiVisible(video_window, 1)
SendTo(self, 'video_player_end', 1000 * video_length, video_window)
end
function calc_xy(self, width, height)
local x = 0
local y = 0
local sprite = stylesheet.sprites[self.spriteId]
local origin_mode = sprite.originMode
local sprite_width = math.ceil(sprite.scaleX * TILE_WIDTH)
local sprite_height = math.ceil(sprite.scaleY * TILE_HEIGHT)
if (origin_mode == 2) then -- bottom-center
x = 0 - math.floor(width / 2)
y = (0 - math.floor(sprite_height / 2)) - math.floor(height / 2)
elseif (origin_mode == 1) then -- top-left
x = math.floor(sprite_width / 2) - math.floor(width / 2)
y = math.floor(sprite_height / 2) - math.floor(height / 2)
else -- (origin_mode == 0) -- center-center
x = 0 - math.floor(width / 2)
y = 0 - math.floor(height / 2)
end
return x, y
end