Skip to content

Instantly share code, notes, and snippets.

@imorrish
Created February 6, 2017 02:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save imorrish/f8a2b6aba612e310169dc7b4da0ac9d9 to your computer and use it in GitHub Desktop.
Save imorrish/f8a2b6aba612e310169dc7b4da0ac9d9 to your computer and use it in GitHub Desktop.
XKR-32 X-Keys and Blackmagic ATEM Television Studio sample
#region About
# Stript to control ATEM with X-keys 32
#
# Button layout
#
# 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 - blue
# 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 - Red
# 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 -blue
# 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 -red
#endregion
#region ATEM setup
add-type -path 'documents\windowspowershell\VISE_Xkeys.dll'
add-type -path 'documents\windowspowershell\SwitcherLib.dll'
[bool]$Global:Debug = $false
$Global:atem = New-Object SwitcherLib.Switcher("192.168.1.8")
$atem.Connect()
$me=$atem.GetMEs()
$me1=$me[0]
try{$me2=$me[1]; $Global:haveME2 = $false}
catch{$Global:haveME2 = $false}
$Global:activeME = $me1
$Global:txMode = $activeME.TransitionStyle
$Global:KeypadMode=""
$Global:Program = $activeME.Program
$Global:Preview = $activeME.Preview
$Global:CurrentTransition = $activeME.TransitionStyle.ToString()
$Global:FTBStatus = $activeME.FadeToBlackFullyBlack
$MediaPlayers = $atem.GetMediaPlayers()
$Global:MP1=$MediaPlayers[0]
$Global:MP2=$MediaPlayers[1]
#$Global:MacroStatus = $atem.MacroStatus()
#$Global:Aux = $atem.GetAuxInputs()
#Global valuses used in event
$global:loopColor = $false
$Global:TimeOnProgram = get-date -f "hh:mm:ss"
$ColorGen= $atem.GetColorInputs()
$Global:ColorGen1 = $ColorGen[0]
$Global:ColorGen2 = $ColorGen[1]
$ColorGen2.Luma =.5
$ColorGen2.Saturation = 1
$global:InputList = @(1,2,3,4,5,6,2002)
$global:InputCurrent = 0
$global:TimeOnInput = 1
$global:LoopInputs = $false
#$global:LoopInputs = $true
#endregion
#region X-keys setup
$Global:Xkeys = new-object VISE_Xkeys.xkeys
$Devices = $Xkeys.GetDevices()
$Devices
$Global:xkeysActiveDevice = $Devices[0].DeviceID
$Global:Xkeys.NewDevice($xkeysActiveDevice)
$numericKeys = @{1=1;3=2;5=3;7=4;9=5;11=6;13=7;15=8;17=9;19=10}
#$ProgramKeys = @{ 73=1; 65=2; 57=3; 49=4; 41=5; 33=6; 25=7; 17=8}
#$previewKeys = @{ 72=1; 64=2; 56=3; 48=4; 40=5; 32=6; 24=7; 16=8}
[string]$Global:KeypadMode=""
if($Global:Program -gt 0 -And $Global:Program -lt 7){
#turn on new program led
$Global:xkeys.SendData($Global:xkeysActiveDevice,32+($Global:Program*2-2),1)
}
if($Global:Preview -gt 0 -And $Global:Preview -lt 7){
#turn on new Preview led
$Global:xkeys.SendData($Global:xkeysActiveDevice,($Global:Preview*2-1),1)
}
#endregion
#region Time on cut clock
#. C:\Users\imorrish\onedrive\powershell\WPF\ClockWidget.ps1
#endregion
#region Telegram Bot
#. C:\Users\imorrish\onedrive\powershell\BA-ISE\Main_Telegram.ps1
#endregion
function LoadXkeys(){
$xkFile = ConvertFrom-Json (get-content "documents\WindowsPowerShell\xkr32.json" -raw)
$Global:xkCommands = @{}
#$xkFile | get-member -MemberType NoteProperty | ForEach-Object{ConvertFrom-Json $_.vlaue} | ForEach-Object{$xkCommands.add($_.name,$xkFile."$($_.name)")}
foreach($key in $xkFile.keys){
$xkCommands.add($key.KeyID,$key.Script)
}
}
LoadXKeys
function HandleXkey($keyId)
{
if($Global:Debug -eq $true){write-host "Key pressed - $($keyId) "}
if($xkCommands.ContainsKey($keyId))
{
try{invoke-expression $xkCommands.Get_Item($keyId)}
catch{write-host "error: $($error)"}
}
else {write-host "Key not defined $($keyID)"}
}
Unregister-Event -SourceIdentifier KeyPressed -ErrorAction SilentlyContinue
$MyEvent = Register-ObjectEvent -InputObject $Xkeys -EventName KeyPressed -SourceIdentifier KeyPressed -Action {HandleXkey($event.sourceEventArgs.KeyID)}
function USKAutoTransition(){
$me1.TransitionSelection=2
Start-Sleep -Milliseconds 1
$me1.AutoTransition()
Start-Sleep -Milliseconds 10 #give it a chance to start
Start-Sleep 2
#Key is now onair so remove from next transition (Turn on BKGD)
$me1.TransitionSelection=1
# Update LED
if($todo){}
}
#region Timer
$timer = New-Object System.Timers.Timer
$timer.Interval = 500
$timer.AutoReset = $true
$sourceIdentifier = "TimerJob"
$timerAction = {
#update leds
#Program
$CurrentProgram = $Global:activeME.Program
if($Global:Program -ne $CurrentProgram){
#reset Time Since Last Cut
#$Clockhash.LastCut = get-date -f "hh:mm:ss"
if($Global:Debug -eq $true){write-host "Program changed from $($Global:Program) to $($CurrentProgram) "}
if($Global:Program -gt 0 -And $Global:Program -lt 7){
#turn off current LED
$xkeys.SendData($Global:xkeysActiveDevice,32+($Global:Program*2)-2,0)
if($Global:Debug -eq $true){write-host "Turn off LED $(($Global:Program*2)-2) "}
if($CurrentProgram -gt 0 -And $CurrentProgram -lt 7){
#turn on new program led
$Global:xkeys.SendData($Global:xkeysActiveDevice,32+($CurrentProgram*2)-2,1)
if($Global:Debug -eq $true){write-host "Turn on LED $(($CurrentProgram*2)-2) "}
}
}
if($Global:Program -ne 3010){$Global:xkeys.SendData($Global:xkeysActiveDevice,44,0)}
if($Global:Program -ne 3020){$Global:xkeys.SendData($Global:xkeysActiveDevice,46,0)}
$Global:Program = $CurrentProgram
}
else{
#no program led was on
if($CurrentProgram -gt 0 -And $CurrentProgram -lt 7){
#turn on new program led
$Global:xkeys.SendData($Global:xkeysActiveDevice,32+($CurrentProgram*2)-2,1)
$Global:Program = $CurrentProgram
}
}
#Preview
$CurrentPreview = $Global:activeME.Preview
if($Global:Preview -ne $CurrentPreview){
if($Global:Debug -eq $true){write-host "Preview changed from $($Global:Preview) to $($CurrentPreview) "}
if($Global:Preview -gt 0 -And $Global:Preview -lt 7){
#turn off current LED
$xkeys.SendData($Global:xkeysActiveDevice,($Global:Preview*2)-1,0)
if($CurrentPreview -gt 0 -And $CurrentPreview -lt 7){
#turn on new Preview led
$Global:xkeys.SendData($Global:xkeysActiveDevice,($CurrentPreview*2)-1,1)
}
}
if($CurrentPreview -ne 3010){$Global:xkeys.SendData($Global:xkeysActiveDevice,12,0)} # MP1
if($CurrentPreview -ne 3020){$Global:xkeys.SendData($Global:xkeysActiveDevice,14,0)} # MP2
if($CurrentPreview -ne 2001){$Global:xkeys.SendData($Global:xkeysActiveDevice,16,0)} # Color 1
if($CurrentPreview -ne 2002){$Global:xkeys.SendData($Global:xkeysActiveDevice,18,0)} # Color 2
$Global:Preview = $CurrentPreview
}
else{
#no program led was on
if($CurrentPreview -gt 0 -And $CurrentPreview -lt 7){
#turn on new preview led
$Global:xkeys.SendData($Global:xkeysActiveDevice,($CurrentPreview*2)-1,1)
$Global:Preview = $CurrentPreview
}
}
if($Global:loopColor -eq $true){
$Global:ColorGen2.Hue =$Global:hue
$Global:hue++
if($Global:hue -eq 357){$Global:hue=1}
}
if($LoopInputs -eq $true){
if($Global:TimeOnInput -eq 10){
#get next input
$Global:InputCurrent++
if($Global:InputCurrent -gt $Global:InputList.Count){
$Global:InputCurrent=1
}
$Global:activeME.Preview = $Global:InputList[$Global:InputCurrent]
$Global:activeME.Cut()
$Global:TimeOnInput=0
}
$Global:TimeOnInput++
}
#Set transition LED
$METransitionStyle = $Global:activeME.TransitionStyle.ToString()
if ($METransitionStyle -ne $Global:CurrentTransition){
switch ($METransitionStyle){
bmdSwitcherTransitionStyleMix{
$Global:xkeys.SendData($Global:xkeysActiveDevice,26,0)
$Global:xkeys.SendData($Global:xkeysActiveDevice,28,0)
$Global:CurrentTransition = "bmdSwitcherTransitionStyleMix"
}
bmdSwitcherTransitionStyleDIP{
$Global:xkeys.SendData($Global:xkeysActiveDevice,26,0)
$Global:xkeys.SendData($Global:xkeysActiveDevice,28,1)
$Global:CurrentTransition = "bmdSwitcherTransitionStyleDIP"
}
bmdSwitcherTransitionStyleWipe{
$Global:xkeys.SendData($Global:xkeysActiveDevice,26,1)
$Global:xkeys.SendData($Global:xkeysActiveDevice,28,0)
$Global:CurrentTransition = "bmdSwitcherTransitionStyleWipe"
}
}
}
If ($Global:MacroStatus -ne $atem.MacroStatus()){
if($atem.MacroStatus() -eq "bmdSwitcherMacroRunStatusWaitingForUser"){
$Global:xkeys.SendData($Global:xkeysActiveDevice,21,1)
$Global:MacroStatus = "bmdSwitcherMacroRunStatusWaitingForUser"
}
}
}
Unregister-Event $sourceIdentifier -ErrorAction SilentlyContinue
$timer.stop()
$start = Register-ObjectEvent -InputObject $timer -SourceIdentifier $sourceIdentifier -EventName Elapsed -Action $timeraction
$timer.start()
#endregion
function ToggleActiveME(){
if($Global:activeME -eq $me1){
$Global:activeME = $me2;
$Global:xkeys.SendData($Global:xkeysActiveDevice,95,1);
$Global:xkeys.SendData($Global:xkeysActiveDevice,15,0)
}
else {
$Global:activeME = $me1;
$Global:xkeys.SendData($Global:xkeysActiveDevice,15,1)
$Global:xkeys.SendData($Global:xkeysActiveDevice,95,0)
}
}
function changeTransition($newTransitionStyle){
switch($Global:activeME.TransitionStyle){
bmdSwitcherTransitionStyleMix{
$Global:activeME.TransitionStyle=$newTransitionStyle
break;
}
bmdSwitcherTransitionStyleDIP{
if($newTransitionStyle="Dip"){
$Global:activeME.TransitionStyle="Mix"
}
else{
$Global:activeME.TransitionStyle="Dip"
}
break;
}
bmdSwitcherTransitionStyleWipe{
if($newTransitionStyle="Wipe"){
$Global:activeME.TransitionStyle="Mix"
}
else{
$Global:activeME.TransitionStyle="Wipe"
}
break;
}
}
}
function keypad([int]$number){
switch($Global:KeypadMode){
Macro{
Write-host "Running Macro $($number)"
$atem.RunMacro($number-1)
$Global:KeypadMode=""
$Global:xkeys.SendData(1,53,0)
break;
}
MP1{
$MP1.MediaStill = $number-1
$Global:KeypadMode=""
if ($Global:Program -eq 3010){$Global:xkeys.SendData(1,44,1)}
elseif ($Global:Preview -eq 3010){$Global:xkeys.SendData(1,12,1)}
else{$Global:xkeys.SendData(1,44,0);$Global:xkeys.SendData(1,12,1)}
}
MP2{
$MP2.MediaStill = $number-1
$Global:KeypadMode=""
if ($Global:Program -eq 3020){$Global:xkeys.SendData(1,46,1)}
elseif ($Global:Preview -eq 3010){$Global:xkeys.SendData(1,14,1)}
else{$Global:xkeys.SendData(1,46,0);$Global:xkeys.SendData(1,14,1)}
}
Aux1{
if($aux.Count -gt 0){$aux[0].Input = $number;}
$Global:xkeys.SendData(1,78,0)
}
Aux2{
if($aux.Count -gt 1){$aux[1].Input = $number;}
$Global:xkeys.SendData(1,77,0)
}
Aux3{
if($aux.Count -gt 0){$aux[2].Input = $number;}
$Global:xkeys.SendData(1,76,0)
}
Color{
switch($number){
1{$Global:ColorGen1.Hue=0;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=.5} #Red}
2{$Global:ColorGen1.Hue=51;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=.5} #Orange
3{$Global:ColorGen1.Hue=103;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=.5} #Yellow
4{$Global:ColorGen1.Hue=154;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=.5} #Green
5{$Global:ColorGen1.Hue=206;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=.5} #Blue
6{$Global:ColorGen1.Hue=257;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=.5} #Indego
7{$Global:ColorGen1.Hue=309;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=.5} #Volot
8{$Global:ColorGen1.Hue=0;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=0} #Black
9{$Global:ColorGen1.Hue=229;$Global:ColorGen1.Saturation=.16;$Global:ColorGen1.Luma=.59} #Grey
10{$Global:ColorGen1.Hue=0;$Global:ColorGen1.Saturation=1;$Global:ColorGen1.Luma=1} #White
}
$Global:KeypadMode=""
$Global:xkeys.SendData($Global:xkeysActiveDevice,16,1)
}
}
}
#$activeME.FadeToBlack()
function cleanup(){
Unregister-Event $sourceIdentifier -ErrorAction SilentlyContinue
$timer.stop()
Unregister-Event -SourceIdentifier KeyPressed -ErrorAction SilentlyContinue
}
#
#This file goes in your documents\WindowsPowerShell directory and will load and run the main.ps1 file (update path depending on where you place that file)
$host.ui.RawUI.WindowTitle = "Video Integrated Scripting Environment (VISE)"
Import-Module PsISEProjectExplorer
$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Edit X-keys config",{$file = "c:\vise\xkeysconfigeditor.exe" -f $pwd;Invoke-Expression $file},"Ctrl+Alt+X")
#display current variables
function GetValues
{
$content = $psISE.CurrentFile.Editor.Text
$tokens = [System.Management.Automation.PsParser]::Tokenize($content, [ref] $null) |? {$_.Type -eq 'Variable'} | Sort Content -Unique
foreach ($t in $tokens)
{
$prop = @{
Name = $t.Content
Value = Get-Variable -Name $($t.Content) -ValueOnly -ErrorAction SilentlyContinue
}
New-Object -TypeName PSObject -Property $prop | Select Name, Value
}
}
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add('Show values',{GetValues},'CTRL+SHIFT+V') | Out-Null
function PSEdit {
[CmdletBinding()]
param([Parameter(Mandatory=$true,ValueFromPipeline=$true)]$filename)
Process{
if(test-path $filename -PathType Leaf) {
$file = Get-ChildItem $filename
if($file.PSProvider.Name -eq “Filesystem”) {
Start-Process PowerShell_ISE -ArgumentList $file
}
else {
Write-Error “Wrong PSProvider: $($File.PSProvider.Name)”
}
}
else {
write-error “Bad path: $filename”
}
}
}
PSEdit "C:\VISE\Main.ps1"
Start-Sleep 2
$runthecode = get-content "C:\VISE\Main.ps1" -raw
Invoke-Expression $runthecode
{
"keys": [
{
"Type": "Script",
"KeyID": 0,
"Command": " ",
"Script": "$ActiveME.Program=1",
"Caption": "Prog 1",
"Description": "CUT"
},
{
"Type": "Script",
"KeyID": 1,
"Command": " ",
"Script": "if($Global:KeypadMode -eq \"\"){$ActiveME.Preview=1} else {keypad 1}",
"Caption": "Prev 1",
"Description": "ME1 Auto Transition"
},
{
"Type": "Script",
"KeyID": 2,
"Command": " ",
"Script": "$ActiveME.Program=2",
"Caption": "Prog 2",
"Description": "ME1 Auto Transition"
},
{
"Type": "Script",
"KeyID": 3,
"Command": " ",
"Script": "if($Global:KeypadMode -eq \"\"){$ActiveME.Preview=2} else {keypad 2}",
"Caption": "Prev 2",
"Description": "Fade to black"
},
{
"Type": "Script",
"KeyID": 4,
"Command": " ",
"Script": "$ActiveME.Program=3",
"Caption": "Prog 3",
"Description": "DSK 2 On-air"
},
{
"Type": "Script",
"KeyID": 5,
"Command": " ",
"Script": "if($Global:KeypadMode -eq \"\"){$ActiveME.Preview=3} else {keypad 3}",
"Caption": "Prev 3",
"Description": "Key 2 Next Transition"
},
{
"Type": "Script",
"KeyID": 6,
"Command": " ",
"Script": "$ActiveME.Program=4",
"Caption": "Prog 4",
"Description": "Key 2 On-Air"
},
{
"Type": "Script",
"KeyID": 7,
"Command": " ",
"Script": "if($Global:KeypadMode -eq\"\"){$ActiveME.Preview=4} else {keypad 4}",
"Caption": "Prev 4",
"Description": "Reset to default state"
},
{
"Type": "Script",
"KeyID": 8,
"Command": " ",
"Script": "$ActiveME.Program=5",
"Caption": "Prog 5",
"Description": "Set transition type to Wipe"
},
{
"Type": "Script",
"KeyID": 9,
"Command": " ",
"Script": "if($Global:KeypadMode -eq\"\"){$ActiveME.Preview=5} else {keypad 5}",
"Caption": "Prev 5",
"Description": "Set transition type to DIP"
},
{
"Type": "Script",
"KeyID": 10,
"Command": " ",
"Script": "$ActiveME.Program=6",
"Caption": "Prog 6",
"Description": "Set transition type to DIP"
},
{
"Type": "Script",
"KeyID": 11,
"Command": " ",
"Script": "if($Global:KeypadMode -eq \"\"){$ActiveME.Preview=6} else {keypad 6}",
"Caption": "Prev 6",
"Description": "Side screens on current Preview input"
},
{
"Type": "Script",
"KeyID": 12,
"Command": " ",
"Script": "if($ActiveME.Preview -eq 3010){$Global:KeypadMode=\"MP1\";$Global:xkeys.SendData($Global:xkeysActiveDevice,44,2);$Global:Preview=3010} elseif($ActiveME.Program -eq 3010){$Global:KeypadMode=\"MP1\";$Global:xkeys.SendData($Global:xkeysActiveDevice,44,2);$Global:Program=3010} else {$Global:xkeys.SendData($Global:xkeysActiveDevice,12,1);$ActiveME.Preview=3010}",
"Caption": "Key 7",
"Description": "DSK 1 On-air"
},
{
"Type": "Script",
"KeyID": 13,
"Command": " ",
"Script": "keypad 7",
"Caption": "Key 7",
"Description": null
},
{
"Type": "Script",
"KeyID": 14,
"Command": " ",
"Script": "if($ActiveME.Preview -eq 3020){$Global:KeypadMode=\"MP2\";$Global:xkeys.SendData($Global:xkeysActiveDevice,14,2);$Global:Preview=3020} elseif($ActiveME.Program -eq 3020){$Global:KeypadMode=\"MP2\";$Global:xkeys.SendData($Global:xkeysActiveDevice,46,2);$Global:Program=3020} else {$Global:xkeys.SendData($Global:xkeysActiveDevice,14,1);$ActiveME.Preview=3020}",
"Caption": "MP2",
"Description": null
},
{
"Type": "Script",
"KeyID": 15,
"Command": " ",
"Script": "keypad 8",
"Caption": "Key 8",
"Description": "If ATEM is 2 ME then switch buttons to control other ME"
},
{
"Type": "Script",
"KeyID": 16,
"Command": " ",
"Script": "if($Global:ActiveME.Preview -ne 2001){$Global:ActiveME.Preview = 2001;$Global:xkeys.SendData($Global:xkeysActiveDevice,16,1)} else {$Global:KeypadMode=\"Color\";$Global:xkeys.SendData($Global:xkeysActiveDevice,16,2)}",
"Caption": "MP2",
"Description": null
},
{
"Type": "Script",
"KeyID": 17,
"Command": " ",
"Script": "keypad 9",
"Caption": "Key 9",
"Description": null
},
{
"Type": "Script",
"KeyID": 18,
"Command": " ",
"Script": "if($global:loopColor -eq $true){$global:loopColor = $false;$Global:xkeys.SendData($Global:xkeysActiveDevice,18,0)} else {$global:loopColor = $true;$Global:xkeys.SendData($Global:xkeysActiveDevice,18,1);$ActiveME.Preview=2002}",
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 19,
"Command": " ",
"Script": "keypad 10",
"Caption": "Key 10",
"Description": null
},
{
"Type": "Script",
"KeyID": 20,
"Command": " ",
"Script": null,
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 21,
"Command": " ",
"Script": "if( $Global:MacroStatus -eq \"bmdSwitcherMacroRunStatusWaitingForUser\"){$atem.MacroResume();$Global:xkeys.SendData($Global:xkeysActiveDevice,21,0)} else {$Global:xkeys.SendData($Global:xkeysActiveDevice,53,2);$Global:KeypadMode=\"Macro\"}",
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 22,
"Command": " ",
"Script": null,
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 23,
"Command": " ",
"Script": "if($global:LoopInputs -eq $true){$global:LoopInputs = $false;$Global:xkeys.SendData($Global:xkeysActiveDevice,13,0)} else {$global:LoopInputs = $true;$Global:xkeys.SendData($Global:xkeysActiveDevice,13,1)}",
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 24,
"Command": " ",
"Script": "$DSK[0].OnAir = DSKToggle 1",
"Caption": "Preview AV",
"Description": "Set Preview bus to input 0"
},
{
"Type": "Script",
"KeyID": 25,
"Command": " ",
"Script": null,
"Caption": "DSK1",
"Description": null
},
{
"Type": "Script",
"KeyID": 26,
"Command": " ",
"Script": "changeTransition \"Wipe\"",
"Caption": "Wipe",
"Description": null
},
{
"Type": "Script",
"KeyID": 27,
"Command": " ",
"Script": null,
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 28,
"Command": " ",
"Script": "changeTransition \"Dip\"",
"Caption": "DIP",
"Description": null
},
{
"Type": "Script",
"KeyID": 29,
"Command": " ",
"Script": "$ActiveME.AutoTransition()",
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 30,
"Command": " ",
"Script": "$ActiveME.FadeToblack()",
"Caption": null,
"Description": null
},
{
"Type": "Script",
"KeyID": 31,
"Command": " ",
"Script": "$ActiveME.Cut()",
"Caption": null,
"Description": null
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment