package main import ( "fmt" "github.com/andreykaipov/goobs" "github.com/andreykaipov/goobs/api/requests/sceneitems" ) // SceneItemCmd provides commands to manage scene items in OBS Studio. type SceneItemCmd struct { List SceneItemListCmd `cmd:"" help:"List all scene items." aliases:"ls"` Show SceneItemShowCmd `cmd:"" help:"Show scene item." aliases:"sh"` Hide SceneItemHideCmd `cmd:"" help:"Hide scene item." aliases:"h"` Toggle SceneItemToggleCmd `cmd:"" help:"Toggle scene item." aliases:"tg"` Visible SceneItemVisibleCmd `cmd:"" help:"Get scene item visibility." aliases:"v"` Transform SceneItemTransformCmd `cmd:"" help:"Transform scene item." aliases:"t"` } // SceneItemListCmd provides a command to list all scene items in a scene. type SceneItemListCmd struct { SceneName string `arg:"" help:"Scene name."` } // Run executes the command to list all scene items in a scene. func (cmd *SceneItemListCmd) Run(ctx *context) error { resp, err := ctx.Client.SceneItems.GetSceneItemList(sceneitems.NewGetSceneItemListParams(). WithSceneName(cmd.SceneName)) if err != nil { return fmt.Errorf("failed to get scene item list: %w", err) } for _, item := range resp.SceneItems { fmt.Fprintf(ctx.Out, "Item ID: %d, Source Name: %s\n", item.SceneItemID, item.SourceName) } return nil } func getSceneNameAndItemID( client *goobs.Client, sceneName string, itemName string, parent string, ) (string, int, error) { if parent != "" { resp, err := client.SceneItems.GetGroupSceneItemList(sceneitems.NewGetGroupSceneItemListParams(). WithSceneName(parent)) if err != nil { return "", 0, err } for _, item := range resp.SceneItems { if item.SourceName == itemName { return parent, int(item.SceneItemID), nil } } return "", 0, fmt.Errorf("item '%s' not found in scene '%s'", itemName, sceneName) } itemID, err := client.SceneItems.GetSceneItemId(sceneitems.NewGetSceneItemIdParams(). WithSceneName(sceneName). WithSourceName(itemName)) if err != nil { return "", 0, err } return sceneName, int(itemID.SceneItemId), nil } // SceneItemShowCmd provides a command to show a scene item. type SceneItemShowCmd struct { Parent string `flag:"" help:"Parent group name."` SceneName string `arg:"" help:"Scene name."` ItemName string `arg:"" help:"Item name."` } // Run executes the command to show a scene item. func (cmd *SceneItemShowCmd) Run(ctx *context) error { sceneName, sceneItemID, err := getSceneNameAndItemID(ctx.Client, cmd.SceneName, cmd.ItemName, cmd.Parent) if err != nil { return err } _, err = ctx.Client.SceneItems.SetSceneItemEnabled(sceneitems.NewSetSceneItemEnabledParams(). WithSceneName(sceneName). WithSceneItemId(sceneItemID). WithSceneItemEnabled(true)) if err != nil { return err } if cmd.Parent != "" { fmt.Fprintf(ctx.Out, "Scene item '%s' in group '%s' is now visible.\n", cmd.ItemName, cmd.Parent) } else { fmt.Fprintf(ctx.Out, "Scene item '%s' in scene '%s' is now visible.\n", cmd.ItemName, cmd.SceneName) } return nil } // SceneItemHideCmd provides a command to hide a scene item. type SceneItemHideCmd struct { Parent string `flag:"" help:"Parent group name."` SceneName string `arg:"" help:"Scene name."` ItemName string `arg:"" help:"Item name."` } // Run executes the command to hide a scene item. func (cmd *SceneItemHideCmd) Run(ctx *context) error { sceneName, sceneItemID, err := getSceneNameAndItemID(ctx.Client, cmd.SceneName, cmd.ItemName, cmd.Parent) if err != nil { return err } _, err = ctx.Client.SceneItems.SetSceneItemEnabled(sceneitems.NewSetSceneItemEnabledParams(). WithSceneName(sceneName). WithSceneItemId(sceneItemID). WithSceneItemEnabled(false)) if err != nil { return err } if cmd.Parent != "" { fmt.Fprintf(ctx.Out, "Scene item '%s' in group '%s' is now hidden.\n", cmd.ItemName, cmd.Parent) } else { fmt.Fprintf(ctx.Out, "Scene item '%s' in scene '%s' is now hidden.\n", cmd.ItemName, cmd.SceneName) } return nil } // getItemEnabled retrieves the enabled status of a scene item. func getItemEnabled(client *goobs.Client, sceneName string, itemID int) (bool, error) { item, err := client.SceneItems.GetSceneItemEnabled(sceneitems.NewGetSceneItemEnabledParams(). WithSceneName(sceneName). WithSceneItemId(itemID)) if err != nil { return false, err } return item.SceneItemEnabled, nil } // SceneItemToggleCmd provides a command to toggle the visibility of a scene item. type SceneItemToggleCmd struct { Parent string `flag:"" help:"Parent group name."` SceneName string `arg:"" help:"Scene name."` ItemName string `arg:"" help:"Item name."` } // Run executes the command to toggle the visibility of a scene item. func (cmd *SceneItemToggleCmd) Run(ctx *context) error { sceneName, sceneItemID, err := getSceneNameAndItemID(ctx.Client, cmd.SceneName, cmd.ItemName, cmd.Parent) if err != nil { return err } itemEnabled, err := getItemEnabled(ctx.Client, sceneName, sceneItemID) if err != nil { return err } _, err = ctx.Client.SceneItems.SetSceneItemEnabled(sceneitems.NewSetSceneItemEnabledParams(). WithSceneName(sceneName). WithSceneItemId(sceneItemID). WithSceneItemEnabled(!itemEnabled)) if err != nil { return err } if itemEnabled { fmt.Fprintf(ctx.Out, "Scene item '%s' in scene '%s' is now hidden.\n", cmd.ItemName, cmd.SceneName) } else { fmt.Fprintf(ctx.Out, "Scene item '%s' in scene '%s' is now visible.\n", cmd.ItemName, cmd.SceneName) } return nil } // SceneItemVisibleCmd provides a command to check the visibility of a scene item. type SceneItemVisibleCmd struct { Parent string `flag:"" help:"Parent group name."` SceneName string `arg:"" help:"Scene name."` ItemName string `arg:"" help:"Item name."` } // Run executes the command to check the visibility of a scene item. func (cmd *SceneItemVisibleCmd) Run(ctx *context) error { sceneName, sceneItemID, err := getSceneNameAndItemID(ctx.Client, cmd.SceneName, cmd.ItemName, cmd.Parent) if err != nil { return err } itemEnabled, err := getItemEnabled(ctx.Client, sceneName, sceneItemID) if err != nil { return err } if itemEnabled { fmt.Fprintf(ctx.Out, "Scene item '%s' in scene '%s' is visible.\n", cmd.ItemName, cmd.SceneName) } else { fmt.Fprintf(ctx.Out, "Scene item '%s' in scene '%s' is hidden.\n", cmd.ItemName, cmd.SceneName) } return nil } // SceneItemTransformCmd provides a command to transform a scene item. type SceneItemTransformCmd struct { SceneName string `arg:"" help:"Scene name."` ItemName string `arg:"" help:"Item name."` Parent string `flag:"" help:"Parent group name."` Alignment float64 `flag:"" help:"Alignment of the scene item."` BoundsAlignment float64 `flag:"" help:"Bounds alignment of the scene item."` BoundsHeight float64 `flag:"" help:"Bounds height of the scene item." default:"1.0"` BoundsType string `flag:"" help:"Bounds type of the scene item." default:"OBS_BOUNDS_NONE"` BoundsWidth float64 `flag:"" help:"Bounds width of the scene item." default:"1.0"` CropToBounds bool `flag:"" help:"Whether to crop the scene item to bounds."` CropBottom float64 `flag:"" help:"Crop bottom value of the scene item."` CropLeft float64 `flag:"" help:"Crop left value of the scene item."` CropRight float64 `flag:"" help:"Crop right value of the scene item."` CropTop float64 `flag:"" help:"Crop top value of the scene item."` PositionX float64 `flag:"" help:"X position of the scene item."` PositionY float64 `flag:"" help:"Y position of the scene item."` Rotation float64 `flag:"" help:"Rotation of the scene item."` ScaleX float64 `flag:"" help:"X scale of the scene item."` ScaleY float64 `flag:"" help:"Y scale of the scene item."` } // Run executes the command to transform a scene item. func (cmd *SceneItemTransformCmd) Run(ctx *context) error { sceneName, sceneItemID, err := getSceneNameAndItemID(ctx.Client, cmd.SceneName, cmd.ItemName, cmd.Parent) if err != nil { return err } // Get the current transform of the scene item resp, err := ctx.Client.SceneItems.GetSceneItemTransform(sceneitems.NewGetSceneItemTransformParams(). WithSceneName(sceneName). WithSceneItemId(sceneItemID)) if err != nil { return err } // Update the transform with the provided values transform := resp.SceneItemTransform if cmd.Alignment != 0 { transform.Alignment = cmd.Alignment } if cmd.BoundsAlignment != 0 { transform.BoundsAlignment = cmd.BoundsAlignment } if cmd.BoundsHeight != 0 { transform.BoundsHeight = cmd.BoundsHeight } if cmd.BoundsType != "" { transform.BoundsType = cmd.BoundsType } if cmd.BoundsWidth != 0 { transform.BoundsWidth = cmd.BoundsWidth } if cmd.CropToBounds { transform.CropToBounds = cmd.CropToBounds } if cmd.CropBottom != 0 { transform.CropBottom = cmd.CropBottom } if cmd.CropLeft != 0 { transform.CropLeft = cmd.CropLeft } if cmd.CropRight != 0 { transform.CropRight = cmd.CropRight } if cmd.CropTop != 0 { transform.CropTop = cmd.CropTop } if cmd.PositionX != 0 { transform.PositionX = cmd.PositionX } if cmd.PositionY != 0 { transform.PositionY = cmd.PositionY } if cmd.Rotation != 0 { transform.Rotation = cmd.Rotation } if cmd.ScaleX != 0 { transform.ScaleX = cmd.ScaleX } if cmd.ScaleY != 0 { transform.ScaleY = cmd.ScaleY } _, err = ctx.Client.SceneItems.SetSceneItemTransform(sceneitems.NewSetSceneItemTransformParams(). WithSceneName(sceneName). WithSceneItemId(sceneItemID). WithSceneItemTransform(transform)) if err != nil { return err } if cmd.Parent != "" { fmt.Fprintf(ctx.Out, "Scene item '%s' in group '%s' transformed.\n", cmd.ItemName, cmd.Parent) } else { fmt.Fprintf(ctx.Out, "Scene item '%s' in scene '%s' transformed.\n", cmd.ItemName, cmd.SceneName) } return nil }