diff --git a/main.go b/main.go index e596406..945b5cd 100644 --- a/main.go +++ b/main.go @@ -72,6 +72,7 @@ type CLI struct { Projector ProjectorCmd `help:"Manage projectors." cmd:"" aliases:"prj" group:"Projector"` Screenshot ScreenshotCmd `help:"Take screenshots." cmd:"" aliases:"ss" group:"Screenshot"` Settings SettingsCmd `help:"Manage video and profile settings." cmd:"" aliases:"set" group:"Settings"` + Mediainput Mediainput `help:"Manage media inputs." cmd:"" aliases:"mi" group:"Media Input"` } type context struct { diff --git a/mediainputs.go b/mediainputs.go new file mode 100644 index 0000000..dbd84cd --- /dev/null +++ b/mediainputs.go @@ -0,0 +1,117 @@ +package main + +import ( + "fmt" + + "github.com/andreykaipov/goobs/api/requests/mediainputs" +) + +// Mediainput represents a collection of commands to control media inputs. +type Mediainput struct { + SetCursor MediainputSetCursorCmd `cmd:"" help:"Sets the cursor position of a media input."` + Play MediainputPlayCmd `cmd:"" help:"Plays a media input."` + Pause MediainputPauseCmd `cmd:"" help:"Pauses a media input."` + Stop MediainputStopCmd `cmd:"" help:"Stops a media input."` + Restart MediainputRestartCmd `cmd:"" help:"Restarts a media input."` +} + +// MediainputSetCursorCmd represents the command to set the cursor position of a media input. +type MediainputSetCursorCmd struct { + InputName string `arg:"" help:"Name of the media input."` + TimeString string `arg:"" help:"Time position to set the cursor to (e.g., '00:01:30' for 1 minute 30 seconds)."` +} + +// Run executes the command to set the cursor position of the media input. +func (cmd *MediainputSetCursorCmd) Run(ctx *context) error { + position, err := parseTimeStringToSeconds(cmd.TimeString) + if err != nil { + return fmt.Errorf("failed to parse time string: %w", err) + } + + _, err = ctx.Client.MediaInputs.SetMediaInputCursor( + mediainputs.NewSetMediaInputCursorParams(). + WithInputName(cmd.InputName). + WithMediaCursor(position)) + if err != nil { + return fmt.Errorf("failed to set media input cursor: %w", err) + } + + fmt.Fprintln(ctx.Out, "Set media input cursor to position (seconds):", position) + return nil +} + +// MediainputPlayCmd represents the command to play a media input. +type MediainputPlayCmd struct { + InputName string `arg:"" help:"Name of the media input."` +} + +// Run executes the command to play the media input. +func (cmd *MediainputPlayCmd) Run(ctx *context) error { + _, err := ctx.Client.MediaInputs.TriggerMediaInputAction( + mediainputs.NewTriggerMediaInputActionParams(). + WithInputName(cmd.InputName). + WithMediaAction("OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY")) + if err != nil { + return fmt.Errorf("failed to play media input: %w", err) + } + + fmt.Fprintln(ctx.Out, "Playing media input:", cmd.InputName) + return nil +} + +// MediainputPauseCmd represents the command to pause a media input. +type MediainputPauseCmd struct { + InputName string `arg:"" help:"Name of the media input."` +} + +// Run executes the command to pause the media input. +func (cmd *MediainputPauseCmd) Run(ctx *context) error { + _, err := ctx.Client.MediaInputs.TriggerMediaInputAction( + mediainputs.NewTriggerMediaInputActionParams(). + WithInputName(cmd.InputName). + WithMediaAction("OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE")) + if err != nil { + return fmt.Errorf("failed to pause media input: %w", err) + } + + fmt.Fprintln(ctx.Out, "Pausing media input:", cmd.InputName) + return nil +} + +// MediainputStopCmd represents the command to stop a media input. +type MediainputStopCmd struct { + InputName string `arg:"" help:"Name of the media input."` +} + +// Run executes the command to stop the media input. +func (cmd *MediainputStopCmd) Run(ctx *context) error { + _, err := ctx.Client.MediaInputs.TriggerMediaInputAction( + mediainputs.NewTriggerMediaInputActionParams(). + WithInputName(cmd.InputName). + WithMediaAction("OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP")) + if err != nil { + return fmt.Errorf("failed to stop media input: %w", err) + } + + fmt.Fprintln(ctx.Out, "Stopping media input:", cmd.InputName) + return nil +} + +// MediainputRestartCmd represents the command to restart a media input. +type MediainputRestartCmd struct { + InputName string `arg:"" help:"Name of the media input."` +} + +// Run executes the command to restart the media input. +func (cmd *MediainputRestartCmd) Run(ctx *context) error { + _, err := ctx.Client.MediaInputs.TriggerMediaInputAction( + mediainputs.NewTriggerMediaInputActionParams(). + WithInputName(cmd.InputName). + WithMediaAction("OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART")) + if err != nil { + return fmt.Errorf("failed to restart media input: %w", err) + } + + fmt.Fprintln(ctx.Out, "Restarting media input:", cmd.InputName) + return nil +} diff --git a/util.go b/util.go index c98c25a..88beb95 100644 --- a/util.go +++ b/util.go @@ -3,8 +3,10 @@ package main import ( + "fmt" "os" "strings" + "time" ) func snakeCaseToTitleCase(snake string) string { @@ -36,3 +38,29 @@ func trimPrefix(s, prefix string) string { } return s } + +func parseTimeStringToSeconds(timeStr string) (float64, error) { + parts := strings.Split(timeStr, ":") + var durationStr string + + switch len(parts) { + case 1: + // Format: SS -> "SSs" + durationStr = parts[0] + "s" + case 2: + // Format: MM:SS -> "MMmSSs" + durationStr = parts[0] + "m" + parts[1] + "s" + case 3: + // Format: HH:MM:SS -> "HHhMMmSSs" + durationStr = parts[0] + "h" + parts[1] + "m" + parts[2] + "s" + default: + return 0, fmt.Errorf("invalid time format: %s", timeStr) + } + + duration, err := time.ParseDuration(durationStr) + if err != nil { + return 0, fmt.Errorf("failed to parse duration: %w", err) + } + + return duration.Seconds(), nil +}