Skip to content
sk89q edited this page Aug 16, 2010 · 20 revisions

Introduction

When a user wants to play a video, the user first puts in a media open request. This is the built-in way of player control but it can overridden via the API so that you can use your own control mechanism. This media open request gets sent to the instance’s OpenMedia method which calls PlayX.ResolveProvider to get or guess the provider (YouTube, Vimeo, etc.). The provider converts the arguments into a handler name and its arguments. This handler name and the arguments are sent to the client and are given to the specified handler. The handler builds the HTML, CSS, and JavaScript for the browser and the client entity takes this handler result and uses it to play the media.

Spawning the Player

The player’s entity is named gmod_playx and it can be spawned like any other entity. The only critical piece of information is the entity’s model because it determines the screen position. It is currently not possible to manually define a screen location.

local ent = ents.Create("gmod_playx")
ent:SetModel("models/dav0r/camera.mdl")
ent:SetPos(Vector(-124.8963, 399.7217, 300))
ent:SetAngles(Angle(90, 0, 0))
ent:Spawn()
ent:Activate()

PlayX can be embedded inside a map using Hammer as well.

Playing Media

There are two methods to playing media:

  • Using ENT:OpenMedia(), which will automatically find a provider to generate the handler information.
  • Using ENT:BeginMedia(), where you have to provide the handler and handler arguments directly.

The normal player control mechanism uses OpenMedia() but for a gamemode, it provides little control of acceptable videos. If you want finer control, you will have to generate the handler manually.

Resolving Providers

PlayX.ResolveProvider() detects the provider (or lets you force one) and returns the provider name (useful if it was detected) and handler table if given a media URI. You can thus check the returned information to see if you want to allow the media. If you do, you could pass the handler information onto ENT:BeginMedia().

local provider, result = PlayX.ResolveProvider(provider, uri, useJW)

-- No provider was detected
if provider == nil then
    return false, result -- Result is a human-readable error message 
end

ent:BeginMedia(result.Handler, result.URI, start, result.ResumeSupported,
               result.LowFramerate, result.HandlerArgs)

In the handler table that is returned is a QueryMetadata() member function that fetches whatever metadata is available for the media. The function takes two arguments: a success callback and a failure callback. The first argument passed to the success callback will be a table contain metadata information. An example member of this metadata information table is Length, which is the length of the media in seconds. This can be used to restrict videos based on length.

ENT:OpenMedia() calls the metadata query function and updates the entity’s metadata with the information using ENT:UpdateMetadata(). If you call ENT:BeginMedia() instead, the metadata information will not be provided to the entity. The following code is the code in OpenMedia() that updates the metadata information.

if result.QueryMetadata then
    result.QueryMetadata(function(data)
        if ValidEntity(self) then self:UpdateMetadata(data) end
    end,
    function(err)
        if ValidEntity(self) then self.OnMetadataError(err) end
    end)
end

Note that you cannot begin any media right after the PlayX entity was spawned because PlayX sends a usermessage when you begin media. This usermessage will arrive before the entity actually exists on the client, causing an error.

Closing Media

Call ENT:CloseMedia() to close media.

Controlling Subscribers

People who are able to view a PlayX entity are called “subscribers.” By default, everyone will see the video and sound on all PlayX entities. If your gamemode has several PlayX entities, this becomes a problem. This behavior is called “auto subscription,” where users are automatically subscribed to a PlayX instance when they join or when the entity is created. Behavior by default, as mentioned, is to subscribe everyone, but you can control this behavior with the PlayXShouldAutoSubscribe hook. You can even disable it all together by returning false for the hook.

-- Disable auto-subscription
hook.Add("PlayXShouldAutoSubscribe", "Example", function(ply, instance) do
    return false
end)

To manually subscribe or unsubscribe a player, you can call the ENT:Subscribe and ENT:Unsubscribe methods on a PlayX entity. Note that manual subscription will not collide with the PlayXShouldAutoSubscribe hook because that hook is only used when a player joins the server or when a new PlayX entity is created. It is never used to “check” subscribers.

Example code to automatically subscribe or unsubscribe a user from a player when the user presses use on the entity follows:

hook.Add("PlayXUse", "Example", function(instance, activator, caller) do
    if activator:IsPlayer() then
        if instance:IsSubscribed(activator) then
            instance:Unsubscribe(activator)
        else
            instance:Subscribe(activator)
        end
    end
end)

Be aware that that code does not prevent a user from spamming the use key or subscribing to multiple players at once.

Clone this wiki locally