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 "JackWinNamedPipeServerChannel.h"
21 #include "JackRequest.h"
22 #include "JackServer.h"
23 #include "JackEngine.h"
24 #include "JackGlobals.h"
25 #include "JackClient.h"
33 HANDLE
JackClientPipeThread::fMutex
= NULL
; // never released....
35 // fRefNum = -1 correspond to already removed client
37 JackClientPipeThread::JackClientPipeThread(JackWinNamedPipeClient
* pipe
)
38 : fPipe(pipe
), fServer(NULL
), fRefNum(0)
40 fThread
= JackGlobals::MakeThread(this);
42 fMutex
= CreateMutex(NULL
, FALSE
, NULL
);
45 JackClientPipeThread::~JackClientPipeThread()
47 JackLog("JackClientPipeThread::~JackClientPipeThread\n");
52 int JackClientPipeThread::Open(JackServer
* server
) // Open the Server/Client connection
57 if (fThread
->Start() != 0) {
58 jack_error("Cannot start Jack server listener\n");
65 void JackClientPipeThread::Close() // Close the Server/Client connection
67 JackLog("JackClientPipeThread::Close %x %ld\n", this, fRefNum
);
69 TODO : solve WIN32 thread Kill issue
70 This would hang.. since Close will be followed by a delete,
71 all ressources will be desallocated at the end.
79 bool JackClientPipeThread::Execute()
81 JackLog("JackClientPipeThread::Execute\n");
82 return (HandleRequest() == 0);
85 int JackClientPipeThread::HandleRequest()
89 int res
= header
.Read(fPipe
);
92 // Lock the global mutex
93 if (WaitForSingleObject(fMutex
, INFINITE
) == WAIT_FAILED
)
94 jack_error("JackClientPipeThread::HandleRequest: mutex wait error");
97 jack_error("HandleRequest: cannot read header");
103 switch (header
.fType
) {
105 case JackRequest::kClientNew
: {
106 JackLog("JackRequest::ClientNew\n");
107 JackClientNewRequest req
;
108 JackClientNewResult res
;
109 if (req
.Read(fPipe
) == 0)
110 AddClient(req
.fName
, &res
.fSharedEngine
, &res
.fSharedClient
, &res
.fSharedPorts
, &res
.fResult
);
115 case JackRequest::kClientClose
: {
116 JackLog("JackRequest::ClientClose\n");
117 JackClientCloseRequest req
;
119 if (req
.Read(fPipe
) == 0)
120 res
.fResult
= fServer
->GetEngine()->ClientClose(req
.fRefNum
);
127 case JackRequest::kActivateClient
: {
128 JackActivateRequest req
;
130 JackLog("JackRequest::ActivateClient\n");
131 if (req
.Read(fPipe
) == 0)
132 res
.fResult
= fServer
->Activate(req
.fRefNum
);
137 case JackRequest::kDeactivateClient
: {
138 JackLog("JackRequest::DeactivateClient\n");
139 JackDeactivateRequest req
;
141 if (req
.Read(fPipe
) == 0)
142 res
.fResult
= fServer
->Deactivate(req
.fRefNum
);
147 case JackRequest::kRegisterPort
: {
148 JackLog("JackRequest::RegisterPort\n");
149 JackPortRegisterRequest req
;
150 JackPortRegisterResult res
;
151 if (req
.Read(fPipe
) == 0)
152 res
.fResult
= fServer
->GetEngine()->PortRegister(req
.fRefNum
, req
.fName
, req
.fFlags
, req
.fBufferSize
, &res
.fPortIndex
);
157 case JackRequest::kUnRegisterPort
: {
158 JackLog("JackRequest::UnRegisterPort\n");
159 JackPortUnRegisterRequest req
;
161 if (req
.Read(fPipe
) == 0)
162 res
.fResult
= fServer
->GetEngine()->PortUnRegister(req
.fRefNum
, req
.fPortIndex
);
167 case JackRequest::kConnectNamePorts
: {
168 JackLog("JackRequest::ConnectPorts\n");
169 JackPortConnectNameRequest req
;
171 if (req
.Read(fPipe
) == 0)
172 res
.fResult
= fServer
->GetEngine()->PortConnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
177 case JackRequest::kDisconnectNamePorts
: {
178 JackLog("JackRequest::DisconnectPorts\n");
179 JackPortDisconnectNameRequest req
;
181 if (req
.Read(fPipe
) == 0)
182 res
.fResult
= fServer
->GetEngine()->PortDisconnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
187 case JackRequest::kConnectPorts
: {
188 JackLog("JackRequest::ConnectPorts\n");
189 JackPortConnectRequest req
;
191 if (req
.Read(fPipe
) == 0)
192 res
.fResult
= fServer
->GetEngine()->PortConnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
197 case JackRequest::kDisconnectPorts
: {
198 JackLog("JackRequest::DisconnectPorts\n");
199 JackPortDisconnectRequest req
;
201 if (req
.Read(fPipe
) == 0)
202 res
.fResult
= fServer
->GetEngine()->PortDisconnect(req
.fRefNum
, req
.fSrc
, req
.fDst
);
207 case JackRequest::kSetBufferSize
: {
208 JackLog("JackRequest::SetBufferSize\n");
209 JackSetBufferSizeRequest req
;
211 if (req
.Read(fPipe
) == 0)
212 res
.fResult
= fServer
->SetBufferSize(req
.fBufferSize
);
217 case JackRequest::kSetFreeWheel
: {
218 JackLog("JackRequest::SetFreeWheel\n");
219 JackSetFreeWheelRequest req
;
221 if (req
.Read(fPipe
) == 0)
222 res
.fResult
= fServer
->SetFreewheel(req
.fOnOff
);
227 case JackRequest::kReleaseTimebase
: {
228 JackLog("JackRequest::kReleaseTimebase\n");
229 JackReleaseTimebaseRequest req
;
231 if (req
.Read(fPipe
) == 0)
232 res
.fResult
= fServer
->GetEngine()->ReleaseTimebase(req
.fRefNum
);
237 case JackRequest::kSetTimebaseCallback
: {
238 JackLog("JackRequest::kSetTimebaseCallback\n");
239 JackSetTimebaseCallbackRequest req
;
241 if (req
.Read(fPipe
) == 0)
242 res
.fResult
= fServer
->GetEngine()->SetTimebaseCallback(req
.fRefNum
, req
.fConditionnal
);
247 case JackRequest::kNotification
: {
248 JackLog("JackRequest::Notification\n");
249 JackClientNotificationRequest req
;
250 if (req
.Read(fPipe
) == 0)
251 fServer
->Notify(req
.fRefNum
, req
.fNotify
, req
.fValue
);
256 JackLog("Unknown request %ld\n", header
.fType
);
261 // Unlock the global mutex
262 ReleaseMutex(fMutex
);
266 void JackClientPipeThread::AddClient(char* name
, int* shared_engine
, int* shared_client
, int* shared_ports
, int* result
)
268 JackLog("JackClientPipeThread::AddClient %s\n", name
);
270 *result
= fServer
->GetEngine()->ClientNew(name
, &fRefNum
, shared_engine
, shared_client
, shared_ports
);
273 void JackClientPipeThread::RemoveClient()
275 JackLog("JackClientPipeThread::RemoveClient ref = %d\n", fRefNum
);
276 /* TODO : solve WIN32 thread Kill issue
283 void JackClientPipeThread::KillClient()
285 JackLog("JackClientPipeThread::KillClient ref = %d\n", fRefNum
);
287 if (fRefNum
== -1) { // Correspond to an already removed client.
288 JackLog("Kill a closed client\n");
289 } else if (fRefNum
== 0) { // Correspond to a still not opened client.
290 JackLog("Kill a not opened client\n");
292 fServer
->Notify(fRefNum
, JackNotifyChannelInterface::kDeadClient
, 0);
298 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel()
300 fThread
= JackGlobals::MakeThread(this);
303 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel()
305 std::list
<JackClientPipeThread
*>::iterator it
;
307 for (it
= fClientList
.begin(); it
!= fClientList
.end(); it
++) {
308 JackClientPipeThread
* client
= *it
;
316 int JackWinNamedPipeServerChannel::Open(JackServer
* server
)
318 JackLog("JackWinNamedPipeServerChannel::Open \n");
322 // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object
323 if (fRequestListenPipe
.Bind(jack_server_dir
, 0) < 0) {
324 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
329 if (fThread
->Start() != 0) {
330 jack_error("Cannot start Jack server listener\n");
337 fRequestListenPipe
.Close();
341 void JackWinNamedPipeServerChannel::Close()
343 /* TODO : solve WIN32 thread Kill issue
344 This would hang the server... since we are quitting it, its not really problematic,
345 all ressources will be desallocated at the end.
347 fRequestListenPipe.Close();
352 fRequestListenPipe
.Close();
355 bool JackWinNamedPipeServerChannel::Init()
357 JackLog("JackWinNamedPipeServerChannel::Init \n");
358 JackWinNamedPipeClient
* pipe
;
360 // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object
361 if ((pipe
= fRequestListenPipe
.AcceptClient()) == NULL
) {
362 jack_error("JackWinNamedPipeServerChannel::Init : cannot connect pipe");
370 bool JackWinNamedPipeServerChannel::Execute()
372 JackWinNamedPipeClient
* pipe
;
374 if (fRequestListenPipe
.Bind(jack_server_dir
, 0) < 0) {
375 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe");
379 if ((pipe
= fRequestListenPipe
.AcceptClient()) == NULL
) {
380 jack_error("JackWinNamedPipeServerChannel::Open : cannot connect pipe");
388 void JackWinNamedPipeServerChannel::AddClient(JackWinNamedPipeClient
* pipe
)
390 // Remove dead (= not running anymore) clients.
391 std::list
<JackClientPipeThread
*>::iterator it
= fClientList
.begin();
392 JackClientPipeThread
* client
;
394 JackLog("AddClient size %ld\n", fClientList
.size());
396 while (it
!= fClientList
.end()) {
398 JackLog("Remove dead client = %x running = %ld\n", client
, client
->IsRunning());
399 if (client
->IsRunning()) {
402 it
= fClientList
.erase(it
);
407 client
= new JackClientPipeThread(pipe
);
408 client
->Open(fServer
);
409 // Here we are sure that the client is running (because it's thread is in "running" state).
410 fClientList
.push_back(client
);
413 } // end of namespace