Dmitry Baikov jackmp-time patch: add jack_get_time, jack_time_to_frames, jack_frames_...
[jack2.git] / common / JackSocketServerChannel.cpp
blob1dfdbc9e299a29f6fc5209b7f689ac77eef535ab
1 /*
2 Copyright (C) 2004-2006 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "JackSocketServerChannel.h"
21 #include "JackRequest.h"
22 #include "JackServer.h"
23 #include "JackEngine.h"
24 #include "JackGlobals.h"
25 #include "JackClient.h"
26 #include <assert.h>
28 using namespace std;
30 namespace Jack
33 JackSocketServerChannel::JackSocketServerChannel()
35 fThread = JackGlobals::MakeThread(this);
36 fPollTable = NULL;
37 fRebuild = true;
40 JackSocketServerChannel::~JackSocketServerChannel()
42 delete fThread;
43 delete[] fPollTable;
46 int JackSocketServerChannel::Open(JackServer* server)
48 JackLog("JackSocketServerChannel::Open \n");
49 fServer = server;
51 // Prepare request socket
52 if (fRequestListenSocket.Bind(jack_server_dir, 0) < 0) {
53 JackLog("JackSocketServerChannel::Open : cannot create result listen socket\n");
54 return -1;
57 // Prepare for poll
58 BuildPoolTable();
60 // Start listening
61 if (fThread->Start() != 0) {
62 jack_error("Cannot start Jack server listener");
63 goto error;
66 return 0;
68 error:
69 fRequestListenSocket.Close();
70 return -1;
73 void JackSocketServerChannel::Close()
75 fThread->Kill();
76 fRequestListenSocket.Close();
79 void JackSocketServerChannel::CreateClient()
81 JackLog("JackSocketServerChannel::CreateClient socket\n");
82 JackClientSocket* socket = fRequestListenSocket.Accept();
83 if (socket) {
84 fSocketTable[socket->GetFd()] = make_pair( -1, socket);
85 fRebuild = true;
86 } else {
87 jack_error("Client socket cannot be created");
91 void JackSocketServerChannel::AddClient(int fd, char* name, int* shared_engine, int* shared_client, int* shared_graph, int* result)
93 JackLog("JackSocketServerChannel::AddClient\n");
94 int refnum = -1;
95 *result = fServer->GetEngine()->ClientExternalOpen(name, &refnum, shared_engine, shared_client, shared_graph);
96 if (*result == 0) {
97 fSocketTable[fd].first = refnum;
98 fRebuild = true;
99 } else {
100 jack_error("Cannot create new client");
104 void JackSocketServerChannel::RemoveClient(int fd, int refnum)
106 pair<int, JackClientSocket*> elem = fSocketTable[fd];
107 JackClientSocket* socket = elem.second;
108 assert(socket);
109 JackLog("JackSocketServerChannel::RemoveClient ref = %d\n", refnum);
110 fSocketTable.erase(fd);
111 socket->Close();
112 delete socket;
113 fRebuild = true;
116 void JackSocketServerChannel::KillClient(int fd)
118 pair<int, JackClientSocket*> elem = fSocketTable[fd];
119 JackClientSocket* socket = elem.second;
120 int refnum = elem.first;
122 assert(socket);
123 JackLog("JackSocketServerChannel::KillClient ref = %d\n", refnum);
125 if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened...
126 jack_error("Client not opened");
127 } else {
128 fServer->Notify(refnum, JackNotifyChannelInterface::kDeadClient, 0);
131 fSocketTable.erase(fd);
132 socket->Close();
133 delete socket;
134 fRebuild = true;
137 int JackSocketServerChannel::HandleRequest(int fd)
139 pair<int, JackClientSocket*> elem = fSocketTable[fd];
140 JackClientSocket* socket = elem.second;
141 assert(socket);
143 // Read header
144 JackRequest header;
145 if (header.Read(socket) < 0) {
146 jack_error("HandleRequest: cannot read header");
147 return -1;
150 // Read data
151 switch (header.fType) {
153 case JackRequest::kClientOpen: {
154 JackLog("JackRequest::ClientOpen\n");
155 JackClientOpenRequest req;
156 JackClientOpenResult res;
157 if (req.Read(socket) == 0)
158 AddClient(fd, req.fName, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult);
159 res.Write(socket);
160 break;
163 case JackRequest::kClientClose: {
164 JackLog("JackRequest::ClientClose\n");
165 JackClientCloseRequest req;
166 JackResult res;
167 if (req.Read(socket) == 0)
168 res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum);
169 res.Write(socket);
170 RemoveClient(fd, req.fRefNum);
171 break;
174 case JackRequest::kActivateClient: {
175 JackActivateRequest req;
176 JackResult res;
177 JackLog("JackRequest::ActivateClient\n");
178 if (req.Read(socket) == 0)
179 res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum);
180 res.Write(socket);
181 break;
184 case JackRequest::kDeactivateClient: {
185 JackLog("JackRequest::DeactivateClient\n");
186 JackDeactivateRequest req;
187 JackResult res;
188 if (req.Read(socket) == 0)
189 res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum);
190 res.Write(socket);
191 break;
194 case JackRequest::kRegisterPort: {
195 JackLog("JackRequest::RegisterPort\n");
196 JackPortRegisterRequest req;
197 JackPortRegisterResult res;
198 if (req.Read(socket) == 0)
199 res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fFlags, req.fBufferSize, &res.fPortIndex);
200 res.Write(socket);
201 break;
204 case JackRequest::kUnRegisterPort: {
205 JackLog("JackRequest::UnRegisterPort\n");
206 JackPortUnRegisterRequest req;
207 JackResult res;
208 if (req.Read(socket) == 0)
209 res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex);
210 res.Write(socket);
211 break;
214 case JackRequest::kConnectNamePorts: {
215 JackLog("JackRequest::ConnectPorts\n");
216 JackPortConnectNameRequest req;
217 JackResult res;
218 if (req.Read(socket) == 0)
219 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
220 res.Write(socket);
221 break;
224 case JackRequest::kDisconnectNamePorts: {
225 JackLog("JackRequest::DisconnectPorts\n");
226 JackPortDisconnectNameRequest req;
227 JackResult res;
228 if (req.Read(socket) == 0)
229 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
230 res.Write(socket);
231 break;
234 case JackRequest::kConnectPorts: {
235 JackLog("JackRequest::ConnectPorts\n");
236 JackPortConnectRequest req;
237 JackResult res;
238 if (req.Read(socket) == 0)
239 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst);
240 res.Write(socket);
241 break;
244 case JackRequest::kDisconnectPorts: {
245 JackLog("JackRequest::DisconnectPorts\n");
246 JackPortDisconnectRequest req;
247 JackResult res;
248 if (req.Read(socket) == 0)
249 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst);
250 res.Write(socket);
251 break;
254 case JackRequest::kSetBufferSize: {
255 JackLog("JackRequest::SetBufferSize\n");
256 JackSetBufferSizeRequest req;
257 JackResult res;
258 if (req.Read(socket) == 0)
259 res.fResult = fServer->SetBufferSize(req.fBufferSize);
260 res.Write(socket);
261 break;
264 case JackRequest::kSetFreeWheel: {
265 JackLog("JackRequest::SetFreeWheel\n");
266 JackSetFreeWheelRequest req;
267 JackResult res;
268 if (req.Read(socket) == 0)
269 res.fResult = fServer->SetFreewheel(req.fOnOff);
270 res.Write(socket);
271 break;
274 case JackRequest::kReleaseTimebase: {
275 JackLog("JackRequest::kReleaseTimebase\n");
276 JackReleaseTimebaseRequest req;
277 JackResult res;
278 if (req.Read(socket) == 0)
279 res.fResult = fServer->GetEngine()->ReleaseTimebase(req.fRefNum);
280 res.Write(socket);
281 break;
284 case JackRequest::kSetTimebaseCallback: {
285 JackLog("JackRequest::kSetTimebaseCallback\n");
286 JackSetTimebaseCallbackRequest req;
287 JackResult res;
288 if (req.Read(socket) == 0)
289 res.fResult = fServer->GetEngine()->SetTimebaseCallback(req.fRefNum, req.fConditionnal);
290 res.Write(socket);
291 break;
294 case JackRequest::kNotification: {
295 JackLog("JackRequest::Notification\n");
296 JackClientNotificationRequest req;
297 if (req.Read(socket) == 0)
298 fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
299 break;
302 default:
303 JackLog("Unknown request %ld\n", header.fType);
304 break;
307 return 0;
310 void JackSocketServerChannel::BuildPoolTable()
312 if (fRebuild) {
313 fRebuild = false;
314 delete[] fPollTable;
315 fPollTable = new pollfd[fSocketTable.size() + 1];
317 JackLog("JackSocketServerChannel::BuildPoolTable size = %d\n", fSocketTable.size() + 1);
319 // First fd is the server request socket
320 fPollTable[0].fd = fRequestListenSocket.GetFd();
321 fPollTable[0].events = POLLIN | POLLERR;
323 // Next fd for clients
324 map<int, pair<int, JackClientSocket*> >::iterator it;
325 int i;
327 for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) {
328 JackLog("fSocketTable i = %ld fd = %ld\n", i, it->first);
329 fPollTable[i].fd = it->first;
330 fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
335 bool JackSocketServerChannel::Execute()
337 // Global poll
338 if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
339 jack_error("Engine poll failed err = %s request thread quits...", strerror(errno));
340 return false;
341 } else {
343 // Poll all clients
344 for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
345 int fd = fPollTable[i].fd;
346 JackLog("fPollTable i = %ld fd = %ld\n", i, fd);
347 if (fPollTable[i].revents & ~POLLIN) {
348 jack_error("Poll client error err = %s", strerror(errno));
349 KillClient(fd);
350 } else if (fPollTable[i].revents & POLLIN) {
351 if (HandleRequest(fd) < 0) {
352 jack_error("Could not handle external client request");
353 //RemoveClient(fd); TO CHECK
358 // Check the server request socket */
359 if (fPollTable[0].revents & POLLERR) {
360 jack_error("Error on server request socket err = %s", strerror(errno));
361 //return false; TO CHECK
364 if (fPollTable[0].revents & POLLIN) {
365 CreateClient();
369 BuildPoolTable();
370 return true;
373 } // end of namespace