-- 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