mirror of
https://github.com/onyx-and-iris/gobs-cli.git
synced 2025-06-30 23:40:29 +01:00
444 lines
13 KiB
Go
444 lines
13 KiB
Go
// nolint: misspell
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/andreykaipov/goobs"
|
|
"github.com/andreykaipov/goobs/api/requests/sceneitems"
|
|
"github.com/charmbracelet/lipgloss"
|
|
"github.com/charmbracelet/lipgloss/table"
|
|
)
|
|
|
|
// 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 {
|
|
UUID bool `flag:"" help:"Display UUIDs of scene items."`
|
|
SceneName string ` help:"Name of the scene to list items from." arg:"" default:""`
|
|
}
|
|
|
|
// Run executes the command to list all scene items in a scene.
|
|
func (cmd *SceneItemListCmd) Run(ctx *context) error {
|
|
if cmd.SceneName == "" {
|
|
currentScene, err := ctx.Client.Scenes.GetCurrentProgramScene()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get current program scene: %w", err)
|
|
}
|
|
cmd.SceneName = currentScene.SceneName
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
if len(resp.SceneItems) == 0 {
|
|
fmt.Fprintf(ctx.Out, "No scene items found in scene %s.\n", ctx.Style.Highlight(cmd.SceneName))
|
|
return nil
|
|
}
|
|
|
|
t := table.New().Border(lipgloss.RoundedBorder()).
|
|
BorderStyle(lipgloss.NewStyle().Foreground(ctx.Style.border))
|
|
if cmd.UUID {
|
|
t.Headers("Item ID", "Item Name", "In Group", "Enabled", "UUID")
|
|
} else {
|
|
t.Headers("Item ID", "Item Name", "In Group", "Enabled")
|
|
}
|
|
t.StyleFunc(func(row, col int) lipgloss.Style {
|
|
style := lipgloss.NewStyle().Padding(0, 3)
|
|
switch col {
|
|
case 0:
|
|
style = style.Align(lipgloss.Center)
|
|
case 1:
|
|
style = style.Align(lipgloss.Left)
|
|
case 2:
|
|
style = style.Align(lipgloss.Center)
|
|
case 3:
|
|
style = style.Align(lipgloss.Center)
|
|
case 4:
|
|
style = style.Align(lipgloss.Left)
|
|
}
|
|
switch {
|
|
case row == table.HeaderRow:
|
|
style = style.Bold(true).Align(lipgloss.Center)
|
|
case row%2 == 0:
|
|
style = style.Foreground(ctx.Style.evenRows)
|
|
default:
|
|
style = style.Foreground(ctx.Style.oddRows)
|
|
}
|
|
return style
|
|
})
|
|
|
|
sort.Slice(resp.SceneItems, func(i, j int) bool {
|
|
return resp.SceneItems[i].SceneItemID < resp.SceneItems[j].SceneItemID
|
|
})
|
|
|
|
for _, item := range resp.SceneItems {
|
|
if item.IsGroup {
|
|
resp, err := ctx.Client.SceneItems.GetGroupSceneItemList(sceneitems.NewGetGroupSceneItemListParams().
|
|
WithSceneName(item.SourceName))
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"failed to get group scene item list for group %s: %w",
|
|
ctx.Style.Error(item.SourceName),
|
|
err,
|
|
)
|
|
}
|
|
|
|
sort.Slice(resp.SceneItems, func(i, j int) bool {
|
|
return resp.SceneItems[i].SceneItemID < resp.SceneItems[j].SceneItemID
|
|
})
|
|
|
|
for _, groupItem := range resp.SceneItems {
|
|
if cmd.UUID {
|
|
t.Row(
|
|
fmt.Sprintf("%d", groupItem.SceneItemID),
|
|
groupItem.SourceName,
|
|
item.SourceName,
|
|
getEnabledMark(item.SceneItemEnabled && groupItem.SceneItemEnabled),
|
|
groupItem.SourceUuid,
|
|
)
|
|
} else {
|
|
t.Row(
|
|
fmt.Sprintf("%d", groupItem.SceneItemID),
|
|
groupItem.SourceName,
|
|
item.SourceName,
|
|
getEnabledMark(item.SceneItemEnabled && groupItem.SceneItemEnabled),
|
|
)
|
|
}
|
|
}
|
|
} else {
|
|
if cmd.UUID {
|
|
t.Row(fmt.Sprintf("%d", item.SceneItemID), item.SourceName, "",
|
|
getEnabledMark(item.SceneItemEnabled), item.SourceUuid)
|
|
} else {
|
|
t.Row(fmt.Sprintf("%d", item.SceneItemID), item.SourceName, "", getEnabledMark(item.SceneItemEnabled))
|
|
}
|
|
}
|
|
}
|
|
fmt.Fprintln(ctx.Out, t.Render())
|
|
return nil
|
|
}
|
|
|
|
// getSceneNameAndItemID retrieves the scene name and item ID for a given item in a scene or group.
|
|
func getSceneNameAndItemID(
|
|
ctx *context,
|
|
sceneName string,
|
|
itemName string,
|
|
group string,
|
|
) (string, int, error) {
|
|
if group != "" {
|
|
resp, err := ctx.Client.SceneItems.GetGroupSceneItemList(sceneitems.NewGetGroupSceneItemListParams().
|
|
WithSceneName(group))
|
|
if err != nil {
|
|
return "", 0, err
|
|
}
|
|
for _, item := range resp.SceneItems {
|
|
if item.SourceName == itemName {
|
|
return group, int(item.SceneItemID), nil
|
|
}
|
|
}
|
|
return "", 0, fmt.Errorf("item %s not found in scene %s", ctx.Style.Error(itemName), ctx.Style.Error(sceneName))
|
|
}
|
|
|
|
itemID, err := ctx.Client.SceneItems.GetSceneItemId(sceneitems.NewGetSceneItemIdParams().
|
|
WithSceneName(sceneName).
|
|
WithSourceName(itemName))
|
|
if err != nil {
|
|
if err.Error() == "request GetSceneItemId: ResourceNotFound (600): No scene items were found in the specified scene by that name or offset." {
|
|
return "", 0, fmt.Errorf(
|
|
"item %s not found in scene %s. is it in a group? if so use the %s flag to specify the parent group\nuse %s for a list of items in the scene",
|
|
ctx.Style.Error(itemName),
|
|
ctx.Style.Error(sceneName),
|
|
ctx.Style.Error("--group"),
|
|
ctx.Style.Error("gobs-cli si ls"),
|
|
)
|
|
}
|
|
return "", 0, err
|
|
}
|
|
return sceneName, int(itemID.SceneItemId), nil
|
|
}
|
|
|
|
// SceneItemShowCmd provides a command to show a scene item.
|
|
type SceneItemShowCmd struct {
|
|
Group 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, cmd.SceneName, cmd.ItemName, cmd.Group)
|
|
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.Group != "" {
|
|
fmt.Fprintf(
|
|
ctx.Out,
|
|
"Scene item %s in group %s is now visible.\n",
|
|
ctx.Style.Highlight(cmd.ItemName),
|
|
ctx.Style.Highlight(cmd.Group),
|
|
)
|
|
} else {
|
|
fmt.Fprintf(ctx.Out, "Scene item %s in scene %s is now visible.\n", ctx.Style.Highlight(cmd.ItemName), ctx.Style.Highlight(cmd.SceneName))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SceneItemHideCmd provides a command to hide a scene item.
|
|
type SceneItemHideCmd struct {
|
|
Group 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, cmd.SceneName, cmd.ItemName, cmd.Group)
|
|
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.Group != "" {
|
|
fmt.Fprintf(
|
|
ctx.Out,
|
|
"Scene item %s in group %s is now hidden.\n",
|
|
ctx.Style.Highlight(cmd.ItemName),
|
|
ctx.Style.Highlight(cmd.Group),
|
|
)
|
|
} else {
|
|
fmt.Fprintf(ctx.Out, "Scene item %s in scene %s is now hidden.\n", ctx.Style.Highlight(cmd.ItemName), ctx.Style.Highlight(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 {
|
|
Group 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, cmd.SceneName, cmd.ItemName, cmd.Group)
|
|
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",
|
|
ctx.Style.Highlight(cmd.ItemName),
|
|
ctx.Style.Highlight(cmd.SceneName),
|
|
)
|
|
} else {
|
|
fmt.Fprintf(ctx.Out, "Scene item %s in scene %s is now visible.\n", ctx.Style.Highlight(cmd.ItemName), ctx.Style.Highlight(cmd.SceneName))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SceneItemVisibleCmd provides a command to check the visibility of a scene item.
|
|
type SceneItemVisibleCmd struct {
|
|
Group 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, cmd.SceneName, cmd.ItemName, cmd.Group)
|
|
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",
|
|
ctx.Style.Highlight(cmd.ItemName),
|
|
ctx.Style.Highlight(cmd.SceneName),
|
|
)
|
|
} else {
|
|
fmt.Fprintf(ctx.Out, "Scene item %s in scene %s is hidden.\n", ctx.Style.Highlight(cmd.ItemName), ctx.Style.Highlight(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."`
|
|
|
|
Group 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, cmd.SceneName, cmd.ItemName, cmd.Group)
|
|
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.Group != "" {
|
|
fmt.Fprintf(
|
|
ctx.Out,
|
|
"Scene item %s in group %s transformed.\n",
|
|
ctx.Style.Highlight(cmd.ItemName),
|
|
ctx.Style.Highlight(cmd.Group),
|
|
)
|
|
} else {
|
|
fmt.Fprintf(ctx.Out, "Scene item %s in scene %s transformed.\n", ctx.Style.Highlight(cmd.ItemName), ctx.Style.Highlight(cmd.SceneName))
|
|
}
|
|
|
|
return nil
|
|
}
|