Guest User

Untitled

a guest
Apr 4th, 2025
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.46 KB | None | 0 0
  1. import obspython as obs
  2.  
  3. # Required by advss helpers
  4. import threading
  5. from typing import NamedTuple
  6.  
  7. # Required for the custom action
  8. import subprocess
  9.  
  10. ###############################################################################
  11.  
  12. # Define the settings available for the user for this action type
  13. def get_action_properties():
  14. props = obs.obs_properties_create()
  15. obs.obs_properties_add_text(props, "script_to_run", "Script", obs.OBS_TEXT_MULTILINE)
  16. return props
  17.  
  18.  
  19. # Set default values for each setting
  20. def get_action_defaults():
  21. default_settings = obs.obs_data_create()
  22. obs.obs_data_set_default_string(default_settings, "script_to_run", "echo \"hello world!\"")
  23. return default_settings
  24.  
  25.  
  26. # The settings for each instance of this action the will be passed in the
  27. # "data" argument
  28. def run_cmd_action(data, instance_id):
  29. script = obs.obs_data_get_string(data, "script_to_run")
  30. # Build a single line command to run
  31. command = " & ".join(script.splitlines())
  32. result = subprocess.run(command, shell=True, capture_output=True, text=True)
  33. obs.script_log(obs.LOG_INFO, result.stdout)
  34. obs.script_log(obs.LOG_INFO, result.stderr)
  35.  
  36. ###############################################################################
  37.  
  38.  
  39. def script_load(settings):
  40. # Register the custom action
  41. advss_register_action(
  42. "CMD",
  43. run_cmd_action,
  44. get_action_properties,
  45. get_action_defaults(),
  46. )
  47.  
  48. def script_unload():
  49. advss_deregister_action("CMD")
  50.  
  51.  
  52. ###############################################################################
  53.  
  54. # Advanced Scene Switcher helper functions below:
  55. # Usually you should not have to modify this code.
  56. # Simply copy paste it into your scripts.
  57.  
  58.  
  59. ###############################################################################
  60. # Actions
  61. ###############################################################################
  62.  
  63.  
  64. # The advss_register_action() function is used to register custom actions
  65. # It takes the following arguments:
  66. # 1. The name of the new action type.
  67. # 2. The function callback which should run when the action is executed.
  68. # 3. The optional function callback which return the properties to display the
  69. # settings of this action type.
  70. # 4. The optional default_settings pointer used to set the default settings of
  71. # newly created actions.
  72. # The pointer must not be freed within this script.
  73. # 5. The optional list of macro properties associated with this action type.
  74. # You can set values using advss_set_temp_var_value().
  75.  
  76.  
  77. def advss_register_action(
  78. name,
  79. callback,
  80. get_properties=None,
  81. default_settings=None,
  82. macro_properties=None,
  83. ):
  84. advss_register_segment_type(
  85. True, name, callback, get_properties, default_settings, macro_properties
  86. )
  87.  
  88.  
  89. def advss_deregister_action(name):
  90. advss_deregister_segment(True, name)
  91.  
  92.  
  93. ###############################################################################
  94. # Conditions
  95. ###############################################################################
  96.  
  97.  
  98. # The advss_register_condition() function is used to register custom conditions
  99. # It takes the following arguments:
  100. # 1. The name of the new condition type.
  101. # 2. The function callback which should run when the condition is executed.
  102. # 3. The optional function callback which return the properties to display the
  103. # settings of this condition type.
  104. # 4. The optional default_settings pointer used to set the default settings of
  105. # newly created condition.
  106. # The pointer must not be freed within this script.
  107. # 5. The optional list of macro properties associated with this condition type.
  108. # You can set values using advss_set_temp_var_value().
  109. def advss_register_condition(
  110. name,
  111. callback,
  112. get_properties=None,
  113. default_settings=None,
  114. macro_properties=None,
  115. ):
  116. advss_register_segment_type(
  117. False, name, callback, get_properties, default_settings, macro_properties
  118. )
  119.  
  120.  
  121. def advss_deregister_condition(name):
  122. advss_deregister_segment(False, name)
  123.  
  124.  
  125. ###############################################################################
  126. # (De)register helpers
  127. ###############################################################################
  128.  
  129.  
  130. def advss_register_segment_type(
  131. is_action, name, callback, get_properties, default_settings, macro_properties
  132. ):
  133. proc_handler = obs.obs_get_proc_handler()
  134. data = obs.calldata_create()
  135.  
  136. obs.calldata_set_string(data, "name", name)
  137. obs.calldata_set_ptr(data, "default_settings", default_settings)
  138.  
  139. register_proc = (
  140. "advss_register_script_action"
  141. if is_action
  142. else "advss_register_script_condition"
  143. )
  144. obs.proc_handler_call(proc_handler, register_proc, data)
  145.  
  146. success = obs.calldata_bool(data, "success")
  147. if success is False:
  148. segment_type = "action" if is_action else "condition"
  149. log_msg = f'failed to register custom {segment_type} "{name}"'
  150. obs.script_log(obs.LOG_WARNING, log_msg)
  151. obs.calldata_destroy(data)
  152. return
  153.  
  154. # Run in separate thread to avoid blocking main OBS signal handler.
  155. # Operation completion will be indicated via signal completion_signal_name.
  156. def run_helper(data):
  157. completion_signal_name = obs.calldata_string(data, "completion_signal_name")
  158. completion_id = obs.calldata_int(data, "completion_id")
  159. instance_id = obs.calldata_int(data, "instance_id")
  160.  
  161. def thread_func(settings):
  162. settings = obs.obs_data_create_from_json(
  163. obs.calldata_string(data, "settings")
  164. )
  165. callback_result = callback(settings, instance_id)
  166. if is_action:
  167. callback_result = True
  168.  
  169. reply_data = obs.calldata_create()
  170. obs.calldata_set_int(reply_data, "completion_id", completion_id)
  171. obs.calldata_set_bool(reply_data, "result", callback_result)
  172. signal_handler = obs.obs_get_signal_handler()
  173. obs.signal_handler_signal(
  174. signal_handler, completion_signal_name, reply_data
  175. )
  176. obs.obs_data_release(settings)
  177. obs.calldata_destroy(reply_data)
  178.  
  179. threading.Thread(target=thread_func, args={data}).start()
  180.  
  181. def properties_helper(data):
  182. if get_properties is not None:
  183. properties = get_properties()
  184. else:
  185. properties = None
  186. obs.calldata_set_ptr(data, "properties", properties)
  187.  
  188. # Helper to register the macro properties every time a new instance of the
  189. # macro segment is created.
  190. def register_temp_vars_helper(data):
  191. id = obs.calldata_int(data, "instance_id")
  192. proc_handler = obs.obs_get_proc_handler()
  193. data = obs.calldata_create()
  194. for prop in macro_properties:
  195. obs.calldata_set_string(data, "temp_var_id", prop.id)
  196. obs.calldata_set_string(data, "temp_var_name", prop.name)
  197. obs.calldata_set_string(data, "temp_var_help", prop.description)
  198. obs.calldata_set_int(data, "instance_id", id)
  199.  
  200. obs.proc_handler_call(proc_handler, "advss_register_temp_var", data)
  201.  
  202. success = obs.calldata_bool(data, "success")
  203. if success is False:
  204. segment_type = "action" if is_action else "condition"
  205. log_msg = f'failed to register macro property {prop.id} for {segment_type} "{name}"'
  206. obs.script_log(obs.LOG_WARNING, log_msg)
  207. obs.calldata_destroy(data)
  208.  
  209. trigger_signal_name = obs.calldata_string(data, "trigger_signal_name")
  210. property_signal_name = obs.calldata_string(data, "properties_signal_name")
  211. new_instance_signal_name = obs.calldata_string(data, "new_instance_signal_name")
  212.  
  213. signal_handler = obs.obs_get_signal_handler()
  214. obs.signal_handler_connect(signal_handler, trigger_signal_name, run_helper)
  215. obs.signal_handler_connect(signal_handler, property_signal_name, properties_helper)
  216. if isinstance(macro_properties, list):
  217. obs.signal_handler_connect(
  218. signal_handler, new_instance_signal_name, register_temp_vars_helper
  219. )
  220. obs.calldata_destroy(data)
  221.  
  222.  
  223. def advss_deregister_segment(is_action, name):
  224. proc_handler = obs.obs_get_proc_handler()
  225. data = obs.calldata_create()
  226.  
  227. obs.calldata_set_string(data, "name", name)
  228.  
  229. deregister_proc = (
  230. "advss_deregister_script_action"
  231. if is_action
  232. else "advss_deregister_script_condition"
  233. )
  234.  
  235. obs.proc_handler_call(proc_handler, deregister_proc, data)
  236.  
  237. success = obs.calldata_bool(data, "success")
  238. if success is False:
  239. segment_type = "action" if is_action else "condition"
  240. log_msg = f'failed to deregister custom {segment_type} "{name}"'
  241. obs.script_log(obs.LOG_WARNING, log_msg)
  242.  
  243. obs.calldata_destroy(data)
  244.  
  245.  
  246. ###############################################################################
  247. # Macro properties (temporary variables)
  248. ###############################################################################
  249.  
  250.  
  251. class MacroProperty(NamedTuple):
  252. id: str # Internal identifier used by advss_set_temp_var_value()
  253. name: str # User facing name
  254. description: str # User facing description
  255.  
  256.  
  257. def advss_set_temp_var_value(temp_var_id, value, instance_id):
  258. proc_handler = obs.obs_get_proc_handler()
  259. data = obs.calldata_create()
  260.  
  261. obs.calldata_set_string(data, "temp_var_id", str(temp_var_id))
  262. obs.calldata_set_string(data, "value", str(value))
  263. obs.calldata_set_int(data, "instance_id", int(instance_id))
  264. obs.proc_handler_call(proc_handler, "advss_set_temp_var_value", data)
  265.  
  266. success = obs.calldata_bool(data, "success")
  267. if success is False:
  268. obs.script_log(
  269. obs.LOG_WARNING, f'failed to set value for macro property "{temp_var_id}"'
  270. )
  271.  
  272. obs.calldata_destroy(data)
  273.  
  274.  
  275. ###############################################################################
  276. # Variables
  277. ###############################################################################
  278.  
  279.  
  280. # The advss_get_variable_value() function can be used to query the value of a
  281. # variable with a given name.
  282. # None is returned in case the variable does not exist.
  283. def advss_get_variable_value(name):
  284. proc_handler = obs.obs_get_proc_handler()
  285. data = obs.calldata_create()
  286.  
  287. obs.calldata_set_string(data, "name", name)
  288. obs.proc_handler_call(proc_handler, "advss_get_variable_value", data)
  289.  
  290. success = obs.calldata_bool(data, "success")
  291. if success is False:
  292. obs.script_log(obs.LOG_WARNING, f'failed to get value for variable "{name}"')
  293. obs.calldata_destroy(data)
  294. return None
  295.  
  296. value = obs.calldata_string(data, "value")
  297.  
  298. obs.calldata_destroy(data)
  299. return value
  300.  
  301.  
  302. # The advss_set_variable_value() function can be used to set the value of a
  303. # variable with a given name.
  304. # True is returned if the operation was successful.
  305. def advss_set_variable_value(name, value):
  306. proc_handler = obs.obs_get_proc_handler()
  307. data = obs.calldata_create()
  308.  
  309. obs.calldata_set_string(data, "name", name)
  310. obs.calldata_set_string(data, "value", value)
  311. obs.proc_handler_call(proc_handler, "advss_set_variable_value", data)
  312.  
  313. success = obs.calldata_bool(data, "success")
  314. if success is False:
  315. obs.script_log(obs.LOG_WARNING, f'failed to set value for variable "{name}"')
  316.  
  317. obs.calldata_destroy(data)
  318. return success
  319.  
Advertisement
Add Comment
Please, Sign In to add comment