RAM2118 commited on
Commit
8335f9f
·
verified ·
1 Parent(s): 24a3c7f

Upload Source/Plugin/HelperConnection.cpp

Browse files
Files changed (1) hide show
  1. Source/Plugin/HelperConnection.cpp +41 -28
Source/Plugin/HelperConnection.cpp CHANGED
@@ -17,7 +17,6 @@ using json = nlohmann::json;
17
  HelperConnection::HelperConnection()
18
  {
19
  myPid = getpid();
20
- // Ignore SIGPIPE globally (macOS doesn't have MSG_NOSIGNAL)
21
  signal(SIGPIPE, SIG_IGN);
22
  }
23
 
@@ -30,7 +29,6 @@ bool HelperConnection::spawnHelper()
30
  {
31
  killHelper();
32
 
33
- // 1. Create shared memory
34
  auto shmName = IPC::getShmName(myPid);
35
  if (!sharedAudio.create(shmName))
36
  {
@@ -38,7 +36,6 @@ bool HelperConnection::spawnHelper()
38
  return false;
39
  }
40
 
41
- // 2. Create semaphores
42
  if (!inputSem.create(IPC::getInputSemName(myPid)) ||
43
  !outputSem.create(IPC::getOutputSemName(myPid)))
44
  {
@@ -46,7 +43,6 @@ bool HelperConnection::spawnHelper()
46
  return false;
47
  }
48
 
49
- // 3. Create Unix domain socket (server side)
50
  auto socketPath = IPC::getSocketPath(myPid);
51
  unlink(socketPath.c_str());
52
 
@@ -65,37 +61,42 @@ bool HelperConnection::spawnHelper()
65
  if (bind(serverSocketFd, (struct sockaddr*)&addr, sizeof(addr)) < 0 ||
66
  listen(serverSocketFd, 1) < 0)
67
  {
68
- DBG("HelperConnection: Failed to bind/listen socket");
69
  close(serverSocketFd);
70
  serverSocketFd = -1;
71
  return false;
72
  }
73
 
74
- // 4. Find helper binary
75
- auto helperPath = juce::File::getSpecialLocation(juce::File::currentExecutableFile)
76
- .getParentDirectory() // MacOS/
77
- .getParentDirectory() // Contents/
78
- .getChildFile("Resources")
79
- .getChildFile(PluginBridgeConstants::kHelperBinaryName);
 
 
 
80
 
81
- if (!helperPath.exists())
82
  {
83
- helperPath = juce::File::getSpecialLocation(juce::File::currentExecutableFile)
84
- .getParentDirectory()
85
- .getChildFile(PluginBridgeConstants::kHelperBinaryName);
 
 
 
86
  }
87
 
88
- if (!helperPath.exists())
89
  {
90
- DBG("HelperConnection: Helper binary not found at: " + helperPath.getFullPathName());
91
  return false;
92
  }
93
 
94
- // 5. Spawn helper process
95
  state.store(State::Starting);
96
 
97
  auto pidStr = juce::String(myPid).toStdString();
98
- auto helperPathStr = helperPath.getFullPathName().toStdString();
99
 
100
  pid_t pid;
101
  char* argv[] = {
@@ -108,7 +109,7 @@ bool HelperConnection::spawnHelper()
108
  int spawnResult = posix_spawn(&pid, helperPathStr.c_str(), nullptr, nullptr, argv, environ);
109
  if (spawnResult != 0)
110
  {
111
- DBG("HelperConnection: Failed to spawn helper: " + juce::String(strerror(spawnResult)));
112
  state.store(State::Disconnected);
113
  return false;
114
  }
@@ -116,7 +117,6 @@ bool HelperConnection::spawnHelper()
116
  helperPid = pid;
117
  helperRunning.store(true);
118
 
119
- // 6. Accept connection from helper (with timeout)
120
  struct pollfd pfd;
121
  pfd.fd = serverSocketFd;
122
  pfd.events = POLLIN;
@@ -131,23 +131,19 @@ bool HelperConnection::spawnHelper()
131
  clientSocketFd = accept(serverSocketFd, nullptr, nullptr);
132
  if (clientSocketFd < 0)
133
  {
134
- DBG("HelperConnection: Failed to accept helper connection");
135
  killHelper();
136
  return false;
137
  }
138
 
139
- // Set SO_NOSIGPIPE on the accepted socket (macOS)
140
  int nosigpipe = 1;
141
  setsockopt(clientSocketFd, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
142
 
143
- // 7. Start IPC listen thread
144
  ipcRunning.store(true);
145
  ipcThread = std::thread([this]() { ipcListenLoop(); });
146
 
147
- // 8. Start crash detection timer
148
  startTimerHz(4);
149
 
150
- // Wait for "ready" notification
151
  int waitMs = 0;
152
  while (state.load() == State::Starting && waitMs < IPC::kHelperTimeoutMs)
153
  {
@@ -161,8 +157,8 @@ bool HelperConnection::spawnHelper()
161
  void HelperConnection::killHelper()
162
  {
163
  stopTimer();
164
-
165
  ipcRunning.store(false);
 
166
  if (clientSocketFd >= 0) { close(clientSocketFd); clientSocketFd = -1; }
167
  if (serverSocketFd >= 0) { close(serverSocketFd); serverSocketFd = -1; }
168
  if (ipcThread.joinable()) ipcThread.join();
@@ -224,7 +220,7 @@ void HelperConnection::timerCallback()
224
  helperRunning.store(false);
225
  state.store(State::Crashed);
226
  stopTimer();
227
- DBG("HelperConnection: Helper process died");
228
  if (onHelperCrashed)
229
  onHelperCrashed();
230
  }
@@ -297,6 +293,23 @@ void HelperConnection::handleNotification(const std::string& jsonStr)
297
  if (onHelperReady)
298
  juce::MessageManager::callAsync([this]() { if (onHelperReady) onHelperReady(); });
299
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  else if (notify == "param_changed")
301
  {
302
  int index = j.value("index", -1);
 
17
  HelperConnection::HelperConnection()
18
  {
19
  myPid = getpid();
 
20
  signal(SIGPIPE, SIG_IGN);
21
  }
22
 
 
29
  {
30
  killHelper();
31
 
 
32
  auto shmName = IPC::getShmName(myPid);
33
  if (!sharedAudio.create(shmName))
34
  {
 
36
  return false;
37
  }
38
 
 
39
  if (!inputSem.create(IPC::getInputSemName(myPid)) ||
40
  !outputSem.create(IPC::getOutputSemName(myPid)))
41
  {
 
43
  return false;
44
  }
45
 
 
46
  auto socketPath = IPC::getSocketPath(myPid);
47
  unlink(socketPath.c_str());
48
 
 
61
  if (bind(serverSocketFd, (struct sockaddr*)&addr, sizeof(addr)) < 0 ||
62
  listen(serverSocketFd, 1) < 0)
63
  {
64
+ DBG("HelperConnection: Failed to bind/listen");
65
  close(serverSocketFd);
66
  serverSocketFd = -1;
67
  return false;
68
  }
69
 
70
+ // Find helper .app bundle inside .vst3/Contents/Resources/
71
+ auto helperApp = juce::File::getSpecialLocation(juce::File::currentExecutableFile)
72
+ .getParentDirectory() // MacOS/
73
+ .getParentDirectory() // Contents/
74
+ .getChildFile("Resources")
75
+ .getChildFile("PluginBridgeHelper.app")
76
+ .getChildFile("Contents")
77
+ .getChildFile("MacOS")
78
+ .getChildFile(PluginBridgeConstants::kHelperBinaryName);
79
 
80
+ if (!helperApp.exists())
81
  {
82
+ // Fallback: bare binary
83
+ helperApp = juce::File::getSpecialLocation(juce::File::currentExecutableFile)
84
+ .getParentDirectory()
85
+ .getParentDirectory()
86
+ .getChildFile("Resources")
87
+ .getChildFile(PluginBridgeConstants::kHelperBinaryName);
88
  }
89
 
90
+ if (!helperApp.exists())
91
  {
92
+ DBG("HelperConnection: Helper not found at: " + helperApp.getFullPathName());
93
  return false;
94
  }
95
 
 
96
  state.store(State::Starting);
97
 
98
  auto pidStr = juce::String(myPid).toStdString();
99
+ auto helperPathStr = helperApp.getFullPathName().toStdString();
100
 
101
  pid_t pid;
102
  char* argv[] = {
 
109
  int spawnResult = posix_spawn(&pid, helperPathStr.c_str(), nullptr, nullptr, argv, environ);
110
  if (spawnResult != 0)
111
  {
112
+ DBG("HelperConnection: Failed to spawn: " + juce::String(strerror(spawnResult)));
113
  state.store(State::Disconnected);
114
  return false;
115
  }
 
117
  helperPid = pid;
118
  helperRunning.store(true);
119
 
 
120
  struct pollfd pfd;
121
  pfd.fd = serverSocketFd;
122
  pfd.events = POLLIN;
 
131
  clientSocketFd = accept(serverSocketFd, nullptr, nullptr);
132
  if (clientSocketFd < 0)
133
  {
134
+ DBG("HelperConnection: Failed to accept connection");
135
  killHelper();
136
  return false;
137
  }
138
 
 
139
  int nosigpipe = 1;
140
  setsockopt(clientSocketFd, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
141
 
 
142
  ipcRunning.store(true);
143
  ipcThread = std::thread([this]() { ipcListenLoop(); });
144
 
 
145
  startTimerHz(4);
146
 
 
147
  int waitMs = 0;
148
  while (state.load() == State::Starting && waitMs < IPC::kHelperTimeoutMs)
149
  {
 
157
  void HelperConnection::killHelper()
158
  {
159
  stopTimer();
 
160
  ipcRunning.store(false);
161
+
162
  if (clientSocketFd >= 0) { close(clientSocketFd); clientSocketFd = -1; }
163
  if (serverSocketFd >= 0) { close(serverSocketFd); serverSocketFd = -1; }
164
  if (ipcThread.joinable()) ipcThread.join();
 
220
  helperRunning.store(false);
221
  state.store(State::Crashed);
222
  stopTimer();
223
+ DBG("HelperConnection: Helper died");
224
  if (onHelperCrashed)
225
  onHelperCrashed();
226
  }
 
293
  if (onHelperReady)
294
  juce::MessageManager::callAsync([this]() { if (onHelperReady) onHelperReady(); });
295
  }
296
+ else if (notify == "gui_ready")
297
+ {
298
+ auto portName = juce::String(j.value("layerPortName", ""));
299
+ int width = j.value("width", 0);
300
+ int height = j.value("height", 0);
301
+ if (onGuiReady)
302
+ juce::MessageManager::callAsync([this, portName, width, height]()
303
+ { if (onGuiReady) onGuiReady(portName, width, height); });
304
+ }
305
+ else if (notify == "resized")
306
+ {
307
+ int width = j.value("width", 0);
308
+ int height = j.value("height", 0);
309
+ if (onGuiResized)
310
+ juce::MessageManager::callAsync([this, width, height]()
311
+ { if (onGuiResized) onGuiResized(width, height); });
312
+ }
313
  else if (notify == "param_changed")
314
  {
315
  int index = j.value("index", -1);