jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

391 lines
12KB

  1. /*
  2. Copyright (C) 2004-2006 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "JackWinNamedPipeServerChannel.h"
  16. #include "JackRequest.h"
  17. #include "JackServer.h"
  18. #include "JackEngine.h"
  19. #include "JackGlobals.h"
  20. #include "JackClient.h"
  21. #include <assert.h>
  22. using namespace std;
  23. namespace Jack
  24. {
  25. HANDLE JackClientPipeThread::fMutex = NULL; // never released....
  26. // fRefNum = 0 is used as a "running" state for the JackWinNamedPipeServerNotifyChannel object
  27. // fRefNum = -1 correspond to a not running client
  28. JackClientPipeThread::JackClientPipeThread(JackWinNamedPipeClient* pipe)
  29. : fPipe(pipe), fServer(NULL), fRefNum(0)
  30. {
  31. fThread = JackGlobals::MakeThread(this);
  32. if (fMutex == NULL)
  33. fMutex = CreateMutex(NULL, FALSE, NULL);
  34. }
  35. JackClientPipeThread::~JackClientPipeThread()
  36. {
  37. delete fPipe;
  38. delete fThread;
  39. }
  40. int JackClientPipeThread::Open(JackServer* server) // Open the Server/Client connection
  41. {
  42. fServer = server;
  43. // Start listening
  44. if (fThread->Start() != 0){
  45. jack_error("Cannot start Jack server listener\n");
  46. return -1;
  47. } else {
  48. return 0;
  49. }
  50. }
  51. void JackClientPipeThread::Close() // Close the Server/Client connection
  52. {
  53. fThread->Kill();
  54. }
  55. bool JackClientPipeThread::Execute()
  56. {
  57. JackLog("JackClientPipeThread::Execute\n");
  58. if (HandleRequest(fPipe) < 0) {
  59. return false;
  60. } else {
  61. return true;
  62. }
  63. }
  64. int JackClientPipeThread::HandleRequest(JackWinNamedPipeClient* pipe)
  65. {
  66. // Read header
  67. JackRequest header;
  68. if (header.Read(pipe) < 0) {
  69. jack_error("HandleRequest: cannot read header");
  70. // Lock the global mutex
  71. if (WaitForSingleObject(fMutex, INFINITE) == WAIT_FAILED)
  72. jack_error("JackClientPipeThread::HandleRequest: mutex wait error");
  73. KillClient(fPipe);
  74. // Unlock the global mutex
  75. ReleaseMutex(fMutex);
  76. return -1;
  77. }
  78. // Lock the global mutex
  79. if (WaitForSingleObject(fMutex, INFINITE) == WAIT_FAILED)
  80. jack_error("JackClientPipeThread::HandleRequest: mutex wait error");
  81. // Read data
  82. switch (header.fType) {
  83. case JackRequest::kClientNew: {
  84. JackLog("JackRequest::ClientNew\n");
  85. JackClientNewRequest req;
  86. JackClientNewResult res;
  87. req.Read(pipe);
  88. AddClient(pipe, req.fName, &res.fSharedEngine, &res.fSharedClient, &res.fSharedPorts, &res.fResult);
  89. res.Write(pipe);
  90. break;
  91. }
  92. case JackRequest::kClientClose: {
  93. JackLog("JackRequest::ClientClose\n");
  94. JackClientCloseRequest req;
  95. JackResult res;
  96. req.Read(pipe);
  97. res.fResult = fServer->GetEngine()->ClientClose(req.fRefNum);
  98. res.Write(pipe);
  99. RemoveClient(pipe, req.fRefNum);
  100. break;
  101. }
  102. case JackRequest::kActivateClient: {
  103. JackActivateRequest req;
  104. JackResult res;
  105. JackLog("JackRequest::ActivateClient\n");
  106. req.Read(pipe);
  107. res.fResult = fServer->Activate(req.fRefNum);
  108. res.Write(pipe);
  109. break;
  110. }
  111. case JackRequest::kDeactivateClient: {
  112. JackLog("JackRequest::DeactivateClient\n");
  113. JackDeactivateRequest req;
  114. JackResult res;
  115. req.Read(pipe);
  116. res.fResult = fServer->Deactivate(req.fRefNum);
  117. res.Write(pipe);
  118. break;
  119. }
  120. case JackRequest::kRegisterPort: {
  121. JackLog("JackRequest::RegisterPort\n");
  122. JackPortRegisterRequest req;
  123. JackPortRegisterResult res;
  124. req.Read(pipe);
  125. res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fFlags, req.fBufferSize, &res.fPortIndex);
  126. res.Write(pipe);
  127. break;
  128. }
  129. case JackRequest::kUnRegisterPort: {
  130. JackLog("JackRequest::UnRegisterPort\n");
  131. JackPortUnRegisterRequest req;
  132. JackResult res;
  133. req.Read(pipe);
  134. res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex);
  135. res.Write(pipe);
  136. break;
  137. }
  138. case JackRequest::kConnectNamePorts: {
  139. JackLog("JackRequest::ConnectPorts\n");
  140. JackPortConnectNameRequest req;
  141. JackResult res;
  142. req.Read(pipe);
  143. res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
  144. res.Write(pipe);
  145. break;
  146. }
  147. case JackRequest::kDisconnectNamePorts: {
  148. JackLog("JackRequest::DisconnectPorts\n");
  149. JackPortDisconnectNameRequest req;
  150. JackResult res;
  151. req.Read(pipe);
  152. res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
  153. res.Write(pipe);
  154. break;
  155. }
  156. case JackRequest::kConnectPorts: {
  157. JackLog("JackRequest::ConnectPorts\n");
  158. JackPortConnectRequest req;
  159. JackResult res;
  160. req.Read(pipe);
  161. res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
  162. res.Write(pipe);
  163. break;
  164. }
  165. case JackRequest::kDisconnectPorts: {
  166. JackLog("JackRequest::DisconnectPorts\n");
  167. JackPortDisconnectRequest req;
  168. JackResult res;
  169. req.Read(pipe);
  170. res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
  171. res.Write(pipe);
  172. break;
  173. }
  174. case JackRequest::kSetBufferSize: {
  175. JackLog("JackRequest::SetBufferSize\n");
  176. JackSetBufferSizeRequest req;
  177. JackResult res;
  178. req.Read(pipe);
  179. res.fResult = fServer->SetBufferSize(req.fBufferSize);
  180. res.Write(pipe);
  181. break;
  182. }
  183. case JackRequest::kSetFreeWheel: {
  184. JackLog("JackRequest::SetFreeWheel\n");
  185. JackSetFreeWheelRequest req;
  186. JackResult res;
  187. req.Read(pipe);
  188. res.fResult = fServer->SetFreewheel(req.fOnOff);
  189. res.Write(pipe);
  190. break;
  191. }
  192. case JackRequest::kReleaseTimebase: {
  193. JackLog("JackRequest::kReleaseTimebase\n");
  194. JackReleaseTimebaseRequest req;
  195. JackResult res;
  196. req.Read(pipe);
  197. res.fResult = fServer->GetEngine()->ReleaseTimebase(req.fRefNum);
  198. res.Write(pipe);
  199. break;
  200. }
  201. case JackRequest::kSetTimebaseCallback: {
  202. JackLog("JackRequest::kSetTimebaseCallback\n");
  203. JackSetTimebaseCallbackRequest req;
  204. JackResult res;
  205. req.Read(pipe);
  206. res.fResult = fServer->GetEngine()->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
  207. res.Write(pipe);
  208. break;
  209. }
  210. case JackRequest::kNotification: {
  211. JackLog("JackRequest::Notification\n");
  212. JackClientNotificationRequest req;
  213. req.Read(pipe);
  214. fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
  215. break;
  216. }
  217. default:
  218. JackLog("Unknown request %ld\n", header.fType);
  219. break;
  220. }
  221. // Unlock the global mutex
  222. ReleaseMutex(fMutex);
  223. return 0;
  224. }
  225. void JackClientPipeThread::AddClient(JackWinNamedPipeClient* pipe, char* name, int* shared_engine, int* shared_client, int* shared_ports, int* result)
  226. {
  227. JackLog("JackWinNamedPipeServerChannel::AddClient %s\n", name);
  228. fRefNum = -1;
  229. *result = fServer->GetEngine()->ClientNew(name, &fRefNum, shared_engine, shared_client, shared_ports);
  230. }
  231. void JackClientPipeThread::RemoveClient(JackWinNamedPipeClient* pipe, int refnum)
  232. {
  233. JackLog("JackWinNamedPipeServerChannel::RemoveClient ref = %d\n", refnum);
  234. fRefNum = -1;
  235. pipe->Close();
  236. }
  237. void JackClientPipeThread::KillClient(JackWinNamedPipeClient* pipe)
  238. {
  239. JackLog("JackClientPipeThread::KillClient \n");
  240. JackLog("JackWinNamedPipeServerChannel::KillClient ref = %d\n", fRefNum);
  241. if (fRefNum == -1) { // Correspond to an already removed client.
  242. JackLog("Kill a closed client\n");
  243. } else if (fRefNum == 0) { // Correspond to a still not opened client.
  244. JackLog("Kill a not opened client\n");
  245. } else {
  246. fServer->Notify(fRefNum, JackNotifyChannelInterface::kDeadClient, 0);
  247. }
  248. fRefNum = -1;
  249. pipe->Close();
  250. }
  251. JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel()
  252. {
  253. fThread = JackGlobals::MakeThread(this);
  254. }
  255. JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel()
  256. {
  257. delete fThread;
  258. }
  259. int JackWinNamedPipeServerChannel::Open(JackServer* server)
  260. {
  261. JackLog("JackWinNamedPipeServerChannel::Open \n");
  262. fServer = server;
  263. // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object
  264. if (fRequestListenPipe.Bind(jack_server_dir, 0) < 0) {
  265. jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
  266. return false;
  267. }
  268. // Start listening
  269. if (fThread->Start() != 0) {
  270. jack_error("Cannot start Jack server listener\n");
  271. goto error;
  272. }
  273. return 0;
  274. error:
  275. fRequestListenPipe.Close();
  276. return -1;
  277. }
  278. void JackWinNamedPipeServerChannel::Close()
  279. {
  280. fThread->Kill();
  281. fRequestListenPipe.Close();
  282. }
  283. bool JackWinNamedPipeServerChannel::Init()
  284. {
  285. JackLog("JackWinNamedPipeServerChannel::Init \n");
  286. JackWinNamedPipeClient* pipe;
  287. // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object
  288. if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
  289. jack_error("JackWinNamedPipeServerChannel::Init : cannot connect pipe");
  290. return false;
  291. } else {
  292. AddClient(pipe);
  293. return true;
  294. }
  295. }
  296. bool JackWinNamedPipeServerChannel::Execute()
  297. {
  298. JackWinNamedPipeClient* pipe;
  299. if (fRequestListenPipe.Bind(jack_server_dir, 0) < 0) {
  300. jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
  301. return false;
  302. }
  303. if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) {
  304. jack_error("JackWinNamedPipeServerChannel::Open : cannot connect pipe");
  305. return false;
  306. }
  307. AddClient(pipe);
  308. return true;
  309. }
  310. void JackWinNamedPipeServerChannel::AddClient(JackWinNamedPipeClient* pipe)
  311. {
  312. // Remove dead clients
  313. std::list<JackClientPipeThread*>::iterator it = fClientList.begin();
  314. JackClientPipeThread* client;
  315. while (it != fClientList.end()) {
  316. client = *it;
  317. if (!client->IsRunning()) { // Dead client
  318. JackLog("Remove client from list\n");
  319. it = fClientList.erase(it);
  320. delete(client);
  321. } else {
  322. it++;
  323. }
  324. }
  325. client = new JackClientPipeThread(pipe);
  326. client->Open(fServer);
  327. fClientList.push_back(client);
  328. }
  329. } // end of namespace