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
|
import os
import subprocess
from sys import platform
import time
import pathlib
import psutil
from renardo.SCFilesHandling import SC_USER_CONFIG_DIR
class PulsarNotFoundError(Exception):
pass
class PulsarAlreadyRunning(Exception):
pass
class PulsarInstance:
def __init__(self):
self.pulsar_process = None
self.pulsar_ready = None
if platform == "win32":
# if chocolatey
pulsar_appdata_path = pathlib.Path(os.getenv('LOCALAPPDATA')) / 'Programs' / 'Pulsar' / 'Pulsar.exe'
pulsar_c_path = pathlib.WindowsPath(os.getenv('ProgramFiles')) / 'Pulsar' / 'Pulsar.exe'
if pulsar_appdata_path.exists():
self.pulsar_exec = [str(pulsar_appdata_path)]
self.check_exec = [str(pulsar_appdata_path),'--version']
elif pulsar_c_path.exists():
self.pulsar_exec = [str(pulsar_c_path)]
self.check_exec = [str(pulsar_c_path),'--version']
else:
self.pulsar_ready = False
elif platform == "Darwin":
pulsar_path = pathlib.Path("/Applications" / "Pulsar.app")
self.pulsar_exec = ['open', str(pulsar_path)]
self.check_exec = ['open', str(pulsar_path), "--version"]
else:
self.pulsar_exec = ["pulsar"]
self.check_exec = ["pulsar", "--version"]
self.is_pulsar_ready()
def is_pulsar_ready(self):
if self.pulsar_ready is None:
try:
completed_process = subprocess.run(self.check_exec, capture_output=True)
self.pulsar_ready = completed_process.returncode==0
except:
self.pulsar_ready = False
return self.pulsar_ready
def start_pulsar_subprocess(self):
try:
if self.is_pulsar_running():
raise PulsarAlreadyRunning()
self.pulsar_process = subprocess.Popen(
args=self.pulsar_exec,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
)
return "Pulsar started"
except Exception as e:
return f"Pulsar not started: {e}"
def read_stdout_line(self):
if self.pulsar_process.returncode is None:
return self.pulsar_process.stdout.readline().decode("utf-8")
def read_stderr_line(self):
if self.pulsar_process.returncode is None:
return self.pulsar_process.stderr.readline().decode("utf-8")
def evaluate_sclang_code(self, code_string):
raw = code_string.encode("utf-8") + b"\x1b"
self.pulsar_process.stdin.write(raw)
self.pulsar_process.stdin.flush()
# TODO : find a way to consistently stop sclang and scsynth when renardo stops/dies
# TODO : find a way to name/tag the sclang/synth processes with name renardo to find it better
# TODO : Use name renardo for scsynth audio server (for example with JACK Driver)
def __del__(self):
pass
# self.popen.kill() # TODO: fix that the destructor is not called
# need to clarify the launch and close process of foxdot/renardo !
# self.popen.wait()
def is_pulsar_running(self):
running = False
for process in psutil.process_iter():
if 'pulsar' in process.name().lower():
running = True
return running
|