summaryrefslogtreecommitdiff
path: root/crystal/bullshit.cr
blob: 9feb24db4f49049181dfb062145c336d93e5f10e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
require "obswebsocket"
require "pretty_print"
require "math"

STDOUT.sync = true
STDOUT.flush_on_newline = true

struct Nil
  def as_s?
    self
  end
end

settings = Hash(String, String).new

settings["configdir"] = Path.home./("/.config/bungmobott/").to_s
settings["statedir"]  = Path.home./("/.local/state/bungmobott/").to_s

if ENV["LOCALAPPDATA"]?
  settings["configdir"] = Path.windows( ENV["LOCALAPPDATA"] + "\\bungmobott\\" ).to_s
  settings["statedir"] = Path.windows( ENV["LOCALAPPDATA"] + "\\bungmobott\\state\\" ).to_s
end

settings["tempdir"] = "/tmp/bungmobott/"
ENV["TEMP"]? && ( settings["tempdir"] = "#{ENV["TEMP"]}\\bungmobott\\" )

ENV["XDG_CONFIG_HOME"]? && ( settings["configdir"] = ENV["XDG_CONFIG_HOME"] + "/bungmobott/" )
#ENV["XDG_DATA_HOME"]? && ( settings["datadir"] = ENV["XDG_DATA_HOME"] ) # unused?
ENV["XDG_STATE_HOME"]? && ( settings["statedir"] = ENV["XDG_STATE_HOME"] + "/bungmobott/" )

Dir.mkdir_p( settings["configdir"] )
Dir.mkdir_p( settings["statedir"] )
Dir.mkdir_p( settings["tempdir"] )

settings["home"] = Path.home.to_s
regextwitchuser = /^[0-9a-zA-Z_]+$/

obs = OBS::WebSocket.new( "ws://127.0.0.1:4455/" )
directions = Hash( String, Float64 ).new

# OBS event thread
spawn do
  evchan = Channel( JSON::Any ).new
  obs.eventsub_add( evchan )
  while json = evchan.receive
    # A Fiber.yield occurs after this to make sure "json" doesn't get overwritten before we can use it.
    spawn do
      d = json # Copy *immediately*
      case d["eventType"].as_s
      when "SceneItemTransformChanged"
        edata = d["eventData"]
        puts "test 1"
        scenelist = obs.scenes[edata["sceneName"].as_s]
        puts "test 2"
        sceneitem = scenelist[edata["sceneItemId"].as_i64]
        puts "test 3"
        t = edata["sceneItemTransform"]
        if ( direction = directions[sceneitem.name]? )
          spx = t["positionX"   ].as_f.to_i64
          spy = t["positionY"   ].as_f.to_i64
          sdx = t["sourceHeight"].as_f.to_i64
          sdy = t["sourceWidth" ].as_f.to_i64
          bx = obs.video.to_h["baseWidth" ].as(Int64 | Float64).to_i64
          by = obs.video.to_h["baseHeight"].as(Int64 | Float64).to_i64
          abx = bx - sdx
          aby = by - sdy
          ratio = Math.tan(direction)
          spxr = (aby/2 * ratio).abs
          if spxr > abx/2
            spxr = abx/2
            spyr = abx/2 * ratio
          elsif ratio > 0
            spyr = abx/2
          else # ratio < 0
            spyr = abx/2 * -1
          end
          if    ( direction >= 0  ) && ( direction <= Math::PI   )
            nspx = spxr
          else # ( direction >= Math::PI ) && ( direction <= 2*Math::PI )
            nspx = ( spxr * -1 )
          end
            nspx = nspx - sdx
            nspy = spyr - sdy
          unless ( spx == nspx && spy == nspy )
            sceneitem.transform( { "positionX" => nspx, "positionY" => nspy } )
          end
        end
      end
    end
    Fiber.yield
  end
end

def obsrandommediaenable( obs : OBS::WebSocket, siname : String )
  if ( Random.rand(3) < 2 )
    obs.scenes.current.metascene[siname][0].enable!
  else
    randsiname = obs.scenes.current.metascene.keys.select( /^#{siname}/ ).sample( 1 )[0]
    obs.scenes.current.metascene[randsiname][0].enable!
  end
end

name=ARGV[0].sub( /.+\//, "" ).sub( /\..+/, "" )

def obsmediacreate( obs : OBS::WebSocket, sname : String, iname, path : String )
  iname = "medialoop-bullshit-#{iname}"
  isettings = Hash( String, String | Bool | Int64 | Float64 ){
    "advanced" => true,
    "clear_on_media_end" => true,
    "color_range" => 0.to_i64,
    "is_local_file" => true,
    "looping" => true,
    "restart_on_activate" => true,
    "local_file" => path,
  }
  response = obs.scenes[sname].createinput( iname, "ffmpeg_source", isettings )
  # Skip object model stuff and configure the SceneItem as fast as we possibly can
  if ( rdata = response["responseData"]? ) && ( goodtransform = obs.sources.last_known_real_transform?( iname ) )
    siid = rdata["sceneItemId"].as_i64
    ENV["DISTANCE"] # percent
    ENV["DIRECTION"] # degrees
    ENV["SIZE"] # width\nheight
    ENV["COLORMASK"] # color/RGB(A) html color code
#    obs.send_sync( OBS.req( "SetSceneItemTransform", JSON.parse( { "sceneName" => sname, "sceneItemId" => siid, "sceneItemTransform" => { "positionX" => goodtransform.to_h["positionX"], "positionY" => goodtransform.to_h["positionY"] } }.to_json ) ) )
  end
  if ( colormask = ENV["COLORMASK"].to_u32 )
    obs.send_sync( OBS.req( "CreateSourceFilter", JSON.parse( { "sourceName" => iname, "filterName" => "chromakey", "filterKind" => "chroma_key_filter_v2", "filterSettings" => { "key_color_type" => "custom", "key_color" => colormask, "smoothness" => 10, "similarity" => "1" } }.to_json ) ) )
    #obs.send_sync( OBS.req( "CreateSourceFilter", JSON.parse( { "sourceName" => iname, "filterName" => "colorkey", "filterKind" => "color_key_filter_v2", "filterSettings" => { "key_color_type" => "custom", "key_color" => colormask, "smoothness" => 1000 } }.to_json ) ) )
  end
end

# white: 4294967296

if ( direction = ENV["DIRECTION"].to_u16 )
  directions[name] = Math::PI/180*direction
else
  directions[name] = Math::PI/180*rand(360)
end

obsmediacreate( obs, "meta-bullshit", name, ARGV[0] )

sleep 2
Fiber.yield