2 Copyright (C) 2001 Paul Davis
3 Copyright (C) 2004-2008 Grame
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "JackClient.h"
22 #include "JackGraphManager.h"
23 #include "JackClientControl.h"
24 #include "JackEngineControl.h"
25 #include "JackGlobals.h"
26 #include "JackChannel.h"
27 #include "JackTransportEngine.h"
28 #include "driver_interface.h"
29 #include "JackLibGlobals.h"
40 #define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL))
42 JackClient::JackClient():fThread(this)
45 JackClient::JackClient(JackSynchro
* table
):fThread(this)
47 fSynchroTable
= table
;
54 fClientRegistration
= NULL
;
56 fPortRegistration
= NULL
;
63 fGraphOrderArg
= NULL
;
67 fBufferSizeArg
= NULL
;
69 fClientRegistrationArg
= NULL
;
70 fPortRegistrationArg
= NULL
;
71 fPortConnectArg
= NULL
;
72 fPortRenameArg
= NULL
;
78 JackClient::~JackClient()
81 int JackClient::Close()
83 jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum
);
87 fChannel
->Stop(); // Channels is stopped first to avoid receiving notifications while closing
89 // Request close only if server is still running
90 if (JackGlobals::fServerRunning
) {
91 fChannel
->ClientClose(GetClientControl()->fRefNum
, &result
);
93 jack_log("JackClient::Close server is shutdown");
97 fSynchroTable
[GetClientControl()->fRefNum
].Disconnect();
98 JackGlobals::fClientTable
[GetClientControl()->fRefNum
] = NULL
;
102 bool JackClient::IsActive()
104 return (GetClientControl()) ? GetClientControl()->fActive
: false;
107 pthread_t
JackClient::GetThreadID()
109 return fThread
.GetThreadID();
113 In "async" mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations.
114 The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations.
115 Drivers synchro are setup in "flush" mode if server is "async" and NOT freewheel.
117 void JackClient::SetupDriverSync(bool freewheel
)
119 if (!freewheel
&& !GetEngineControl()->fSyncMode
) {
120 jack_log("JackClient::SetupDriverSync driver sem in flush mode");
121 for (int i
= 0; i
< GetEngineControl()->fDriverNum
; i
++) {
122 fSynchroTable
[i
].SetFlush(true);
125 jack_log("JackClient::SetupDriverSync driver sem in normal mode");
126 for (int i
= 0; i
< GetEngineControl()->fDriverNum
; i
++)
127 fSynchroTable
[i
].SetFlush(false);
132 \brief Notification received from the server.
135 int JackClient::ClientNotifyImp(int refnum
, const char* name
, int notify
, int sync
, int value1
, int value2
)
140 int JackClient::ClientNotify(int refnum
, const char* name
, int notify
, int sync
, int value1
, int value2
)
144 // Done all time: redirected on subclass implementation JackLibClient and JackInternalClient
148 res
= ClientNotifyImp(refnum
, name
, notify
, sync
, value1
, value2
);
152 res
= ClientNotifyImp(refnum
, name
, notify
, sync
, value1
, value2
);
155 case kActivateClient
:
156 jack_log("JackClient::kActivateClient name = %s ref = %ld ", name
, refnum
);
162 The current semantic is that notifications can only be received when the client has been activated,
163 although is this implementation, one could imagine calling notifications as soon as the client has be opened.
170 jack_log("JackClient::kAddClient fName = %s name = %s", GetClientControl()->fName
, name
);
171 if (fClientRegistration
&& strcmp(GetClientControl()->fName
, name
) != 0) // Don't call the callback for the registering client itself
172 fClientRegistration(name
, 1, fClientRegistrationArg
);
176 jack_log("JackClient::kRemoveClient fName = %s name = %s", GetClientControl()->fName
, name
);
177 if (fClientRegistration
&& strcmp(GetClientControl()->fName
, name
) != 0) // Don't call the callback for the registering client itself
178 fClientRegistration(name
, 0, fClientRegistrationArg
);
181 case kBufferSizeCallback
:
182 jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", value1
);
184 res
= fBufferSize(value1
, fBufferSizeArg
);
187 case kSampleRateCallback
:
188 jack_log("JackClient::kSampleRateCallback sample_rate = %ld", value1
);
190 res
= fSampleRate(value1
, fSampleRateArg
);
193 case kGraphOrderCallback
:
194 jack_log("JackClient::kGraphOrderCallback");
196 res
= fGraphOrder(fGraphOrderArg
);
199 case kStartFreewheelCallback
:
200 jack_log("JackClient::kStartFreewheel");
201 SetupDriverSync(true);
202 fThread
.DropRealTime();
204 fFreewheel(1, fFreewheelArg
);
207 case kStopFreewheelCallback
:
208 jack_log("JackClient::kStopFreewheel");
209 SetupDriverSync(false);
211 fFreewheel(0, fFreewheelArg
);
212 fThread
.AcquireRealTime();
215 case kPortRegistrationOnCallback
:
216 jack_log("JackClient::kPortRegistrationOn port_index = %ld", value1
);
217 if (fPortRegistration
)
218 fPortRegistration(value1
, 1, fPortRegistrationArg
);
221 case kPortRegistrationOffCallback
:
222 jack_log("JackClient::kPortRegistrationOff port_index = %ld ", value1
);
223 if (fPortRegistration
)
224 fPortRegistration(value1
, 0, fPortRegistrationArg
);
227 case kPortConnectCallback
:
228 jack_log("JackClient::kPortConnectCallback src = %ld dst = %ld", value1
, value2
);
230 fPortConnect(value1
, value2
, 1, fPortConnectArg
);
233 case kPortDisconnectCallback
:
234 jack_log("JackClient::kPortDisconnectCallback src = %ld dst = %ld", value1
, value2
);
236 fPortConnect(value1
, value2
, 0, fPortConnectArg
);
239 case kPortRenameCallback
:
240 jack_log("JackClient::kPortRenameCallback port = %ld");
242 fPortRename(value1
, GetGraphManager()->GetPort(value1
)->GetName(), fPortRenameArg
);
246 jack_log("JackClient::kXRunCallback");
248 res
= fXrun(fXrunArg
);
257 \brief We need to start thread before activating in the server, otherwise the FW driver
258 connected to the client may not be activated.
260 int JackClient::Activate()
262 jack_log("JackClient::Activate");
266 // RT thread is started only when needed...
268 if (StartThread() < 0)
273 Insertion of client in the graph will cause a kGraphOrderCallback notification
274 to be delivered by the server, the client wants to receive it.
276 GetClientControl()->fActive
= true;
278 // Transport related callback become "active"
279 GetClientControl()->fTransportSync
= true;
280 GetClientControl()->fTransportTimebase
= true;
283 GetClientControl()->fCallback
[kRealTimeCallback
] = IsRealTime();
284 fChannel
->ClientActivate(GetClientControl()->fRefNum
, IsRealTime(), &result
);
289 \brief Need to stop thread after deactivating in the server.
291 int JackClient::Deactivate()
293 jack_log("JackClient::Deactivate");
297 GetClientControl()->fActive
= false;
299 // Transport related callback become "unactive"
300 GetClientControl()->fTransportSync
= false;
301 GetClientControl()->fTransportTimebase
= false;
303 // We need to wait for the new engine cycle before stopping the RT thread, but this is done by ClientDeactivate
305 fChannel
->ClientDeactivate(GetClientControl()->fRefNum
, &result
);
306 jack_log("JackClient::Deactivate res = %ld", result
);
308 // RT thread is stopped only when needed...
314 //----------------------
315 // RT thread management
316 //----------------------
319 \brief Called once when the thread starts.
321 bool JackClient::Init()
324 jack_log("JackClient::Init calling client thread init callback");
330 int JackClient::StartThread()
332 jack_log("JackClient::StartThread : period = %ld computation = %ld constraint = %ld",
333 long(int64_t(GetEngineControl()->fPeriod
) / 1000.0f
),
334 long(int64_t(GetEngineControl()->fComputation
) / 1000.0f
),
335 long(int64_t(GetEngineControl()->fConstraint
) / 1000.0f
));
337 // Will do "something" on OSX only...
338 fThread
.SetParams(GetEngineControl()->fPeriod
, GetEngineControl()->fComputation
, GetEngineControl()->fConstraint
);
340 if (fThread
.StartSync() < 0) {
341 jack_error("Start thread error");
345 if (GetEngineControl()->fRealTime
) {
346 if (fThread
.AcquireRealTime(GetEngineControl()->fClientPriority
) < 0) {
347 jack_error("AcquireRealTime error");
358 bool JackClient::Execute()
360 if (!jack_tls_set(JackGlobals::fRealTime
, this))
361 jack_error("failed to set thread realtime key");
363 if (GetEngineControl()->fRealTime
)
364 set_threaded_log_function();
366 // Execute a dummy cycle to be sure thread has the correct properties
370 fThreadFun(fThreadFunArg
);
377 void JackClient::DummyCycle()
383 inline void JackClient::ExecuteThread()
387 CycleSignalAux(CallProcessCallback());
391 inline jack_nframes_t
JackClient::CycleWaitAux()
394 Error(); // Terminates the thread
395 CallSyncCallbackAux();
396 return GetEngineControl()->fBufferSize
;
399 inline void JackClient::CycleSignalAux(int status
)
402 CallTimebaseCallbackAux();
405 End(); // Terminates the thread
408 jack_nframes_t
JackClient::CycleWait()
410 return CycleWaitAux();
413 void JackClient::CycleSignal(int status
)
415 CycleSignalAux(status
);
418 inline int JackClient::CallProcessCallback()
420 return (fProcess
!= NULL
) ? fProcess(GetEngineControl()->fBufferSize
, fProcessArg
) : 0;
423 inline bool JackClient::WaitSync()
425 // Suspend itself: wait on the input synchro
426 if (GetGraphManager()->SuspendRefNum(GetClientControl(), fSynchroTable
, 0x7FFFFFFF) < 0) {
427 jack_error("SuspendRefNum error");
434 inline void JackClient::SignalSync()
436 // Resume: signal output clients connected to the running client
437 if (GetGraphManager()->ResumeRefNum(GetClientControl(), fSynchroTable
) < 0) {
438 jack_error("ResumeRefNum error");
442 inline void JackClient::End()
444 jack_log("JackClient::Execute end name = %s", GetClientControl()->fName
);
445 // Hum... not sure about this, the following "close" code is called in the RT thread...
447 fThread
.DropRealTime();
448 GetClientControl()->fActive
= false;
449 fChannel
->ClientDeactivate(GetClientControl()->fRefNum
, &result
);
453 inline void JackClient::Error()
455 jack_error("JackClient::Execute error name = %s", GetClientControl()->fName
);
456 // Hum... not sure about this, the following "close" code is called in the RT thread...
458 fThread
.DropRealTime();
459 GetClientControl()->fActive
= false;
460 fChannel
->ClientDeactivate(GetClientControl()->fRefNum
, &result
);
469 int JackClient::PortRegister(const char* port_name
, const char* port_type
, unsigned long flags
, unsigned long buffer_size
)
471 // Check if port name is empty
472 string port_name_str
= string(port_name
);
473 if (port_name_str
.size() == 0) {
474 jack_error("port_name is empty");
475 return 0; // Means failure here...
478 // Check port name length
479 string name
= string(GetClientControl()->fName
) + string(":") + port_name_str
;
480 if (name
.size() >= JACK_PORT_NAME_SIZE
) {
481 jack_error("\"%s:%s\" is too long to be used as a JACK port name.\n"
482 "Please use %lu characters or less",
483 GetClientControl()->fName
,
485 JACK_PORT_NAME_SIZE
- 1);
486 return 0; // Means failure here...
490 jack_port_id_t port_index
= NO_PORT
;
491 fChannel
->PortRegister(GetClientControl()->fRefNum
, name
.c_str(), port_type
, flags
, buffer_size
, &port_index
, &result
);
494 jack_log("JackClient::PortRegister ref = %ld name = %s type = %s port_index = %ld", GetClientControl()->fRefNum
, name
.c_str(), port_type
, port_index
);
495 fPortList
.push_back(port_index
);
502 int JackClient::PortUnRegister(jack_port_id_t port_index
)
504 jack_log("JackClient::PortUnRegister port_index = %ld", port_index
);
505 list
<jack_port_id_t
>::iterator it
= find(fPortList
.begin(), fPortList
.end(), port_index
);
507 if (it
!= fPortList
.end()) {
510 fChannel
->PortUnRegister(GetClientControl()->fRefNum
, port_index
, &result
);
513 jack_error("unregistering a port %ld that is not own by the client", port_index
);
518 int JackClient::PortConnect(const char* src
, const char* dst
)
520 jack_log("JackClient::Connect src = %s dst = %s", src
, dst
);
522 fChannel
->PortConnect(GetClientControl()->fRefNum
, src
, dst
, &result
);
526 int JackClient::PortDisconnect(const char* src
, const char* dst
)
528 jack_log("JackClient::Disconnect src = %s dst = %s", src
, dst
);
530 fChannel
->PortDisconnect(GetClientControl()->fRefNum
, src
, dst
, &result
);
534 int JackClient::PortDisconnect(jack_port_id_t src
)
536 jack_log("JackClient::PortDisconnect src = %ld", src
);
538 fChannel
->PortDisconnect(GetClientControl()->fRefNum
, src
, ALL_PORTS
, &result
);
542 int JackClient::PortIsMine(jack_port_id_t port_index
)
544 JackPort
* port
= GetGraphManager()->GetPort(port_index
);
545 return GetClientControl()->fRefNum
== port
->GetRefNum();
548 int JackClient::PortRename(jack_port_id_t port_index
, const char* name
)
551 fChannel
->PortRename(GetClientControl()->fRefNum
, port_index
, name
, &result
);
555 //--------------------
556 // Context management
557 //--------------------
559 int JackClient::SetBufferSize(jack_nframes_t buffer_size
)
562 fChannel
->SetBufferSize(buffer_size
, &result
);
566 int JackClient::SetFreeWheel(int onoff
)
569 fChannel
->SetFreewheel(onoff
, &result
);
575 - from the RT thread when Execute method fails
576 - possibly from a "closed" notification channel
577 (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown))
580 void JackClient::ShutDown()
582 jack_log("ShutDown");
583 JackGlobals::fServerRunning
= false;
586 fShutdown(fShutdownArg
);
591 //----------------------
592 // Transport management
593 //----------------------
595 inline int JackClient::ActivateAux()
597 // If activated without RT thread...
598 if (IsActive() && fThread
.GetStatus() != JackThread::kRunning
) {
600 jack_log("ActivateAux");
602 // RT thread is started
603 if (StartThread() < 0)
607 GetClientControl()->fCallback
[kRealTimeCallback
] = IsRealTime();
608 fChannel
->ClientActivate(GetClientControl()->fRefNum
, IsRealTime(), &result
);
616 int JackClient::ReleaseTimebase()
619 fChannel
->ReleaseTimebase(GetClientControl()->fRefNum
, &result
);
621 GetClientControl()->fTransportTimebase
= false;
628 /* Call the server if the client is active, otherwise keeps the arguments */
629 int JackClient::SetSyncCallback(JackSyncCallback sync_callback
, void* arg
)
631 GetClientControl()->fTransportSync
= (fSync
!= NULL
);
633 fSync
= sync_callback
;
634 return ActivateAux();
637 int JackClient::SetTimebaseCallback(int conditional
, JackTimebaseCallback timebase_callback
, void* arg
)
640 fChannel
->SetTimebaseCallback(GetClientControl()->fRefNum
, conditional
, &result
);
643 GetClientControl()->fTransportTimebase
= true;
644 fTimebase
= timebase_callback
;
646 return ActivateAux();
654 int JackClient::SetSyncTimeout(jack_time_t timeout
)
656 GetEngineControl()->fTransport
.SetSyncTimeout(timeout
);
662 void JackClient::TransportLocate(jack_nframes_t frame
)
666 pos
.valid
= (jack_position_bits_t
)0;
667 jack_log("TransportLocate pos = %ld", pos
.frame
);
668 GetEngineControl()->fTransport
.RequestNewPos(&pos
);
671 int JackClient::TransportReposition(jack_position_t
* pos
)
673 jack_position_t tmp
= *pos
;
674 jack_log("TransportReposition pos = %ld", pos
->frame
);
675 if (tmp
.valid
& ~JACK_POSITION_MASK
) {
678 GetEngineControl()->fTransport
.RequestNewPos(pos
);
683 jack_transport_state_t
JackClient::TransportQuery(jack_position_t
* pos
)
685 return GetEngineControl()->fTransport
.Query(pos
);
688 jack_nframes_t
JackClient::GetCurrentTransportFrame()
690 return GetEngineControl()->fTransport
.GetCurrentFrame();
693 // Must be RT safe: directly write in the transport shared mem
694 void JackClient::TransportStart()
696 GetEngineControl()->fTransport
.SetCommand(TransportCommandStart
);
699 // Must be RT safe: directly write in the transport shared mem
700 void JackClient::TransportStop()
702 GetEngineControl()->fTransport
.SetCommand(TransportCommandStop
);
705 // Never called concurently with the server
706 // TODO check concurrency with SetSyncCallback
708 void JackClient::CallSyncCallback()
710 CallSyncCallbackAux();
713 inline void JackClient::CallSyncCallbackAux()
715 if (GetClientControl()->fTransportSync
) {
717 JackTransportEngine
& transport
= GetEngineControl()->fTransport
;
718 jack_position_t
* cur_pos
= transport
.ReadCurrentState();
719 jack_transport_state_t transport_state
= transport
.GetState();
722 if (fSync(transport_state
, cur_pos
, fSyncArg
)) {
723 GetClientControl()->fTransportState
= JackTransportRolling
;
724 GetClientControl()->fTransportSync
= false;
727 GetClientControl()->fTransportState
= JackTransportRolling
;
728 GetClientControl()->fTransportSync
= false;
733 void JackClient::CallTimebaseCallback()
735 CallTimebaseCallbackAux();
738 inline void JackClient::CallTimebaseCallbackAux()
740 JackTransportEngine
& transport
= GetEngineControl()->fTransport
;
744 transport
.GetTimebaseMaster(master
, unused
);
746 if (GetClientControl()->fRefNum
== master
&& fTimebase
) { // Client *is* timebase...
748 jack_transport_state_t transport_state
= transport
.GetState();
749 jack_position_t
* cur_pos
= transport
.WriteNextStateStart(1);
751 if (GetClientControl()->fTransportTimebase
) {
752 fTimebase(transport_state
, GetEngineControl()->fBufferSize
, cur_pos
, true, fTimebaseArg
);
753 GetClientControl()->fTransportTimebase
= false; // Callback is called only once with "new_pos" = true
754 } else if (transport_state
== JackTransportRolling
) {
755 fTimebase(transport_state
, GetEngineControl()->fBufferSize
, cur_pos
, false, fTimebaseArg
);
758 transport
.WriteNextStateStop(1);
762 //---------------------
763 // Callback management
764 //---------------------
766 void JackClient::OnShutdown(JackShutdownCallback callback
, void *arg
)
769 jack_error("You cannot set callbacks on an active client");
772 fShutdown
= callback
;
776 int JackClient::SetProcessCallback(JackProcessCallback callback
, void *arg
)
779 jack_error("You cannot set callbacks on an active client");
781 } else if (fThreadFun
) {
782 jack_error ("A thread callback has already been setup, both models cannot be used at the same time!");
791 int JackClient::SetXRunCallback(JackXRunCallback callback
, void *arg
)
794 jack_error("You cannot set callbacks on an active client");
797 GetClientControl()->fCallback
[kXRunCallback
] = (callback
!= NULL
);
804 int JackClient::SetInitCallback(JackThreadInitCallback callback
, void *arg
)
807 jack_error("You cannot set callbacks on an active client");
816 int JackClient::SetGraphOrderCallback(JackGraphOrderCallback callback
, void *arg
)
818 jack_log("SetGraphOrderCallback ");
821 jack_error("You cannot set callbacks on an active client");
824 GetClientControl()->fCallback
[kGraphOrderCallback
] = (callback
!= NULL
);
825 fGraphOrder
= callback
;
826 fGraphOrderArg
= arg
;
831 int JackClient::SetBufferSizeCallback(JackBufferSizeCallback callback
, void *arg
)
834 jack_error("You cannot set callbacks on an active client");
837 GetClientControl()->fCallback
[kBufferSizeCallback
] = (callback
!= NULL
);
838 fBufferSizeArg
= arg
;
839 fBufferSize
= callback
;
844 int JackClient::SetSampleRateCallback(JackSampleRateCallback callback
, void *arg
)
847 jack_error("You cannot set callbacks on an active client");
850 GetClientControl()->fCallback
[kSampleRateCallback
] = (callback
!= NULL
);
851 fSampleRateArg
= arg
;
852 fSampleRate
= callback
;
857 int JackClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback
, void* arg
)
860 jack_error("You cannot set callbacks on an active client");
863 // kAddClient and kRemoveClient notifications must be delivered by the server in any case
864 fClientRegistrationArg
= arg
;
865 fClientRegistration
= callback
;
870 int JackClient::SetFreewheelCallback(JackFreewheelCallback callback
, void *arg
)
873 jack_error("You cannot set callbacks on an active client");
876 GetClientControl()->fCallback
[kStartFreewheelCallback
] = (callback
!= NULL
);
877 GetClientControl()->fCallback
[kStopFreewheelCallback
] = (callback
!= NULL
);
879 fFreewheel
= callback
;
884 int JackClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback
, void *arg
)
887 jack_error("You cannot set callbacks on an active client");
890 GetClientControl()->fCallback
[kPortRegistrationOnCallback
] = (callback
!= NULL
);
891 GetClientControl()->fCallback
[kPortRegistrationOffCallback
] = (callback
!= NULL
);
892 fPortRegistrationArg
= arg
;
893 fPortRegistration
= callback
;
898 int JackClient::SetPortConnectCallback(JackPortConnectCallback callback
, void *arg
)
901 jack_error("You cannot set callbacks on an active client");
904 GetClientControl()->fCallback
[kPortConnectCallback
] = (callback
!= NULL
);
905 GetClientControl()->fCallback
[kPortDisconnectCallback
] = (callback
!= NULL
);
906 fPortConnectArg
= arg
;
907 fPortConnect
= callback
;
912 int JackClient::SetPortRenameCallback(JackPortRenameCallback callback
, void *arg
)
915 jack_error("You cannot set callbacks on an active client");
918 GetClientControl()->fCallback
[kPortRenameCallback
] = (callback
!= NULL
);
919 fPortRenameArg
= arg
;
920 fPortRename
= callback
;
925 int JackClient::SetProcessThread(JackThreadCallback fun
, void *arg
)
928 jack_error("You cannot set callbacks on an active client");
930 } else if (fProcess
) {
931 jack_error ("A process callback has already been setup, both models cannot be used at the same time!");
944 char* JackClient::GetInternalClientName(int ref
)
946 char name_res
[JACK_CLIENT_NAME_SIZE
+ 1];
948 fChannel
->GetInternalClientName(GetClientControl()->fRefNum
, ref
, name_res
, &result
);
953 char* name
= (char*)malloc(strlen(name_res
));
954 strcpy(name
, name_res
);
959 int JackClient::InternalClientHandle(const char* client_name
, jack_status_t
* status
)
961 int int_ref
, result
= -1;
962 fChannel
->InternalClientHandle(GetClientControl()->fRefNum
, client_name
, (int*)status
, &int_ref
, &result
);
966 int JackClient::InternalClientLoad(const char* client_name
, jack_options_t options
, jack_status_t
* status
, jack_varargs_t
* va
)
968 if (strlen(client_name
) >= JACK_CLIENT_NAME_SIZE
) {
969 jack_error ("\"%s\" is too long for a JACK client name.\n"
970 "Please use %lu characters or less.",
971 client_name
, JACK_CLIENT_NAME_SIZE
);
975 if (va
->load_name
&& (strlen(va
->load_name
) >= JACK_PATH_MAX
)) {
976 jack_error("\"%s\" is too long for a shared object name.\n"
977 "Please use %lu characters or less.",
978 va
->load_name
, PATH_MAX
);
979 int my_status1
= *status
| (JackFailure
| JackInvalidOption
);
980 *status
= (jack_status_t
)my_status1
;
984 if (va
->load_init
&& (strlen(va
->load_init
) >= JACK_LOAD_INIT_LIMIT
)) {
985 jack_error ("\"%s\" is too long for internal client init "
986 "string.\nPlease use %lu characters or less.",
987 va
->load_init
, JACK_LOAD_INIT_LIMIT
);
988 int my_status1
= *status
| (JackFailure
| JackInvalidOption
);
989 *status
= (jack_status_t
)my_status1
;
993 int int_ref
, result
= -1;
994 fChannel
->InternalClientLoad(GetClientControl()->fRefNum
, client_name
, va
->load_name
, va
->load_init
, options
, (int*)status
, &int_ref
, &result
);
998 void JackClient::InternalClientUnload(int ref
, jack_status_t
* status
)
1001 fChannel
->InternalClientUnload(GetClientControl()->fRefNum
, ref
, (int*)status
, &result
);
1005 } // end of namespace