diff options
-rw-r--r-- | .travis.yml | 37 | ||||
-rwxr-xr-x | .wafupdaterc | 2 | ||||
-rw-r--r-- | common/JackDebugClient.cpp | 2 | ||||
-rw-r--r-- | common/JackDriver.cpp | 1 | ||||
-rw-r--r-- | common/JackRequest.h | 204 | ||||
-rw-r--r-- | common/Jackdmp.cpp | 31 | ||||
-rw-r--r-- | common/jack/systemdeps.h | 2 | ||||
-rw-r--r-- | common/memops.c | 353 | ||||
-rw-r--r-- | common/wscript | 53 | ||||
-rw-r--r-- | dbus/sigsegv.c | 20 | ||||
-rw-r--r-- | example-clients/ipload.c | 46 | ||||
-rw-r--r-- | example-clients/simdtests.cpp | 390 | ||||
-rw-r--r-- | example-clients/transport.c | 24 | ||||
-rw-r--r-- | example-clients/wscript | 23 | ||||
-rw-r--r-- | linux/JackLinuxFutex.cpp | 243 | ||||
-rw-r--r-- | linux/JackLinuxFutex.h | 85 | ||||
-rw-r--r-- | linux/JackPlatformPlug_os.h | 4 | ||||
-rw-r--r-- | linux/firewire/JackFFADODriver.cpp | 5 | ||||
-rw-r--r-- | macosx/JackMachSemaphore.mm (renamed from macosx/JackMachSemaphore.cpp) | 0 | ||||
-rw-r--r-- | macosx/JackMachThread.h | 2 | ||||
-rw-r--r-- | macosx/JackMachThread.mm (renamed from macosx/JackMachThread.cpp) | 0 | ||||
-rw-r--r-- | macosx/coreaudio/JackCoreAudioAdapter.mm (renamed from macosx/coreaudio/JackCoreAudioAdapter.cpp) | 0 | ||||
-rw-r--r-- | macosx/coreaudio/JackCoreAudioDriver.mm (renamed from macosx/coreaudio/JackCoreAudioDriver.cpp) | 0 | ||||
-rw-r--r-- | macosx/coreaudio/TiPhoneCoreAudioRenderer.mm (renamed from macosx/coreaudio/TiPhoneCoreAudioRenderer.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiDriver.mm (renamed from macosx/coremidi/JackCoreMidiDriver.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiInputPort.mm (renamed from macosx/coremidi/JackCoreMidiInputPort.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiOutputPort.mm (renamed from macosx/coremidi/JackCoreMidiOutputPort.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiPhysicalInputPort.mm (renamed from macosx/coremidi/JackCoreMidiPhysicalInputPort.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiPhysicalOutputPort.mm (renamed from macosx/coremidi/JackCoreMidiPhysicalOutputPort.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiPort.mm (renamed from macosx/coremidi/JackCoreMidiPort.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiUtil.h | 3 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiUtil.mm (renamed from macosx/coremidi/JackCoreMidiUtil.cpp) | 15 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiVirtualInputPort.mm (renamed from macosx/coremidi/JackCoreMidiVirtualInputPort.cpp) | 0 | ||||
-rw-r--r-- | macosx/coremidi/JackCoreMidiVirtualOutputPort.mm (renamed from macosx/coremidi/JackCoreMidiVirtualOutputPort.cpp) | 0 | ||||
-rw-r--r-- | posix/JackNetUnixSocket.cpp | 1 | ||||
-rw-r--r-- | posix/JackPosixSemaphore.cpp | 12 | ||||
-rw-r--r-- | tests/iodelay.cpp | 1 | ||||
-rw-r--r-- | tests/wscript | 3 | ||||
-rw-r--r-- | waflib/extras/xcode.py | 312 | ||||
-rw-r--r-- | waflib/extras/xcode6.py | 656 | ||||
-rw-r--r-- | windows/JackNetWinSocket.cpp | 1 | ||||
-rw-r--r-- | wscript | 76 |
42 files changed, 2424 insertions, 183 deletions
diff --git a/.travis.yml b/.travis.yml index 33235eb3..103729fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,34 @@ +sudo: false +os: + - osx + - linux language: - - cpp + - cpp compiler: - - gcc -install: - - sudo apt-get install libsamplerate-dev libsndfile-dev libasound2-dev + - gcc + - clang +addons: + apt: + packages: + - libsamplerate-dev + - libsndfile-dev + - libasound2-dev + +before_install: + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew outdated pkg-config || brew upgrade pkg-config; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install aften; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install libsamplerate; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install libsndfile; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install opus; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install readline; fi + script: - - ./waf configure --alsa - - ./waf build + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then ./waf configure --alsa; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then ./waf configure --opus=no --readline=no; fi + - ./waf build + +matrix: + exclude: + - os: osx + compiler: gcc diff --git a/.wafupdaterc b/.wafupdaterc index 69f4293a..9d98b67f 100755 --- a/.wafupdaterc +++ b/.wafupdaterc @@ -133,6 +133,4 @@ WAFLIB_STRIP_EXTRAS=" valadoc why win32_opts - xcode - xcode6 " diff --git a/common/JackDebugClient.cpp b/common/JackDebugClient.cpp index 5ba5e897..3308c457 100644 --- a/common/JackDebugClient.cpp +++ b/common/JackDebugClient.cpp @@ -58,7 +58,7 @@ JackDebugClient::~JackDebugClient() if (fOpenPortNumber != 0) *fStream << "!!! WARNING !!! Some ports have not been unregistered ! Incorrect exiting !" << endl; if (fIsDeactivated != fIsActivated) - *fStream << "!!! ERROR !!! Client seem to not perform symetric activation-deactivation ! (not the same number of activate and deactivate)" << endl; + *fStream << "!!! ERROR !!! Client seem to not perform symmetric activation-deactivation ! (not the same number of activate and deactivate)" << endl; if (fIsClosed == 0) *fStream << "!!! ERROR !!! Client have not been closed with jack_client_close() !" << endl; diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index 1e57abc6..aae7ee7b 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -48,6 +48,7 @@ JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* en fEngine = engine; fGraphManager = NULL; fBeginDateUst = 0; + fEndDateUst = 0; fDelayedUsecs = 0.f; fIsMaster = true; fIsRunning = false; diff --git a/common/JackRequest.h b/common/JackRequest.h index 9e3d2b84..0262acbc 100644 --- a/common/JackRequest.h +++ b/common/JackRequest.h @@ -163,11 +163,14 @@ struct JackClientCheckRequest : public JackRequest int fUUID; int fOpen; - JackClientCheckRequest() - {} + JackClientCheckRequest() : fProtocol(0), fOptions(0), fUUID(0), fOpen(0) + { + memset(fName, 0, sizeof(fName)); + } JackClientCheckRequest(const char* name, int protocol, int options, int uuid, int open = false) : JackRequest(JackRequest::kClientCheck), fProtocol(protocol), fOptions(options), fUUID(uuid), fOpen(open) { + memset(fName, 0, sizeof(fName)); snprintf(fName, sizeof(fName), "%s", name); } @@ -206,10 +209,13 @@ struct JackClientCheckResult : public JackResult int fStatus; JackClientCheckResult(): JackResult(), fStatus(0) - {} + { + memset(fName, 0, sizeof(fName)); + } JackClientCheckResult(int32_t result, const char* name, int status) : JackResult(result), fStatus(status) { + memset(fName, 0, sizeof(fName)); snprintf(fName, sizeof(fName), "%s", name); } @@ -242,10 +248,13 @@ struct JackClientOpenRequest : public JackRequest int fUUID; char fName[JACK_CLIENT_NAME_SIZE+1]; - JackClientOpenRequest() - {} + JackClientOpenRequest() : fPID(0), fUUID(0) + { + memset(fName, 0, sizeof(fName)); + } JackClientOpenRequest(const char* name, int pid, int uuid): JackRequest(JackRequest::kClientOpen) { + memset(fName, 0, sizeof(fName)); snprintf(fName, sizeof(fName), "%s", name); fPID = pid; fUUID = uuid; @@ -318,7 +327,7 @@ struct JackClientCloseRequest : public JackRequest int fRefNum; - JackClientCloseRequest() + JackClientCloseRequest() : fRefNum(0) {} JackClientCloseRequest(int refnum): JackRequest(JackRequest::kClientClose), fRefNum(refnum) {} @@ -348,7 +357,7 @@ struct JackActivateRequest : public JackRequest int fRefNum; int fIsRealTime; - JackActivateRequest() + JackActivateRequest() : fRefNum(0), fIsRealTime(0) {} JackActivateRequest(int refnum, int is_real_time) : JackRequest(JackRequest::kActivateClient), fRefNum(refnum), fIsRealTime(is_real_time) @@ -380,7 +389,7 @@ struct JackDeactivateRequest : public JackRequest int fRefNum; - JackDeactivateRequest() + JackDeactivateRequest() : fRefNum(0) {} JackDeactivateRequest(int refnum): JackRequest(JackRequest::kDeactivateClient), fRefNum(refnum) {} @@ -413,13 +422,18 @@ struct JackPortRegisterRequest : public JackRequest unsigned int fFlags; unsigned int fBufferSize; - JackPortRegisterRequest() - {} + JackPortRegisterRequest() : fRefNum(0), fFlags(0), fBufferSize(0) + { + memset(fName, 0, sizeof(fName)); + memset(fPortType, 0, sizeof(fPortType)); + } JackPortRegisterRequest(int refnum, const char* name, const char* port_type, unsigned int flags, unsigned int buffer_size) : JackRequest(JackRequest::kRegisterPort), fRefNum(refnum), fFlags(flags), fBufferSize(buffer_size) { - strcpy(fName, name); - strcpy(fPortType, port_type); + memset(fName, 0, sizeof(fName)); + memset(fPortType, 0, sizeof(fPortType)); + strncpy(fName, name, sizeof(fName)-1); + strncpy(fPortType, port_type, sizeof(fPortType)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -484,7 +498,7 @@ struct JackPortUnRegisterRequest : public JackRequest int fRefNum; jack_port_id_t fPortIndex; - JackPortUnRegisterRequest() + JackPortUnRegisterRequest() : fRefNum(0), fPortIndex(0) {} JackPortUnRegisterRequest(int refnum, jack_port_id_t index) : JackRequest(JackRequest::kUnRegisterPort), fRefNum(refnum), fPortIndex(index) @@ -520,13 +534,18 @@ struct JackPortConnectNameRequest : public JackRequest char fSrc[REAL_JACK_PORT_NAME_SIZE+1]; // port full name char fDst[REAL_JACK_PORT_NAME_SIZE+1]; // port full name - JackPortConnectNameRequest() - {} + JackPortConnectNameRequest() : fRefNum(0) + { + memset(fSrc, 0, sizeof(fSrc)); + memset(fDst, 0, sizeof(fDst)); + } JackPortConnectNameRequest(int refnum, const char* src_name, const char* dst_name) : JackRequest(JackRequest::kConnectNamePorts), fRefNum(refnum) { - strcpy(fSrc, src_name); - strcpy(fDst, dst_name); + memset(fSrc, 0, sizeof(fSrc)); + memset(fDst, 0, sizeof(fDst)); + strncpy(fSrc, src_name, sizeof(fSrc)-1); + strncpy(fDst, dst_name, sizeof(fDst)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -562,13 +581,18 @@ struct JackPortDisconnectNameRequest : public JackRequest char fSrc[REAL_JACK_PORT_NAME_SIZE+1]; // port full name char fDst[REAL_JACK_PORT_NAME_SIZE+1]; // port full name - JackPortDisconnectNameRequest() - {} + JackPortDisconnectNameRequest() : fRefNum(0) + { + memset(fSrc, 0, sizeof(fSrc)); + memset(fDst, 0, sizeof(fDst)); + } JackPortDisconnectNameRequest(int refnum, const char* src_name, const char* dst_name) : JackRequest(JackRequest::kDisconnectNamePorts), fRefNum(refnum) { - strcpy(fSrc, src_name); - strcpy(fDst, dst_name); + memset(fSrc, 0, sizeof(fSrc)); + memset(fDst, 0, sizeof(fDst)); + strncpy(fSrc, src_name, sizeof(fSrc)-1); + strncpy(fDst, dst_name, sizeof(fDst)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -604,7 +628,7 @@ struct JackPortConnectRequest : public JackRequest jack_port_id_t fSrc; jack_port_id_t fDst; - JackPortConnectRequest() + JackPortConnectRequest() : fRefNum(0), fSrc(0), fDst(0) {} JackPortConnectRequest(int refnum, jack_port_id_t src, jack_port_id_t dst) : JackRequest(JackRequest::kConnectPorts), fRefNum(refnum), fSrc(src), fDst(dst) @@ -642,7 +666,7 @@ struct JackPortDisconnectRequest : public JackRequest jack_port_id_t fSrc; jack_port_id_t fDst; - JackPortDisconnectRequest() + JackPortDisconnectRequest() : fRefNum(0), fSrc(0), fDst(0) {} JackPortDisconnectRequest(int refnum, jack_port_id_t src, jack_port_id_t dst) : JackRequest(JackRequest::kDisconnectPorts), fRefNum(refnum), fSrc(src), fDst(dst) @@ -680,12 +704,15 @@ struct JackPortRenameRequest : public JackRequest jack_port_id_t fPort; char fName[JACK_PORT_NAME_SIZE + 1]; // port short name - JackPortRenameRequest() - {} + JackPortRenameRequest() : fRefNum(0), fPort(0) + { + memset(fName, 0, sizeof(fName)); + } JackPortRenameRequest(int refnum, jack_port_id_t port, const char* name) : JackRequest(JackRequest::kPortRename), fRefNum(refnum), fPort(port) { - strcpy(fName, name); + memset(fName, 0, sizeof(fName)); + strncpy(fName, name, sizeof(fName)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -719,7 +746,7 @@ struct JackSetBufferSizeRequest : public JackRequest jack_nframes_t fBufferSize; - JackSetBufferSizeRequest() + JackSetBufferSizeRequest() : fBufferSize(0) {} JackSetBufferSizeRequest(jack_nframes_t buffer_size) : JackRequest(JackRequest::kSetBufferSize), fBufferSize(buffer_size) @@ -749,7 +776,7 @@ struct JackSetFreeWheelRequest : public JackRequest int fOnOff; - JackSetFreeWheelRequest() + JackSetFreeWheelRequest() : fOnOff(0) {} JackSetFreeWheelRequest(int onoff) : JackRequest(JackRequest::kSetFreeWheel), fOnOff(onoff) @@ -806,7 +833,7 @@ struct JackReleaseTimebaseRequest : public JackRequest int fRefNum; - JackReleaseTimebaseRequest() + JackReleaseTimebaseRequest() : fRefNum(0) {} JackReleaseTimebaseRequest(int refnum) : JackRequest(JackRequest::kReleaseTimebase), fRefNum(refnum) @@ -838,7 +865,7 @@ struct JackSetTimebaseCallbackRequest : public JackRequest int fRefNum; int fConditionnal; - JackSetTimebaseCallbackRequest() + JackSetTimebaseCallbackRequest() : fRefNum(0), fConditionnal(0) {} JackSetTimebaseCallbackRequest(int refnum, int conditional) : JackRequest(JackRequest::kSetTimebaseCallback), fRefNum(refnum), fConditionnal(conditional) @@ -871,7 +898,7 @@ struct JackGetInternalClientNameRequest : public JackRequest int fRefNum; int fIntRefNum; - JackGetInternalClientNameRequest() + JackGetInternalClientNameRequest() : fRefNum(0), fIntRefNum(0) {} JackGetInternalClientNameRequest(int refnum, int int_ref) : JackRequest(JackRequest::kGetInternalClientName), fRefNum(refnum), fIntRefNum(int_ref) @@ -904,10 +931,13 @@ struct JackGetInternalClientNameResult : public JackResult char fName[JACK_CLIENT_NAME_SIZE+1]; JackGetInternalClientNameResult(): JackResult() - {} + { + memset(fName, 0, sizeof(fName)); + } JackGetInternalClientNameResult(int32_t result, const char* name) : JackResult(result) { + memset(fName, 0, sizeof(fName)); snprintf(fName, sizeof(fName), "%s", name); } @@ -938,11 +968,14 @@ struct JackInternalClientHandleRequest : public JackRequest int fRefNum; char fName[JACK_CLIENT_NAME_SIZE+1]; - JackInternalClientHandleRequest() - {} + JackInternalClientHandleRequest() : fRefNum(0) + { + memset(fName, 0, sizeof(fName)); + } JackInternalClientHandleRequest(int refnum, const char* client_name) : JackRequest(JackRequest::kInternalClientHandle), fRefNum(refnum) { + memset(fName, 0, sizeof(fName)); snprintf(fName, sizeof(fName), "%s", client_name); } @@ -973,7 +1006,7 @@ struct JackInternalClientHandleResult : public JackResult int fStatus; int fIntRefNum; - JackInternalClientHandleResult(): JackResult() + JackInternalClientHandleResult(): JackResult(), fStatus(0), fIntRefNum(0) {} JackInternalClientHandleResult(int32_t result, int status, int int_ref) : JackResult(result), fStatus(status), fIntRefNum(int_ref) @@ -1016,15 +1049,21 @@ struct JackInternalClientLoadRequest : public JackRequest int fOptions; int fUUID; - JackInternalClientLoadRequest() - {} + JackInternalClientLoadRequest() : fRefNum(0), fOptions(0), fUUID(0) + { + memset(fName, 0, sizeof(fName)); + memset(fDllName, 0, sizeof(fDllName)); + memset(fLoadInitName, 0, sizeof(fLoadInitName)); + } JackInternalClientLoadRequest(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int uuid ) : JackRequest(JackRequest::kInternalClientLoad), fRefNum(refnum), fOptions(options), fUUID(uuid) { + memset(fName, 0, sizeof(fName)); + memset(fDllName, 0, sizeof(fDllName)); + memset(fLoadInitName, 0, sizeof(fLoadInitName)); snprintf(fName, sizeof(fName), "%s", client_name); snprintf(fDllName, sizeof(fDllName), "%s", so_name); snprintf(fLoadInitName, sizeof(fLoadInitName), "%s", objet_data); - snprintf(fLoadInitName, sizeof(fLoadInitName), "%s", objet_data); } int Read(detail::JackChannelTransactionInterface* trans) @@ -1062,7 +1101,7 @@ struct JackInternalClientLoadResult : public JackResult int fStatus; int fIntRefNum; - JackInternalClientLoadResult(): JackResult() + JackInternalClientLoadResult(): JackResult(), fStatus(0), fIntRefNum(0) {} JackInternalClientLoadResult(int32_t result, int status, int int_ref) : JackResult(result), fStatus(status), fIntRefNum(int_ref) @@ -1097,7 +1136,7 @@ struct JackInternalClientUnloadRequest : public JackRequest int fRefNum; int fIntRefNum; - JackInternalClientUnloadRequest() + JackInternalClientUnloadRequest() : fRefNum(0), fIntRefNum(0) {} JackInternalClientUnloadRequest(int refnum, int int_ref) : JackRequest(JackRequest::kInternalClientUnload), fRefNum(refnum), fIntRefNum(int_ref) @@ -1129,7 +1168,7 @@ struct JackInternalClientUnloadResult : public JackResult int fStatus; - JackInternalClientUnloadResult(): JackResult() + JackInternalClientUnloadResult(): JackResult(), fStatus(0) {} JackInternalClientUnloadResult(int32_t result, int status) : JackResult(result), fStatus(status) @@ -1163,7 +1202,7 @@ struct JackClientNotificationRequest : public JackRequest int fNotify; int fValue; - JackClientNotificationRequest() + JackClientNotificationRequest() : fRefNum(0), fNotify(0), fValue(0) {} JackClientNotificationRequest(int refnum, int notify, int value) : JackRequest(JackRequest::kNotification), fRefNum(refnum), fNotify(notify), fValue(value) @@ -1198,14 +1237,20 @@ struct JackSessionCommand char fCommand[JACK_SESSION_COMMAND_SIZE]; jack_session_flags_t fFlags; - JackSessionCommand() - {} - + JackSessionCommand() : fFlags(JackSessionSaveError) + { + memset(fUUID, 0, sizeof(fUUID)); + memset(fClientName, 0, sizeof(fClientName)); + memset(fCommand, 0, sizeof(fCommand)); + } JackSessionCommand(const char *uuid, const char *clientname, const char *command, jack_session_flags_t flags) { - strncpy(fUUID, uuid, sizeof(fUUID)); - strncpy(fClientName, clientname, sizeof(fClientName)); - strncpy(fCommand, command, sizeof(fCommand)); + memset(fUUID, 0, sizeof(fUUID)); + memset(fClientName, 0, sizeof(fClientName)); + memset(fCommand, 0, sizeof(fCommand)); + strncpy(fUUID, uuid, sizeof(fUUID)-1); + strncpy(fClientName, clientname, sizeof(fClientName)-1); + strncpy(fCommand, command, sizeof(fCommand)-1); fFlags = flags; } }; @@ -1310,16 +1355,18 @@ struct JackSessionNotifyRequest : public JackRequest jack_session_event_type_t fEventType; int fRefNum; - JackSessionNotifyRequest() + JackSessionNotifyRequest() : fEventType(JackSessionSave), fRefNum(0) {} JackSessionNotifyRequest(int refnum, const char* path, jack_session_event_type_t type, const char* dst) : JackRequest(JackRequest::kSessionNotify), fEventType(type), fRefNum(refnum) { + memset(fPath, 0, sizeof(fPath)); + memset(fDst, 0, sizeof(fDst)); snprintf(fPath, sizeof(fPath), "%s", path); + fPath[JACK_MESSAGE_SIZE] = 0; if (dst) { snprintf(fDst, sizeof(fDst), "%s", dst); - } else { - fDst[0] = '\0'; + fDst[JACK_CLIENT_NAME_SIZE] = 0; } } @@ -1350,7 +1397,7 @@ struct JackSessionReplyRequest : public JackRequest { int fRefNum; - JackSessionReplyRequest() + JackSessionReplyRequest() : fRefNum(0) {} JackSessionReplyRequest(int refnum) @@ -1380,10 +1427,13 @@ struct JackClientNameResult : public JackResult char fName[JACK_CLIENT_NAME_SIZE+1]; JackClientNameResult(): JackResult() - {} + { + memset(fName, 0, sizeof(fName)); + } JackClientNameResult(int32_t result, const char* name) : JackResult(result) { + memset(fName, 0, sizeof(fName)); snprintf(fName, sizeof(fName), "%s", name); } @@ -1408,10 +1458,13 @@ struct JackUUIDResult : public JackResult char fUUID[JACK_UUID_SIZE]; JackUUIDResult(): JackResult() - {} + { + memset(fUUID, 0, sizeof(fUUID)); + } JackUUIDResult(int32_t result, const char* uuid) : JackResult(result) { + memset(fUUID, 0, sizeof(fUUID)); snprintf(fUUID, sizeof(fUUID), "%s", uuid); } @@ -1436,12 +1489,15 @@ struct JackGetUUIDRequest : public JackRequest char fName[JACK_CLIENT_NAME_SIZE+1]; JackGetUUIDRequest() - {} + { + memset(fName, 0, sizeof(fName)); + } JackGetUUIDRequest(const char* client_name) : JackRequest(JackRequest::kGetUUIDByClient) { - strncpy(fName, client_name, sizeof(fName)); + memset(fName, 0, sizeof(fName)); + strncpy(fName, client_name, sizeof(fName)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -1467,12 +1523,15 @@ struct JackGetClientNameRequest : public JackRequest char fUUID[JACK_UUID_SIZE]; JackGetClientNameRequest() - {} + { + memset(fUUID, 0, sizeof(fUUID)); + } JackGetClientNameRequest(const char* uuid) : JackRequest(JackRequest::kGetClientByUUID) { - strncpy(fUUID, uuid, sizeof(fUUID)); + memset(fUUID, 0, sizeof(fUUID)); + strncpy(fUUID, uuid, sizeof(fUUID)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -1499,14 +1558,19 @@ struct JackReserveNameRequest : public JackRequest char fName[JACK_CLIENT_NAME_SIZE+1]; char fUUID[JACK_UUID_SIZE]; - JackReserveNameRequest() - {} + JackReserveNameRequest() : fRefNum(0) + { + memset(fName, 0, sizeof(fName)); + memset(fUUID, 0, sizeof(fUUID)); + } JackReserveNameRequest(int refnum, const char *name, const char* uuid) : JackRequest(JackRequest::kReserveClientName), fRefNum(refnum) { - strncpy(fName, name, sizeof(fName)); - strncpy(fUUID, uuid, sizeof(fUUID)); + memset(fName, 0, sizeof(fName)); + memset(fUUID, 0, sizeof(fUUID)); + strncpy(fName, name, sizeof(fName)-1); + strncpy(fUUID, uuid, sizeof(fUUID)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -1536,12 +1600,15 @@ struct JackClientHasSessionCallbackRequest : public JackRequest char fName[JACK_CLIENT_NAME_SIZE+1]; JackClientHasSessionCallbackRequest() - {} + { + memset(fName, 0, sizeof(fName)); + } JackClientHasSessionCallbackRequest(const char *name) : JackRequest(JackRequest::kClientHasSessionCallback) { - strncpy(fName, name, sizeof(fName)); + memset(fName, 0, sizeof(fName)); + strncpy(fName, name, sizeof(fName)-1); } int Read(detail::JackChannelTransactionInterface* trans) @@ -1577,11 +1644,16 @@ struct JackClientNotification int fSync; char fMessage[JACK_MESSAGE_SIZE+1]; - JackClientNotification(): fNotify(-1), fValue1(-1), fValue2(-1) - {} + JackClientNotification(): fSize(0), fRefNum(0), fNotify(-1), fValue1(-1), fValue2(-1), fSync(0) + { + memset(fName, 0, sizeof(fName)); + memset(fMessage, 0, sizeof(fMessage)); + } JackClientNotification(const char* name, int refnum, int notify, int sync, const char* message, int value1, int value2) : fRefNum(refnum), fNotify(notify), fValue1(value1), fValue2(value2), fSync(sync) { + memset(fName, 0, sizeof(fName)); + memset(fMessage, 0, sizeof(fMessage)); snprintf(fName, sizeof(fName), "%s", name); snprintf(fMessage, sizeof(fMessage), "%s", message); fSize = Size(); diff --git a/common/Jackdmp.cpp b/common/Jackdmp.cpp index 55f2c671..eb5044cb 100644 --- a/common/Jackdmp.cpp +++ b/common/Jackdmp.cpp @@ -241,6 +241,15 @@ static void usage(FILE* file, jackctl_server_t *server, bool full = true) // Prototype to be found in libjackserver extern "C" void silent_jack_error_callback(const char *desc); +void print_version() +{ + printf( "jackdmp version " VERSION " tmpdir " + jack_server_dir " protocol %d" "\n", + JACK_PROTOCOL_VERSION); + exit(-1); + +} + int main(int argc, char** argv) { jackctl_server_t * server_ctl; @@ -249,7 +258,13 @@ int main(int argc, char** argv) jackctl_driver_t * master_driver_ctl; jackctl_driver_t * loopback_driver_ctl = NULL; int replace_registry = 0; - const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:" + + for(int a = 1; a < argc; ++a) { + if( !strcmp(argv[a], "--version") || !strcmp(argv[a], "-V") ) { + print_version(); + } + } + const char *options = "-d:X:I:P:uvshrRL:STFl:t:mn:p:" "a:" #ifdef __linux__ "c:" @@ -277,7 +292,6 @@ int main(int argc, char** argv) { "realtime-priority", 1, 0, 'P' }, { "timeout", 1, 0, 't' }, { "temporary", 0, 0, 'T' }, - { "version", 0, 0, 'V' }, { "silent", 0, 0, 's' }, { "sync", 0, 0, 'S' }, { "autoconnect", 1, 0, 'a' }, @@ -290,7 +304,6 @@ int main(int argc, char** argv) char** master_driver_args = NULL; int master_driver_nargs = 1; int loopback = 0; - bool show_version = false; jackctl_sigmask_t * sigmask; jackctl_parameter_t* param; union jackctl_parameter_value value; @@ -469,10 +482,6 @@ int main(int argc, char** argv) } break; - case 'V': - show_version = true; - break; - default: fprintf(stderr, "unknown option character %c\n", optopt); /*fallthru*/ @@ -490,14 +499,6 @@ int main(int argc, char** argv) jackctl_parameter_set_value(param, &value); } - if (show_version) { - printf( "jackdmp version " VERSION - " tmpdir " jack_server_dir - " protocol %d" - "\n", JACK_PROTOCOL_VERSION); - return -1; - } - if (!master_driver_name) { usage(stderr, server_ctl, false); goto destroy_server; diff --git a/common/jack/systemdeps.h b/common/jack/systemdeps.h index 23e48558..f316aeb7 100644 --- a/common/jack/systemdeps.h +++ b/common/jack/systemdeps.h @@ -120,7 +120,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #endif /* __APPLE__ || __linux__ || __sun__ || sun */ -#if defined(__arm__) || defined(__aarch64__) || defined(__ppc__) || defined(__powerpc__) +#if defined(__arm__) || defined(__aarch64__) || defined(__mips__) || defined(__ppc__) || defined(__powerpc__) #undef POST_PACKED_STRUCTURE #define POST_PACKED_STRUCTURE #endif /* __arm__ || __aarch64__ || __ppc__ || __powerpc__ */ diff --git a/common/memops.c b/common/memops.c index 2d416b64..a503ce2b 100644 --- a/common/memops.c +++ b/common/memops.c @@ -42,6 +42,10 @@ #endif #endif +#ifdef __ARM_NEON__ +#include <arm_neon.h> +#endif + /* Notes about these *_SCALING values. the MAX_<N>BIT values are floating point. when multiplied by @@ -193,13 +197,42 @@ static inline __m128i float_24_sse(__m128 s) } #endif + +#ifdef __ARM_NEON__ + +static inline float32x4_t clip(float32x4_t s, float32x4_t min, float32x4_t max) +{ + return vminq_f32(max, vmaxq_f32(s, min)); +} + +static inline int32x4_t float_24_neon(float32x4_t s) +{ + const float32x4_t upper_bound = vdupq_n_f32(NORMALIZED_FLOAT_MAX); + const float32x4_t lower_bound = vdupq_n_f32(NORMALIZED_FLOAT_MIN); + + float32x4_t clipped = clip(s, lower_bound, upper_bound); + float32x4_t scaled = vmulq_f32(clipped, vdupq_n_f32(SAMPLE_24BIT_SCALING)); + return vcvtq_s32_f32(scaled); +} + +static inline int16x4_t float_16_neon(float32x4_t s) +{ + const float32x4_t upper_bound = vdupq_n_f32(NORMALIZED_FLOAT_MAX); + const float32x4_t lower_bound = vdupq_n_f32(NORMALIZED_FLOAT_MIN); + + float32x4_t clipped = clip(s, lower_bound, upper_bound); + float32x4_t scaled = vmulq_f32(clipped, vdupq_n_f32(SAMPLE_16BIT_SCALING)); + return vmovn_s32(vcvtq_s32_f32(scaled)); +} +#endif + /* Linear Congruential noise generator. From the music-dsp list * less random than rand(), but good enough and 10x faster */ static unsigned int seed = 22222; static inline unsigned int fast_rand() { - seed = (seed * 96314165) + 907633515; + seed = (seed * 196314165) + 907633515; return seed; } @@ -248,6 +281,32 @@ void sample_move_dS_floatLE (char *dst, jack_default_audio_sample_t *src, unsign void sample_move_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) { +#ifdef __ARM_NEON__ + unsigned long unrolled = nsamples / 4; + nsamples = nsamples & 3; + + while (unrolled--) { + float32x4_t samples = vld1q_f32(src); + int32x4_t converted = float_24_neon(samples); + int32x4_t shifted = vshlq_n_s32(converted, 8); + shifted = vreinterpretq_s32_u8(vrev32q_u8(vreinterpretq_u8_s32(shifted))); + + switch(dst_skip) { + case 4: + vst1q_s32((int32_t*)dst, shifted); + break; + default: + vst1q_lane_s32((int32_t*)(dst), shifted, 0); + vst1q_lane_s32((int32_t*)(dst+dst_skip), shifted, 1); + vst1q_lane_s32((int32_t*)(dst+2*dst_skip), shifted, 2); + vst1q_lane_s32((int32_t*)(dst+3*dst_skip), shifted, 3); + break; + } + dst += 4*dst_skip; + src+= 4; + } +#endif + int32_t z; while (nsamples--) { @@ -321,7 +380,33 @@ void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigne src++; } -#else +#elif defined(__ARM_NEON__) + unsigned long unrolled = nsamples / 4; + nsamples = nsamples & 3; + + while (unrolled--) { + float32x4_t samples = vld1q_f32(src); + int32x4_t converted = float_24_neon(samples); + int32x4_t shifted = vshlq_n_s32(converted, 8); + + switch(dst_skip) { + case 4: + vst1q_s32((int32_t*)dst, shifted); + break; + default: + vst1q_lane_s32((int32_t*)(dst), shifted, 0); + vst1q_lane_s32((int32_t*)(dst+dst_skip), shifted, 1); + vst1q_lane_s32((int32_t*)(dst+2*dst_skip), shifted, 2); + vst1q_lane_s32((int32_t*)(dst+3*dst_skip), shifted, 3); + break; + } + dst += 4*dst_skip; + + src+= 4; + } +#endif + +#if !defined (__SSE2__) while (nsamples--) { float_24u32 (*src, *((int32_t*) dst)); dst += dst_skip; @@ -332,6 +417,38 @@ void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigne void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) { +#ifdef __ARM_NEON__ + float32x4_t factor = vdupq_n_f32(1.0 / SAMPLE_24BIT_SCALING); + unsigned long unrolled = nsamples / 4; + while (unrolled--) { + int32x4_t src128; + switch(src_skip) + { + case 4: + src128 = vld1q_s32((int32_t*)src); + break; + case 8: + src128 = vld2q_s32((int32_t*)src).val[0]; + break; + default: + src128 = vld1q_lane_s32((int32_t*)src, src128, 0); + src128 = vld1q_lane_s32((int32_t*)(src+src_skip), src128, 1); + src128 = vld1q_lane_s32((int32_t*)(src+2*src_skip), src128, 2); + src128 = vld1q_lane_s32((int32_t*)(src+3*src_skip), src128, 3); + break; + } + src128 = vreinterpretq_s32_u8(vrev32q_u8(vreinterpretq_u8_s32(src128))); + int32x4_t shifted = vshrq_n_s32(src128, 8); + float32x4_t as_float = vcvtq_f32_s32(shifted); + float32x4_t divided = vmulq_f32(as_float, factor); + vst1q_f32(dst, divided); + + src += 4*src_skip; + dst += 4; + } + nsamples = nsamples & 3; +#endif + /* ALERT: signed sign-extension portability !!! */ const jack_default_audio_sample_t scaling = 1.0/SAMPLE_24BIT_SCALING; @@ -389,6 +506,34 @@ void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigne dst += 4; } nsamples = nsamples & 3; +#elif defined(__ARM_NEON__) + unsigned long unrolled = nsamples / 4; + float32x4_t factor = vdupq_n_f32(1.0 / SAMPLE_24BIT_SCALING); + while (unrolled--) { + int32x4_t src128; + switch(src_skip) { + case 4: + src128 = vld1q_s32((int32_t*)src); + break; + case 8: + src128 = vld2q_s32((int32_t*)src).val[0]; + break; + default: + src128 = vld1q_lane_s32((int32_t*)src, src128, 0); + src128 = vld1q_lane_s32((int32_t*)(src+src_skip), src128, 1); + src128 = vld1q_lane_s32((int32_t*)(src+2*src_skip), src128, 2); + src128 = vld1q_lane_s32((int32_t*)(src+3*src_skip), src128, 3); + break; + } + int32x4_t shifted = vshrq_n_s32(src128, 8); + float32x4_t as_float = vcvtq_f32_s32(shifted); + float32x4_t divided = vmulq_f32(as_float, factor); + vst1q_f32(dst, divided); + + src += 4*src_skip; + dst += 4; + } + nsamples = nsamples & 3; #endif /* ALERT: signed sign-extension portability !!! */ @@ -403,6 +548,25 @@ void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigne void sample_move_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) { +#ifdef __ARM_NEON__ + unsigned long unrolled = nsamples / 4; + while (unrolled--) { + int i; + int32_t z[4]; + float32x4_t samples = vld1q_f32(src); + int32x4_t converted = float_24_neon(samples); + converted = vreinterpretq_s32_u8(vrev32q_u8(vreinterpretq_u8_s32(converted))); + vst1q_s32(z, converted); + + for (i = 0; i != 4; ++i) { + memcpy (dst, ((char*)(z+i))+1, 3); + dst += dst_skip; + } + src += 4; + } + nsamples = nsamples & 3; +#endif + int32_t z; while (nsamples--) { @@ -455,6 +619,22 @@ void sample_move_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned l nsamples -= 4; src += 4; } +#elif defined(__ARM_NEON__) + unsigned long unrolled = nsamples / 4; + while (unrolled--) { + int i; + int32_t z[4]; + float32x4_t samples = vld1q_f32(src); + int32x4_t converted = float_24_neon(samples); + vst1q_s32(z, converted); + + for (i = 0; i != 4; ++i) { + memcpy (dst, z+i, 3); + dst += dst_skip; + } + src += 4; + } + nsamples = nsamples & 3; #endif int32_t z; @@ -473,9 +653,41 @@ void sample_move_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned l void sample_move_dS_s24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) { + const jack_default_audio_sample_t scaling = 1.0/SAMPLE_24BIT_SCALING; + +#ifdef __ARM_NEON__ + // we shift 8 to the right by dividing by 256.0 -> no sign extra handling + const float32x4_t vscaling = vdupq_n_f32(scaling/256.0); + int32_t x[4]; + memset(x, 0, sizeof(x)); + unsigned long unrolled = nsamples / 4; + while (unrolled--) { +#if __BYTE_ORDER == __BIG_ENDIAN /* ARM big endian?? */ + // right aligned / inverse sequence below -> *256 + memcpy(((char*)&x[0])+1, src, 3); + memcpy(((char*)&x[1])+1, src+src_skip, 3); + memcpy(((char*)&x[2])+1, src+2*src_skip, 3); + memcpy(((char*)&x[3])+1, src+3*src_skip, 3); +#else + memcpy(&x[0], src, 3); + memcpy(&x[1], src+src_skip, 3); + memcpy(&x[2], src+2*src_skip, 3); + memcpy(&x[3], src+3*src_skip, 3); +#endif + src += 4 * src_skip; + + int32x4_t source = vld1q_s32(x); + source = vreinterpretq_s32_u8(vrev32q_u8(vreinterpretq_u8_s32(source))); + float32x4_t converted = vcvtq_f32_s32(source); + float32x4_t scaled = vmulq_f32(converted, vscaling); + vst1q_f32(dst, scaled); + dst += 4; + } + nsamples = nsamples & 3; +#endif + /* ALERT: signed sign-extension portability !!! */ - const jack_default_audio_sample_t scaling = 1.0/SAMPLE_24BIT_SCALING; while (nsamples--) { int x; #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -528,6 +740,34 @@ void sample_move_dS_s24 (jack_default_audio_sample_t *dst, char *src, unsigned l dst += 4; nsamples -= 4; } +#elif defined(__ARM_NEON__) + // we shift 8 to the right by dividing by 256.0 -> no sign extra handling + const float32x4_t vscaling = vdupq_n_f32(scaling/256.0); + int32_t x[4]; + memset(x, 0, sizeof(x)); + unsigned long unrolled = nsamples / 4; + while (unrolled--) { +#if __BYTE_ORDER == __BIG_ENDIAN /* ARM big endian?? */ + // left aligned -> *256 + memcpy(&x[0], src, 3); + memcpy(&x[1], src+src_skip, 3); + memcpy(&x[2], src+2*src_skip, 3); + memcpy(&x[3], src+3*src_skip, 3); +#else + memcpy(((char*)&x[0])+1, src, 3); + memcpy(((char*)&x[1])+1, src+src_skip, 3); + memcpy(((char*)&x[2])+1, src+2*src_skip, 3); + memcpy(((char*)&x[3])+1, src+3*src_skip, 3); +#endif + src += 4 * src_skip; + + int32x4_t source = vld1q_s32(x); + float32x4_t converted = vcvtq_f32_s32(source); + float32x4_t scaled = vmulq_f32(converted, vscaling); + vst1q_f32(dst, scaled); + dst += 4; + } + nsamples = nsamples & 3; #endif while (nsamples--) { @@ -547,6 +787,30 @@ void sample_move_dS_s24 (jack_default_audio_sample_t *dst, char *src, unsigned l void sample_move_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) { +#ifdef __ARM_NEON__ + unsigned long unrolled = nsamples / 4; + nsamples = nsamples & 3; + + while (unrolled--) { + float32x4_t samples = vld1q_f32(src); + int16x4_t converted = float_16_neon(samples); + converted = vreinterpret_s16_u8(vrev16_u8(vreinterpret_u8_s16(converted))); + + switch(dst_skip) { + case 2: + vst1_s16((int16_t*)dst, converted); + break; + default: + vst1_lane_s16((int16_t*)(dst), converted, 0); + vst1_lane_s16((int16_t*)(dst+dst_skip), converted, 1); + vst1_lane_s16((int16_t*)(dst+2*dst_skip), converted, 2); + vst1_lane_s16((int16_t*)(dst+3*dst_skip), converted, 3); + break; + } + dst += 4*dst_skip; + src+= 4; + } +#endif int16_t tmp; while (nsamples--) { @@ -574,6 +838,29 @@ void sample_move_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned void sample_move_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) { +#ifdef __ARM_NEON__ + unsigned long unrolled = nsamples / 4; + nsamples = nsamples & 3; + + while (unrolled--) { + float32x4_t samples = vld1q_f32(src); + int16x4_t converted = float_16_neon(samples); + + switch(dst_skip) { + case 2: + vst1_s16((int16_t*)dst, converted); + break; + default: + vst1_lane_s16((int16_t*)(dst), converted, 0); + vst1_lane_s16((int16_t*)(dst+dst_skip), converted, 1); + vst1_lane_s16((int16_t*)(dst+2*dst_skip), converted, 2); + vst1_lane_s16((int16_t*)(dst+3*dst_skip), converted, 3); + break; + } + dst += 4*dst_skip; + src+= 4; + } +#endif while (nsamples--) { float_16 (*src, *((int16_t*) dst)); dst += dst_skip; @@ -730,6 +1017,36 @@ void sample_move_dS_s16s (jack_default_audio_sample_t *dst, char *src, unsigned { short z; const jack_default_audio_sample_t scaling = 1.0/SAMPLE_16BIT_SCALING; +#ifdef __ARM_NEON__ + const float32x4_t vscaling = vdupq_n_f32(scaling); + unsigned long unrolled = nsamples / 4; + while (unrolled--) { + int16x4_t source16x4; + switch(src_skip) { + case 2: + source16x4 = vld1_s16((int16_t*)src); + break; + case 4: + source16x4 = vld2_s16((int16_t*)src).val[0]; + break; + default: + source16x4 = vld1_lane_s16((int16_t*)src, source16x4, 0); + source16x4 = vld1_lane_s16((int16_t*)(src+src_skip), source16x4, 1); + source16x4 = vld1_lane_s16((int16_t*)(src+2*src_skip), source16x4, 2); + source16x4 = vld1_lane_s16((int16_t*)(src+3*src_skip), source16x4, 3); + break; + } + source16x4 = vreinterpret_s16_u8(vrev16_u8(vreinterpret_u8_s16(source16x4))); + int32x4_t source32x4 = vmovl_s16(source16x4); + src += 4 * src_skip; + + float32x4_t converted = vcvtq_f32_s32(source32x4); + float32x4_t scaled = vmulq_f32(converted, vscaling); + vst1q_f32(dst, scaled); + dst += 4; + } + nsamples = nsamples & 3; +#endif /* ALERT: signed sign-extension portability !!! */ while (nsamples--) { @@ -752,6 +1069,36 @@ void sample_move_dS_s16 (jack_default_audio_sample_t *dst, char *src, unsigned l { /* ALERT: signed sign-extension portability !!! */ const jack_default_audio_sample_t scaling = 1.0/SAMPLE_16BIT_SCALING; +#ifdef __ARM_NEON__ + const float32x4_t vscaling = vdupq_n_f32(scaling); + unsigned long unrolled = nsamples / 4; + while (unrolled--) { + int16x4_t source16x4; + switch(src_skip) { + case 2: + source16x4 = vld1_s16((int16_t*)src); + break; + case 4: + source16x4 = vld2_s16((int16_t*)src).val[0]; + break; + default: + source16x4 = vld1_lane_s16((int16_t*)src, source16x4, 0); + source16x4 = vld1_lane_s16((int16_t*)(src+src_skip), source16x4, 1); + source16x4 = vld1_lane_s16((int16_t*)(src+2*src_skip), source16x4, 2); + source16x4 = vld1_lane_s16((int16_t*)(src+3*src_skip), source16x4, 3); + break; + } + int32x4_t source32x4 = vmovl_s16(source16x4); + src += 4 * src_skip; + + float32x4_t converted = vcvtq_f32_s32(source32x4); + float32x4_t scaled = vmulq_f32(converted, vscaling); + vst1q_f32(dst, scaled); + dst += 4; + } + nsamples = nsamples & 3; +#endif + while (nsamples--) { *dst = (*((short *) src)) * scaling; dst++; diff --git a/common/wscript b/common/wscript index b64d275f..860cbace 100644 --- a/common/wscript +++ b/common/wscript @@ -17,12 +17,14 @@ def configure(conf): conf.check(function_name='timeGetDevCaps', header_name=['windows.h', 'mmsystem.h'], lib='winmm', uselib_store="WINMM", define_name='HAVE_MMSYSTEM_H') conf.check(function_name='EnumProcesses', header_name=['windows.h', 'psapi.h'], lib='psapi', uselib_store="PSAPI", define_name='HAVE_PSAPI_H') -def create_jack_process_obj(bld, target, sources, uselib = None): +def create_jack_process_obj(bld, target, sources, uselib = None, framework = None): process = bld(features = ['cxx', 'cxxshlib']) if not bld.env['IS_WINDOWS']: process.env['cxxshlib_PATTERN'] = '%s.so' process.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] if bld.env['IS_MACOSX']: + if framework: + process.framework = framework env_includes = ['../macosx', '../posix', '../macosx/coreaudio'] if bld.env['IS_LINUX']: env_includes = ['../linux', '../posix', '../linux/alsa'] @@ -37,8 +39,6 @@ def create_jack_process_obj(bld, target, sources, uselib = None): if bld.env['IS_LINUX']: process.env.append_value("CPPFLAGS", "-fvisibility=hidden") if bld.env['IS_MACOSX']: - process.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") process.env.append_value("CPPFLAGS", "-fvisibility=hidden") process.install_path = '${ADDON_DIR}/' process.use = [uselib.name] @@ -83,10 +83,10 @@ def build(bld): 'JackDebugClient.cpp', 'timestamps.c', '../posix/JackPosixThread.cpp', - '../posix/JackPosixSemaphore.cpp', '../posix/JackPosixProcessSync.cpp', '../posix/JackPosixMutex.cpp', '../posix/JackSocket.cpp', + '../linux/JackLinuxFutex.cpp', '../linux/JackLinuxTime.c', ] includes = ['../linux', '../posix'] + includes @@ -113,8 +113,10 @@ def build(bld): 'timestamps.c', '../posix/JackPosixProcessSync.cpp', '../posix/JackPosixThread.cpp', - '../macosx/JackMachThread.cpp', - '../macosx/JackMachSemaphore.cpp', + '../posix/JackPosixMutex.cpp', + '../macosx/JackMachThread.mm', + #'../macosx/JackMachSemaphore.mm', + '../posix/JackPosixSemaphore.cpp', '../posix/JackSocket.cpp', '../macosx/JackMachTime.c', ] @@ -135,6 +137,8 @@ def build(bld): uselib.append('WINMM') clientlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) + if bld.env['IS_MACOSX']: + clientlib.framework = ['CoreAudio', 'Accelerate'] clientlib.defines = 'HAVE_CONFIG_H' clientlib.use = uselib if bld.env['IS_WINDOWS']: @@ -185,10 +189,7 @@ def build(bld): if bld.env['IS_MACOSX']: clientlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") - clientlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc -arch x86_64" - clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module") - clientlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") + clientlib.env.append_value("LINKFLAGS", "-single_module") if bld.env['IS_SUN']: clientlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") @@ -199,6 +200,8 @@ def build(bld): return serverlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) + if bld.env['IS_MACOSX']: + serverlib.framework = ['CoreAudio', 'CoreFoundation', 'Accelerate'] serverlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] serverlib.includes = includes serverlib.name = 'serverlib' @@ -285,16 +288,15 @@ def build(bld): if bld.env['IS_MACOSX']: serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") - serverlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc -arch x86_64") - serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework CoreFoundation -framework vecLib -single_module") - serverlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") + serverlib.env.append_value("LINKFLAGS", "-single_module") if bld.env['IS_SUN']: serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") if bld.env['BUILD_NETLIB']: netlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) + if bld.env['IS_MACOSX']: + netlib.framework = ['CoreAudio'] netlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] netlib.includes = includes netlib.name = 'netlib' @@ -303,6 +305,8 @@ def build(bld): if bld.env['IS_WINDOWS']: netlib.install_path = '${BINDIR}' netlib.use += ['WS2_32', 'WINMM'] + elif bld.env['IS_MACOSX']: + netlib.install_path = '${LIBDIR}' else: netlib.use += ['RT'] netlib.install_path = '${LIBDIR}' @@ -327,8 +331,8 @@ def build(bld): if bld.env['IS_MACOSX']: - netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../macosx/JackMachThread.cpp', '../macosx/JackMachTime.c'] - netlib.env.append_value("LINKFLAGS", "-framework CoreAudio -single_module") + netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../macosx/JackMachThread.mm', '../macosx/JackMachTime.c'] + netlib.env.append_value("LINKFLAGS", "-single_module") if bld.env['IS_WINDOWS']: netlib.source += ['../windows/JackNetWinSocket.cpp','../windows/JackWinThread.cpp', '../windows/JackMMCSS.cpp', '../windows/JackWinTime.c'] @@ -360,10 +364,19 @@ def build(bld): ] if bld.env['BUILD_ADAPTER'] and bld.env['IS_MACOSX']: - audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.cpp'] - process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) - process.env.append_value("LINKFLAGS", "-framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework CoreServices") - process.use = 'SAMPLERATE' + audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.mm'] + process = create_jack_process_obj(bld, + 'audioadapter', + audio_adapter_sources, + serverlib, + framework = [ + "CoreAudio", + "AudioUnit", + "AudioToolbox", + "CoreServices" + ] + ) + process.use += ['SAMPLERATE'] if bld.env['BUILD_ADAPTER'] and bld.env['IS_LINUX'] and bld.env['BUILD_DRIVER_ALSA']: audio_adapter_sources += ['../linux/alsa/JackAlsaAdapter.cpp'] diff --git a/dbus/sigsegv.c b/dbus/sigsegv.c index ee12f918..ead08e7d 100644 --- a/dbus/sigsegv.c +++ b/dbus/sigsegv.c @@ -27,7 +27,9 @@ #include <stdio.h> #include <signal.h> #include <dlfcn.h> -#include <execinfo.h> +#ifdef HAVE_EXECINFO_H +# include <execinfo.h> +#endif #include <errno.h> #ifndef NO_CPP_DEMANGLE char * __cxa_demangle(const char * __mangled_name, char * __output_buffer, size_t * __length, int * __status); @@ -104,20 +106,20 @@ static void signal_segv(int signum, siginfo_t* info, void*ptr) { jack_error("info.si_errno = %d", info->si_errno); jack_error("info.si_code = %d (%s)", info->si_code, si_code_str); jack_error("info.si_addr = %p", info->si_addr); -#if !defined(__alpha__) && !defined(__ia64__) && !defined(__FreeBSD_kernel__) && !defined(__arm__) && !defined(__hppa__) && !defined(__sh__) && !defined(__aarch64__) && !defined(nios2) +#if defined(HAVE_UCONTEXT) && defined(HAVE_NGREG) for(i = 0; i < NGREG; i++) jack_error("reg[%02d] = 0x" REGFORMAT, i, -#if defined(__powerpc64__) +#if defined(HAVE_UCONTEXT_GP_REGS) ucontext->uc_mcontext.gp_regs[i] -#elif defined(__powerpc__) +#elif defined(HAVE_UCONTEXT_UC_REGS) ucontext->uc_mcontext.uc_regs[i] -#elif defined(__sparc__) && defined(__arch64__) +#elif defined(HAVE_UCONTEXT_MC_GREGS) ucontext->uc_mcontext.mc_gregs[i] -#else +#elif defined(HAVE_UCONTEXT_GREGS) ucontext->uc_mcontext.gregs[i] #endif ); -#endif /* alpha, ia64, kFreeBSD, arm, hppa */ +#endif /* defined(HAVE_UCONTEXT) && defined(HAVE_NGREG) */ #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) # if defined(SIGSEGV_STACK_IA64) @@ -161,12 +163,16 @@ static void signal_segv(int signum, siginfo_t* info, void*ptr) { bp = (void**)bp[0]; } #else +# ifdef HAVE_EXECINFO_H jack_error("Stack trace (non-dedicated):"); sz = backtrace(bt, 20); strings = backtrace_symbols(bt, sz); for(i = 0; i < sz; ++i) jack_error("%s", strings[i]); +# else + jack_error("Stack trace not available"); +# endif #endif jack_error("End of stack trace"); exit (-1); diff --git a/example-clients/ipload.c b/example-clients/ipload.c index 4868de3b..702a79e4 100644 --- a/example-clients/ipload.c +++ b/example-clients/ipload.c @@ -32,11 +32,17 @@ char *intclient_name; char *load_name; char *load_init = ""; char *server_name = NULL; +int autoclose_opt = 0; int wait_opt = 0; +volatile int idling = 1; static void signal_handler (int sig) { + /* do nothing if internal client closed itself */ + if (idling == 0) + return; + jack_status_t status; fprintf (stderr, "signal received, unloading..."); @@ -45,17 +51,34 @@ signal_handler (int sig) fprintf (stderr, "(failed), status = 0x%2.0x\n", status); else fprintf (stderr, "(succeeded)\n"); + if (autoclose_opt) + jack_deactivate(client); jack_client_close (client); exit (0); } static void +registration_callback (const char *name, int reg, void *arg) +{ + if (reg || strcmp(intclient_name, name)) + return; + + /* this will stop the wait loop and thus close this application. */ + idling = 0; + return; + + /* unused */ + (void)arg; +} + +static void show_usage () { fprintf (stderr, "usage: %s [ options ] client-name [ load-name " "[ init-string]]\n\noptions:\n", client_name); fprintf (stderr, "\t-h, --help \t\t print help message\n" + "\t-a, --autoclose\t automatically close when intclient is unloaded\n" "\t-i, --init string\t initialize string\n" "\t-s, --server name\t select JACK server\n" "\t-w, --wait \t\t wait for signal, then unload\n" @@ -68,9 +91,10 @@ parse_args (int argc, char *argv[]) { int c; int option_index = 0; - char *short_options = "hi:s:w"; + char *short_options = "hai:s:w"; struct option long_options[] = { { "help", 0, 0, 'h' }, + { "autoclose", 0, 0, 'a' }, { "init", required_argument, 0, 'i' }, { "server", required_argument, 0, 's' }, { "wait", 0, 0, 'w' }, @@ -87,6 +111,9 @@ parse_args (int argc, char *argv[]) while ((c = getopt_long (argc, argv, short_options, long_options, &option_index)) >= 0) { switch (c) { + case 'a': + autoclose_opt = 1; + break; case 'i': load_init = optarg; break; @@ -103,6 +130,10 @@ parse_args (int argc, char *argv[]) } } + /* autoclose makes no sense without wait */ + if (autoclose_opt && ! wait_opt) + autoclose_opt = 0; + if (optind == argc) { /* no positional args? */ show_usage (); return 1; @@ -176,6 +207,11 @@ main (int argc, char *argv[]) free(name); } + if (autoclose_opt) { + jack_set_client_registration_callback(client, registration_callback, NULL); + jack_activate(client); + } + if (wait_opt) { /* define a signal handler to unload the client, then * wait for it to exit */ @@ -190,7 +226,7 @@ main (int argc, char *argv[]) signal(SIGINT, signal_handler); #endif - while (1) { + while (idling) { #ifdef WIN32 Sleep(1000); #else @@ -199,7 +235,11 @@ main (int argc, char *argv[]) } } - jack_client_close(client); + if (autoclose_opt) { + jack_deactivate(client); + } + + jack_client_close(client); return 0; } diff --git a/example-clients/simdtests.cpp b/example-clients/simdtests.cpp new file mode 100644 index 00000000..b74d50aa --- /dev/null +++ b/example-clients/simdtests.cpp @@ -0,0 +1,390 @@ +/* + * simdtests.c -- test accuraccy and performance of simd optimizations + * + * Copyright (C) 2017 Andreas Mueller. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* We must include all headers memops.c includes to avoid trouble with + * out namespace game below. + */ +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <memory.h> +#include <stdlib.h> +#include <stdint.h> +#include <limits.h> +#ifdef __linux__ +#include <endian.h> +#endif +#include "memops.h" + +#if defined (__SSE2__) && !defined (__sun__) +#include <emmintrin.h> +#ifdef __SSE4_1__ +#include <smmintrin.h> +#endif +#endif + +#ifdef __ARM_NEON__ +#include <arm_neon.h> +#endif + +// our additional headers +#include <time.h> + +/* Dirty: include mempos.c twice the second time with SIMD disabled + * so we can compare aceelerated non accelerated + */ +namespace accelerated { +#include "../common/memops.c" +} + +namespace origerated { +#ifdef __SSE2__ +#undef __SSE2__ +#endif + +#ifdef __ARM_NEON__ +#undef __ARM_NEON__ +#endif + +#include "../common/memops.c" +} + +// define conversion function types +typedef void (*t_jack_to_integer)( + char *dst, + jack_default_audio_sample_t *src, + unsigned long nsamples, + unsigned long dst_skip, + dither_state_t *state); + +typedef void (*t_integer_to_jack)( + jack_default_audio_sample_t *dst, + char *src, + unsigned long nsamples, + unsigned long src_skip); + +// define/setup test case data +typedef struct test_case_data { + uint32_t frame_size; + uint32_t sample_size; + bool reverse; + t_jack_to_integer jack_to_integer_accel; + t_jack_to_integer jack_to_integer_orig; + t_integer_to_jack integer_to_jack_accel; + t_integer_to_jack integer_to_jack_orig; + dither_state_t *ditherstate; + const char *name; +} test_case_data_t; + +test_case_data_t test_cases[] = { + { + 4, + 3, + true, + accelerated::sample_move_d32u24_sSs, + origerated::sample_move_d32u24_sSs, + accelerated::sample_move_dS_s32u24s, + origerated::sample_move_dS_s32u24s, + NULL, + "32u24s" }, + { + 4, + 3, + false, + accelerated::sample_move_d32u24_sS, + origerated::sample_move_d32u24_sS, + accelerated::sample_move_dS_s32u24, + origerated::sample_move_dS_s32u24, + NULL, + "32u24" }, + { + 3, + 3, + true, + accelerated::sample_move_d24_sSs, + origerated::sample_move_d24_sSs, + accelerated::sample_move_dS_s24s, + origerated::sample_move_dS_s24s, + NULL, + "24s" }, + { + 3, + 3, + false, + accelerated::sample_move_d24_sS, + origerated::sample_move_d24_sS, + accelerated::sample_move_dS_s24, + origerated::sample_move_dS_s24, + NULL, + "24" }, + { + 2, + 2, + true, + accelerated::sample_move_d16_sSs, + origerated::sample_move_d16_sSs, + accelerated::sample_move_dS_s16s, + origerated::sample_move_dS_s16s, + NULL, + "16s" }, + { + 2, + 2, + false, + accelerated::sample_move_d16_sS, + origerated::sample_move_d16_sS, + accelerated::sample_move_dS_s16, + origerated::sample_move_dS_s16, + NULL, + "16" }, +}; + +// we need to repeat for better accuracy at time measurement +const uint32_t retry_per_case = 1000; + +// setup test buffers +#define TESTBUFF_SIZE 1024 +jack_default_audio_sample_t jackbuffer_source[TESTBUFF_SIZE]; +// integer buffers: max 4 bytes per value / * 2 for stereo +char integerbuffer_accel[TESTBUFF_SIZE*4*2]; +char integerbuffer_orig[TESTBUFF_SIZE*4*2]; +// float buffers +jack_default_audio_sample_t jackfloatbuffer_accel[TESTBUFF_SIZE]; +jack_default_audio_sample_t jackfloatbuffer_orig[TESTBUFF_SIZE]; + +// comparing unsigned makes life easier +uint32_t extract_integer( + char* buff, + uint32_t offset, + uint32_t frame_size, + uint32_t sample_size, + bool big_endian) +{ + uint32_t retval = 0; + unsigned char* curr; + uint32_t mult = 1; + if(big_endian) { + curr = (unsigned char*)buff + offset + sample_size-1; + for(uint32_t i=0; i<sample_size; i++) { + retval += *(curr--) * mult; + mult*=256; + } + } + else { + curr = (unsigned char*)buff + offset + frame_size-sample_size; + for(uint32_t i=0; i<sample_size; i++) { + retval += *(curr++) * mult; + mult*=256; + } + } + return retval; +} + +int main(int argc, char *argv[]) +{ +// parse_arguments(argc, argv); + uint32_t maxerr_displayed = 10; + + // fill jackbuffer + for(int i=0; i<TESTBUFF_SIZE; i++) { + // ramp + jack_default_audio_sample_t value = + ((jack_default_audio_sample_t)((i % TESTBUFF_SIZE) - TESTBUFF_SIZE/2)) / (TESTBUFF_SIZE/2); + // force clipping + value *= 1.02; + jackbuffer_source[i] = value; + } + + for(uint32_t testcase=0; testcase<sizeof(test_cases)/sizeof(test_case_data_t); testcase++) { + // test mono/stereo + for(uint32_t channels=1; channels<=2; channels++) { + ////////////////////////////////////////////////////////////////////////////// + // jackfloat -> integer + + // clean target buffers + memset(integerbuffer_accel, 0, sizeof(integerbuffer_accel)); + memset(integerbuffer_orig, 0, sizeof(integerbuffer_orig)); + // accel + clock_t time_to_integer_accel = clock(); + for(uint32_t repetition=0; repetition<retry_per_case; repetition++) + { + test_cases[testcase].jack_to_integer_accel( + integerbuffer_accel, + jackbuffer_source, + TESTBUFF_SIZE, + test_cases[testcase].frame_size*channels, + test_cases[testcase].ditherstate); + } + float timediff_to_integer_accel = ((float)(clock() - time_to_integer_accel)) / CLOCKS_PER_SEC; + // orig + clock_t time_to_integer_orig = clock(); + for(uint32_t repetition=0; repetition<retry_per_case; repetition++) + { + test_cases[testcase].jack_to_integer_orig( + integerbuffer_orig, + jackbuffer_source, + TESTBUFF_SIZE, + test_cases[testcase].frame_size*channels, + test_cases[testcase].ditherstate); + } + float timediff_to_integer_orig = ((float)(clock() - time_to_integer_orig)) / CLOCKS_PER_SEC; + // output performance results + printf( + "JackFloat->Integer @%7.7s/%u: Orig %7.6f sec / Accel %7.6f sec -> Win: %5.2f %%\n", + test_cases[testcase].name, + channels, + timediff_to_integer_orig, + timediff_to_integer_accel, + (timediff_to_integer_orig/timediff_to_integer_accel-1)*100.0); + uint32_t int_deviation_max = 0; + uint32_t int_error_count = 0; + // output error (avoid spam -> limit error lines per test case) + for(uint32_t sample=0; sample<TESTBUFF_SIZE; sample++) { + uint32_t sample_offset = sample*test_cases[testcase].frame_size*channels; + // compare both results + uint32_t intval_accel=extract_integer( + integerbuffer_accel, + sample_offset, + test_cases[testcase].frame_size, + test_cases[testcase].sample_size, +#if __BYTE_ORDER == __BIG_ENDIAN + !test_cases[testcase].reverse); +#else + test_cases[testcase].reverse); +#endif + uint32_t intval_orig=extract_integer( + integerbuffer_orig, + sample_offset, + test_cases[testcase].frame_size, + test_cases[testcase].sample_size, +#if __BYTE_ORDER == __BIG_ENDIAN + !test_cases[testcase].reverse); +#else + test_cases[testcase].reverse); +#endif + if(intval_accel != intval_orig) { + if(int_error_count<maxerr_displayed) { + printf("Value error sample %u:", sample); + printf(" Orig 0x"); + char formatstr[10]; + sprintf(formatstr, "%%0%uX", test_cases[testcase].sample_size*2); + printf(formatstr, intval_orig); + printf(" Accel 0x"); + printf(formatstr, intval_accel); + printf("\n"); + } + int_error_count++; + uint32_t int_deviation; + if(intval_accel > intval_orig) + int_deviation = intval_accel-intval_orig; + else + int_deviation = intval_orig-intval_accel; + if(int_deviation > int_deviation_max) + int_deviation_max = int_deviation; + } + } + printf( + "JackFloat->Integer @%7.7s/%u: Errors: %u Max deviation %u\n", + test_cases[testcase].name, + channels, + int_error_count, + int_deviation_max); + + ////////////////////////////////////////////////////////////////////////////// + // integer -> jackfloat + + // clean target buffers + memset(jackfloatbuffer_accel, 0, sizeof(jackfloatbuffer_accel)); + memset(jackfloatbuffer_orig, 0, sizeof(jackfloatbuffer_orig)); + // accel + clock_t time_to_float_accel = clock(); + for(uint32_t repetition=0; repetition<retry_per_case; repetition++) + { + test_cases[testcase].integer_to_jack_accel( + jackfloatbuffer_accel, + integerbuffer_orig, + TESTBUFF_SIZE, + test_cases[testcase].frame_size*channels); + } + float timediff_to_float_accel = ((float)(clock() - time_to_float_accel)) / CLOCKS_PER_SEC; + // orig + clock_t time_to_float_orig = clock(); + for(uint32_t repetition=0; repetition<retry_per_case; repetition++) + { + test_cases[testcase].integer_to_jack_orig( + jackfloatbuffer_orig, + integerbuffer_orig, + TESTBUFF_SIZE, + test_cases[testcase].frame_size*channels); + } + float timediff_to_float_orig = ((float)(clock() - time_to_float_orig)) / CLOCKS_PER_SEC; + // output performance results + printf( + "Integer->JackFloat @%7.7s/%u: Orig %7.6f sec / Accel %7.6f sec -> Win: %5.2f %%\n", + test_cases[testcase].name, + channels, + timediff_to_float_orig, + timediff_to_float_accel, + (timediff_to_float_orig/timediff_to_float_accel-1)*100.0); + jack_default_audio_sample_t float_deviation_max = 0.0; + uint32_t float_error_count = 0; + // output error (avoid spam -> limit error lines per test case) + for(uint32_t sample=0; sample<TESTBUFF_SIZE; sample++) { + // For easier estimation/readabilty we scale floats back to integer + jack_default_audio_sample_t sample_scaling; + switch(test_cases[testcase].sample_size) { + case 2: + sample_scaling = SAMPLE_16BIT_SCALING; + break; + default: + sample_scaling = SAMPLE_24BIT_SCALING; + break; + } + jack_default_audio_sample_t floatval_accel = jackfloatbuffer_accel[sample] * sample_scaling; + jack_default_audio_sample_t floatval_orig = jackfloatbuffer_orig[sample] * sample_scaling; + // compare both results + jack_default_audio_sample_t float_deviation; + if(floatval_accel > floatval_orig) + float_deviation = floatval_accel-floatval_orig; + else + float_deviation = floatval_orig-floatval_accel; + if(float_deviation > float_deviation_max) + float_deviation_max = float_deviation; + // deviation > half bit => error + if(float_deviation > 0.5) { + if(float_error_count<maxerr_displayed) { + printf("Value error sample %u:", sample); + printf(" Orig %8.1f Accel %8.1f\n", floatval_orig, floatval_accel); + } + float_error_count++; + } + } + printf( + "Integer->JackFloat @%7.7s/%u: Errors: %u Max deviation %f\n", + test_cases[testcase].name, + channels, + float_error_count, + float_deviation_max); + + printf("\n"); + } + } + return 0; +} diff --git a/example-clients/transport.c b/example-clients/transport.c index c543b410..56b71c60 100644 --- a/example-clients/transport.c +++ b/example-clients/transport.c @@ -211,6 +211,29 @@ static void com_timeout(char *arg) jack_set_sync_timeout(client, (jack_time_t) (timeout*1000000)); } +/* Toggle between play and stop state */ +static void com_toggle(char *arg) +{ + jack_position_t current; + jack_transport_state_t transport_state; + + transport_state = jack_transport_query (client, ¤t); + + switch (transport_state) { + case JackTransportStopped: + com_play( arg ); + break; + case JackTransportRolling: + com_stop( arg ); + break; + case JackTransportStarting: + fprintf(stderr, "state: Starting - no transport toggling"); + break; + default: + fprintf(stderr, "unexpected state: no transport toggling"); + } +} + /* Command parsing based on GNU readline info examples. */ @@ -238,6 +261,7 @@ command_t commands[] = { {"stop", com_stop, "Stop transport"}, {"tempo", com_tempo, "Set beat tempo <beats_per_min>"}, {"timeout", com_timeout, "Set sync timeout in <seconds>"}, + {"toggle", com_toggle, "Toggle transport rolling"}, {"?", com_help, "Synonym for `help'" }, {(char *)NULL, (cmd_function_t *)NULL, (char *)NULL } }; diff --git a/example-clients/wscript b/example-clients/wscript index ba67614e..b2950f1f 100644 --- a/example-clients/wscript +++ b/example-clients/wscript @@ -28,7 +28,8 @@ example_programs = { 'jack_net_master' : 'netmaster.c', 'jack_latent_client' : 'latent_client.c', 'jack_midi_dump' : 'midi_dump.c', - 'jack_midi_latency_test' : 'midi_latency_test.c' + 'jack_midi_latency_test' : 'midi_latency_test.c', + 'jack_simdtests' : 'simdtests.cpp' } example_libs = { @@ -65,14 +66,13 @@ def build(bld): else: use = ['clientlib'] - prog = bld(features='c cprogram') + if bld.env['IS_MACOSX']: + prog = bld(features='c cprogram', framework = ["Foundation"]) + else: + prog = bld(features='c cprogram') prog.includes = os_incdir + ['../common/jack', '../common'] prog.source = example_program_source prog.use = use - if bld.env['IS_MACOSX']: - prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") - prog.env.append_value("LINKFLAGS", "") if bld.env['IS_LINUX']: prog.use += ['RT', 'M'] if bld.env['IS_SUN']: @@ -85,10 +85,6 @@ def build(bld): prog.includes = os_incdir + ['../common/jack', '../common'] prog.source = 'transport.c' prog.use = ['clientlib'] - if bld.env['IS_MACOSX']: - prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") - prog.env.append_value("LINKFLAGS", "") if bld.env['IS_LINUX']: prog.use += ['RT', 'READLINE'] if bld.env['IS_MACOSX']: @@ -103,9 +99,6 @@ def build(bld): prog.source = 'capture_client.c' prog.use = ['clientlib'] if bld.env['IS_MACOSX']: - prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") - prog.env.append_value("LINKFLAGS", "") prog.use += ['SNDFILE'] if bld.env['IS_LINUX']: prog.use += ['RT', 'SNDFILE'] @@ -146,10 +139,6 @@ def build(bld): lib.includes = os_incdir + ['../common/jack', '../common'] lib.target = example_lib lib.source = example_lib_source - if bld.env['IS_MACOSX']: - lib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #lib.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") - lib.env.append_value("LINKFLAGS", "") if bld.env['IS_SUN']: lib.env.append_value("LINKFLAGS", "-lm") lib.use = 'serverlib' diff --git a/linux/JackLinuxFutex.cpp b/linux/JackLinuxFutex.cpp new file mode 100644 index 00000000..6e897bc8 --- /dev/null +++ b/linux/JackLinuxFutex.cpp @@ -0,0 +1,243 @@ +/* +Copyright (C) 2004-2008 Grame +Copyright (C) 2016 Filipe Coelho + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "JackLinuxFutex.h" +#include "JackTools.h" +#include "JackConstants.h" +#include "JackError.h" +#include <fcntl.h> +#include <stdio.h> +#include <sys/mman.h> +#include <syscall.h> +#include <linux/futex.h> + +namespace Jack +{ + +void JackLinuxFutex::BuildName(const char* client_name, const char* server_name, char* res, int size) +{ + char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; + JackTools::RewriteName(client_name, ext_client_name); + if (getenv("JACK_PROMISCUOUS_SERVER")) { + snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); + } else { + snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); + } +} + +bool JackLinuxFutex::Signal() +{ + if (!fFutex) { + jack_error("JackLinuxFutex::Signal name = %s already deallocated!!", fName); + return false; + } + + if (fFlush) { + return true; + } + + if (! __sync_bool_compare_and_swap(&fFutex->futex, 0, 1)) + { + // already unlocked, do not wake futex + if (! fFutex->internal) return true; + } + + ::syscall(__NR_futex, fFutex, fFutex->internal ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1, NULL, NULL, 0); + return true; +} + +bool JackLinuxFutex::SignalAll() +{ + return Signal(); +} + +bool JackLinuxFutex::Wait() +{ + if (!fFutex) { + jack_error("JackLinuxFutex::Wait name = %s already deallocated!!", fName); + return false; + } + + if (fFutex->needsChange) + { + fFutex->needsChange = false; + fFutex->internal = !fFutex->internal; + } + + for (;;) + { + if (__sync_bool_compare_and_swap(&fFutex->futex, 1, 0)) + return true; + + if (::syscall(__NR_futex, fFutex, fFutex->internal ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, 0, NULL, NULL, 0) != 0 && errno != EWOULDBLOCK) + return false; + } +} + +bool JackLinuxFutex::TimedWait(long usec) +{ + if (!fFutex) { + jack_error("JackLinuxFutex::TimedWait name = %s already deallocated!!", fName); + return false; + } + + if (fFutex->needsChange) + { + fFutex->needsChange = false; + fFutex->internal = !fFutex->internal; + } + + const uint secs = usec / 1000000; + const int nsecs = (usec % 1000000) * 1000; + + const timespec timeout = { static_cast<time_t>(secs), nsecs }; + + for (;;) + { + if (__sync_bool_compare_and_swap(&fFutex->futex, 1, 0)) + return true; + + if (::syscall(__NR_futex, fFutex, fFutex->internal ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, 0, &timeout, NULL, 0) != 0 && errno != EWOULDBLOCK) + return false; + } +} + +// Server side : publish the futex in the global namespace +bool JackLinuxFutex::Allocate(const char* name, const char* server_name, int value, bool internal) +{ + BuildName(name, server_name, fName, sizeof(fName)); + jack_log("JackLinuxFutex::Allocate name = %s val = %ld", fName, value); + + if ((fSharedMem = shm_open(fName, O_CREAT | O_RDWR, 0777)) < 0) { + jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno)); + return false; + } + + ftruncate(fSharedMem, sizeof(FutexData)); + + if ((fFutex = (FutexData*)mmap(NULL, sizeof(FutexData), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fSharedMem, 0)) == NULL) { + jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno)); + close(fSharedMem); + fSharedMem = -1; + shm_unlink(fName); + return false; + } + + fPrivate = internal; + + fFutex->futex = value; + fFutex->internal = internal; + fFutex->wasInternal = internal; + fFutex->needsChange = false; + fFutex->externalCount = 0; + return true; +} + +// Client side : get the published futex from server +bool JackLinuxFutex::Connect(const char* name, const char* server_name) +{ + BuildName(name, server_name, fName, sizeof(fName)); + jack_log("JackLinuxFutex::Connect name = %s", fName); + + // Temporary... + if (fFutex) { + jack_log("Already connected name = %s", name); + return true; + } + + if ((fSharedMem = shm_open(fName, O_RDWR, 0)) < 0) { + jack_error("Connect: can't connect named futex name = %s err = %s", fName, strerror(errno)); + return false; + } + + if ((fFutex = (FutexData*)mmap(NULL, sizeof(FutexData), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fSharedMem, 0)) == NULL) { + jack_error("Connect: can't connect named futex name = %s err = %s", fName, strerror(errno)); + close(fSharedMem); + fSharedMem = -1; + return false; + } + + if (! fPrivate && fFutex->wasInternal) + { + const char* externalSync = getenv("JACK_INTERNAL_CLIENT_SYNC"); + + if (externalSync != NULL && strstr(fName, externalSync) != NULL && ++fFutex->externalCount == 1) + { + jack_error("Note: client %s running as external client temporarily", fName); + fFutex->needsChange = true; + } + } + + return true; +} + +bool JackLinuxFutex::ConnectInput(const char* name, const char* server_name) +{ + return Connect(name, server_name); +} + +bool JackLinuxFutex::ConnectOutput(const char* name, const char* server_name) +{ + return Connect(name, server_name); +} + +bool JackLinuxFutex::Disconnect() +{ + if (!fFutex) { + return true; + } + + if (! fPrivate && fFutex->wasInternal) + { + const char* externalSync = getenv("JACK_INTERNAL_CLIENT_SYNC"); + + if (externalSync != NULL && strstr(fName, externalSync) != NULL && --fFutex->externalCount == 0) + { + jack_error("Note: client %s now running as internal client again", fName); + fFutex->needsChange = true; + } + } + + munmap(fFutex, sizeof(FutexData)); + fFutex = NULL; + + close(fSharedMem); + fSharedMem = -1; + return true; +} + +// Server side : destroy the futex +void JackLinuxFutex::Destroy() +{ + if (!fFutex) { + return; + } + + munmap(fFutex, sizeof(FutexData)); + fFutex = NULL; + + close(fSharedMem); + fSharedMem = -1; + + shm_unlink(fName); +} + +} // end of namespace + diff --git a/linux/JackLinuxFutex.h b/linux/JackLinuxFutex.h new file mode 100644 index 00000000..5c8a7006 --- /dev/null +++ b/linux/JackLinuxFutex.h @@ -0,0 +1,85 @@ +/* +Copyright (C) 2004-2008 Grame +Copyright (C) 2016 Filipe Coelho + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __JackLinuxFutex__ +#define __JackLinuxFutex__ + +#include "JackSynchro.h" +#include "JackCompilerDeps.h" +#include <stddef.h> + +namespace Jack +{ + +/*! +\brief Inter process synchronization using Linux futex. + + Based on the JackPosixSemaphore class. + Adapted to work with linux futex to be as light as possible and also work in multiple architectures. + + Adds a new 'MakePrivate' function that makes the sync happen in the local process only, + making it even faster for internal clients. +*/ + +class SERVER_EXPORT JackLinuxFutex : public detail::JackSynchro +{ + + private: + struct FutexData { + int futex; // futex, needs to be 1st member + bool internal; // current internal state + bool wasInternal; // initial internal state, only changes in allocate + bool needsChange; // change state on next wait call + int externalCount; // how many external clients have connected + }; + + int fSharedMem; + FutexData* fFutex; + bool fPrivate; + + protected: + + void BuildName(const char* name, const char* server_name, char* res, int size); + + public: + + JackLinuxFutex():JackSynchro(), fSharedMem(-1), fFutex(NULL), fPrivate(false) + {} + + bool Signal(); + bool SignalAll(); + bool Wait(); + bool TimedWait(long usec); + + bool Allocate(const char* name, const char* server_name, int value, bool internal = false); + bool Connect(const char* name, const char* server_name); + bool ConnectInput(const char* name, const char* server_name); + bool ConnectOutput(const char* name, const char* server_name); + bool Disconnect(); + void Destroy(); + + void MakePrivate(bool priv); +}; + +} // end of namespace + + +#endif + diff --git a/linux/JackPlatformPlug_os.h b/linux/JackPlatformPlug_os.h index b480f453..60c9a585 100644 --- a/linux/JackPlatformPlug_os.h +++ b/linux/JackPlatformPlug_os.h @@ -54,8 +54,8 @@ namespace Jack { typedef JackPosixThread JackThread; } namespace Jack { typedef JackFifo JackSynchro; } */ -#include "JackPosixSemaphore.h" -namespace Jack { typedef JackPosixSemaphore JackSynchro; } +#include "JackLinuxFutex.h" +namespace Jack { typedef JackLinuxFutex JackSynchro; } /* __JackPlatformChannelTransaction__ */ /* diff --git a/linux/firewire/JackFFADODriver.cpp b/linux/firewire/JackFFADODriver.cpp index 91d999b5..10dfe27c 100644 --- a/linux/firewire/JackFFADODriver.cpp +++ b/linux/firewire/JackFFADODriver.cpp @@ -403,6 +403,11 @@ JackFFADODriver::ffado_driver_new (const char *name, // driver->client = client; driver->engine = NULL; + //from jack1 ffado_driver.c: put arg -dxxx to ffado device_info_t struct + driver->device_info.nb_device_spec_strings=1; + driver->device_info.device_spec_strings=(char**)calloc(1, sizeof(char *)); + driver->device_info.device_spec_strings[0]=strdup(params->device_info); + memset(&driver->device_options, 0, sizeof(driver->device_options)); driver->device_options.sample_rate = params->sample_rate; driver->device_options.period_size = params->period_size; diff --git a/macosx/JackMachSemaphore.cpp b/macosx/JackMachSemaphore.mm index 1e19329f..1e19329f 100644 --- a/macosx/JackMachSemaphore.cpp +++ b/macosx/JackMachSemaphore.mm diff --git a/macosx/JackMachThread.h b/macosx/JackMachThread.h index 1aad4cc6..1cd08fba 100644 --- a/macosx/JackMachThread.h +++ b/macosx/JackMachThread.h @@ -70,7 +70,7 @@ typedef unsigned char Boolean; #include "JackPosixThread.h" #ifndef MY_TARGET_OS_IPHONE -#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> +#include <MacTypes.h> #endif #include <mach/thread_policy.h> diff --git a/macosx/JackMachThread.cpp b/macosx/JackMachThread.mm index 061c7919..061c7919 100644 --- a/macosx/JackMachThread.cpp +++ b/macosx/JackMachThread.mm diff --git a/macosx/coreaudio/JackCoreAudioAdapter.cpp b/macosx/coreaudio/JackCoreAudioAdapter.mm index b0ff171d..b0ff171d 100644 --- a/macosx/coreaudio/JackCoreAudioAdapter.cpp +++ b/macosx/coreaudio/JackCoreAudioAdapter.mm diff --git a/macosx/coreaudio/JackCoreAudioDriver.cpp b/macosx/coreaudio/JackCoreAudioDriver.mm index d9448030..d9448030 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.cpp +++ b/macosx/coreaudio/JackCoreAudioDriver.mm diff --git a/macosx/coreaudio/TiPhoneCoreAudioRenderer.cpp b/macosx/coreaudio/TiPhoneCoreAudioRenderer.mm index dd2be73f..dd2be73f 100644 --- a/macosx/coreaudio/TiPhoneCoreAudioRenderer.cpp +++ b/macosx/coreaudio/TiPhoneCoreAudioRenderer.mm diff --git a/macosx/coremidi/JackCoreMidiDriver.cpp b/macosx/coremidi/JackCoreMidiDriver.mm index 16912ab6..16912ab6 100644 --- a/macosx/coremidi/JackCoreMidiDriver.cpp +++ b/macosx/coremidi/JackCoreMidiDriver.mm diff --git a/macosx/coremidi/JackCoreMidiInputPort.cpp b/macosx/coremidi/JackCoreMidiInputPort.mm index 7395c75e..7395c75e 100644 --- a/macosx/coremidi/JackCoreMidiInputPort.cpp +++ b/macosx/coremidi/JackCoreMidiInputPort.mm diff --git a/macosx/coremidi/JackCoreMidiOutputPort.cpp b/macosx/coremidi/JackCoreMidiOutputPort.mm index 9fcee2a4..9fcee2a4 100644 --- a/macosx/coremidi/JackCoreMidiOutputPort.cpp +++ b/macosx/coremidi/JackCoreMidiOutputPort.mm diff --git a/macosx/coremidi/JackCoreMidiPhysicalInputPort.cpp b/macosx/coremidi/JackCoreMidiPhysicalInputPort.mm index 748dbc17..748dbc17 100644 --- a/macosx/coremidi/JackCoreMidiPhysicalInputPort.cpp +++ b/macosx/coremidi/JackCoreMidiPhysicalInputPort.mm diff --git a/macosx/coremidi/JackCoreMidiPhysicalOutputPort.cpp b/macosx/coremidi/JackCoreMidiPhysicalOutputPort.mm index d8a4af25..d8a4af25 100644 --- a/macosx/coremidi/JackCoreMidiPhysicalOutputPort.cpp +++ b/macosx/coremidi/JackCoreMidiPhysicalOutputPort.mm diff --git a/macosx/coremidi/JackCoreMidiPort.cpp b/macosx/coremidi/JackCoreMidiPort.mm index 67367923..67367923 100644 --- a/macosx/coremidi/JackCoreMidiPort.cpp +++ b/macosx/coremidi/JackCoreMidiPort.mm diff --git a/macosx/coremidi/JackCoreMidiUtil.h b/macosx/coremidi/JackCoreMidiUtil.h index 4f24fc5b..b8ad84e9 100644 --- a/macosx/coremidi/JackCoreMidiUtil.h +++ b/macosx/coremidi/JackCoreMidiUtil.h @@ -22,8 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include <string> -#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> -#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Debugging.h> +#include <MacTypes.h> namespace Jack { diff --git a/macosx/coremidi/JackCoreMidiUtil.cpp b/macosx/coremidi/JackCoreMidiUtil.mm index d976e936..8014f572 100644 --- a/macosx/coremidi/JackCoreMidiUtil.cpp +++ b/macosx/coremidi/JackCoreMidiUtil.mm @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <sstream> +#include <Foundation/Foundation.h> #include "JackError.h" #include "JackCoreMidiUtil.h" @@ -25,13 +26,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. std::string Jack::GetMacOSErrorString(OSStatus status) { - const char *message = GetMacOSStatusErrorString(status); - if (! message) { - std::stringstream stream; - stream << "error (code: '" << status << "')"; - return stream.str(); + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + NSString *errorString = [error localizedDescription]; + std::string returnString; + if (errorString){ + returnString = std::string([errorString UTF8String]); + } else { + returnString = std::string("No error"); } - return std::string(message); + return returnString; } void diff --git a/macosx/coremidi/JackCoreMidiVirtualInputPort.cpp b/macosx/coremidi/JackCoreMidiVirtualInputPort.mm index 511a6efb..511a6efb 100644 --- a/macosx/coremidi/JackCoreMidiVirtualInputPort.cpp +++ b/macosx/coremidi/JackCoreMidiVirtualInputPort.mm diff --git a/macosx/coremidi/JackCoreMidiVirtualOutputPort.cpp b/macosx/coremidi/JackCoreMidiVirtualOutputPort.mm index 9bd1ebe9..9bd1ebe9 100644 --- a/macosx/coremidi/JackCoreMidiVirtualOutputPort.cpp +++ b/macosx/coremidi/JackCoreMidiVirtualOutputPort.mm diff --git a/posix/JackNetUnixSocket.cpp b/posix/JackNetUnixSocket.cpp index c12bc7d5..7a5585ef 100644 --- a/posix/JackNetUnixSocket.cpp +++ b/posix/JackNetUnixSocket.cpp @@ -414,6 +414,7 @@ namespace Jack if (addr_conv < 1) { return addr_conv; } + fSendAddr.sin_port = htons(fPort); #if defined(__sun__) || defined(sun) if (WaitWrite() < 0) { return -1; diff --git a/posix/JackPosixSemaphore.cpp b/posix/JackPosixSemaphore.cpp index 6eccbe58..9e511647 100644 --- a/posix/JackPosixSemaphore.cpp +++ b/posix/JackPosixSemaphore.cpp @@ -81,7 +81,6 @@ bool JackPosixSemaphore::SignalAll() return (res == 0); } -/* bool JackPosixSemaphore::Wait() { int res; @@ -91,17 +90,6 @@ bool JackPosixSemaphore::Wait() return false; } - if ((res = sem_wait(fSemaphore)) != 0) { - jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); - } - return (res == 0); -} -*/ - -bool JackPosixSemaphore::Wait() -{ - int res; - while ((res = sem_wait(fSemaphore) < 0)) { jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); if (errno != EINTR) { diff --git a/tests/iodelay.cpp b/tests/iodelay.cpp index 1ef470fd..f5c58364 100644 --- a/tests/iodelay.cpp +++ b/tests/iodelay.cpp @@ -20,6 +20,7 @@ #include <stdlib.h> #include <stdio.h> +#define __STDC_LIMIT_MACROS #include <stdint.h> #include <math.h> #include <unistd.h> diff --git a/tests/wscript b/tests/wscript index 70d48f0f..24d76e72 100644 --- a/tests/wscript +++ b/tests/wscript @@ -25,8 +25,5 @@ def build(bld): prog.source = test_program_sources if bld.env['IS_LINUX']: prog.uselib = 'RT' - if bld.env['IS_MACOSX']: - prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64") - #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") prog.use = 'clientlib' prog.target = test_program diff --git a/waflib/extras/xcode.py b/waflib/extras/xcode.py new file mode 100644 index 00000000..49a16919 --- /dev/null +++ b/waflib/extras/xcode.py @@ -0,0 +1,312 @@ +#! /usr/bin/env python +# encoding: utf-8 +# XCode 3/XCode 4 generator for Waf +# Nicolas Mercier 2011 + +""" +Usage: + +def options(opt): + opt.load('xcode') + +$ waf configure xcode +""" + +# TODO: support iOS projects + +from waflib import Context, TaskGen, Build, Utils +import os, sys + +HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' + +MAP_EXT = { + '.h' : "sourcecode.c.h", + + '.hh': "sourcecode.cpp.h", + '.inl': "sourcecode.cpp.h", + '.hpp': "sourcecode.cpp.h", + + '.c': "sourcecode.c.c", + + '.m': "sourcecode.c.objc", + + '.mm': "sourcecode.cpp.objcpp", + + '.cc': "sourcecode.cpp.cpp", + + '.cpp': "sourcecode.cpp.cpp", + '.C': "sourcecode.cpp.cpp", + '.cxx': "sourcecode.cpp.cpp", + '.c++': "sourcecode.cpp.cpp", + + '.l': "sourcecode.lex", # luthor + '.ll': "sourcecode.lex", + + '.y': "sourcecode.yacc", + '.yy': "sourcecode.yacc", + + '.plist': "text.plist.xml", + ".nib": "wrapper.nib", + ".xib": "text.xib", +} + + +part1 = 0 +part2 = 10000 +part3 = 0 +id = 562000999 +def newid(): + global id + id = id + 1 + return "%04X%04X%04X%012d" % (0, 10000, 0, id) + +class XCodeNode: + def __init__(self): + self._id = newid() + + def tostring(self, value): + if isinstance(value, dict): + result = "{\n" + for k,v in value.items(): + result = result + "\t\t\t%s = %s;\n" % (k, self.tostring(v)) + result = result + "\t\t}" + return result + elif isinstance(value, str): + return "\"%s\"" % value + elif isinstance(value, list): + result = "(\n" + for i in value: + result = result + "\t\t\t%s,\n" % self.tostring(i) + result = result + "\t\t)" + return result + elif isinstance(value, XCodeNode): + return value._id + else: + return str(value) + + def write_recursive(self, value, file): + if isinstance(value, dict): + for k,v in value.items(): + self.write_recursive(v, file) + elif isinstance(value, list): + for i in value: + self.write_recursive(i, file) + elif isinstance(value, XCodeNode): + value.write(file) + + def write(self, file): + for attribute,value in self.__dict__.items(): + if attribute[0] != '_': + self.write_recursive(value, file) + + w = file.write + w("\t%s = {\n" % self._id) + w("\t\tisa = %s;\n" % self.__class__.__name__) + for attribute,value in self.__dict__.items(): + if attribute[0] != '_': + w("\t\t%s = %s;\n" % (attribute, self.tostring(value))) + w("\t};\n\n") + + + +# Configurations +class XCBuildConfiguration(XCodeNode): + def __init__(self, name, settings = {}, env=None): + XCodeNode.__init__(self) + self.baseConfigurationReference = "" + self.buildSettings = settings + self.name = name + if env and env.ARCH: + settings['ARCHS'] = " ".join(env.ARCH) + + +class XCConfigurationList(XCodeNode): + def __init__(self, settings): + XCodeNode.__init__(self) + self.buildConfigurations = settings + self.defaultConfigurationIsVisible = 0 + self.defaultConfigurationName = settings and settings[0].name or "" + +# Group/Files +class PBXFileReference(XCodeNode): + def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"): + XCodeNode.__init__(self) + self.fileEncoding = 4 + if not filetype: + _, ext = os.path.splitext(name) + filetype = MAP_EXT.get(ext, 'text') + self.lastKnownFileType = filetype + self.name = name + self.path = path + self.sourceTree = sourcetree + +class PBXGroup(XCodeNode): + def __init__(self, name, sourcetree = "<group>"): + XCodeNode.__init__(self) + self.children = [] + self.name = name + self.sourceTree = sourcetree + + def add(self, root, sources): + folders = {} + def folder(n): + if not n.is_child_of(root): + return self + try: + return folders[n] + except KeyError: + f = PBXGroup(n.name) + p = folder(n.parent) + folders[n] = f + p.children.append(f) + return f + for s in sources: + f = folder(s.parent) + source = PBXFileReference(s.name, s.abspath()) + f.children.append(source) + + +# Targets +class PBXLegacyTarget(XCodeNode): + def __init__(self, action, target=''): + XCodeNode.__init__(self) + self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) + if not target: + self.buildArgumentsString = "%s %s" % (sys.argv[0], action) + else: + self.buildArgumentsString = "%s %s --targets=%s" % (sys.argv[0], action, target) + self.buildPhases = [] + self.buildToolPath = sys.executable + self.buildWorkingDirectory = "" + self.dependencies = [] + self.name = target or action + self.productName = target or action + self.passBuildSettingsInEnvironment = 0 + +class PBXShellScriptBuildPhase(XCodeNode): + def __init__(self, action, target): + XCodeNode.__init__(self) + self.buildActionMask = 2147483647 + self.files = [] + self.inputPaths = [] + self.outputPaths = [] + self.runOnlyForDeploymentPostProcessing = 0 + self.shellPath = "/bin/sh" + self.shellScript = "%s %s %s --targets=%s" % (sys.executable, sys.argv[0], action, target) + +class PBXNativeTarget(XCodeNode): + def __init__(self, action, target, node, env): + XCodeNode.__init__(self) + conf = XCBuildConfiguration('waf', {'PRODUCT_NAME':target, 'CONFIGURATION_BUILD_DIR':node.parent.abspath()}, env) + self.buildConfigurationList = XCConfigurationList([conf]) + self.buildPhases = [PBXShellScriptBuildPhase(action, target)] + self.buildRules = [] + self.dependencies = [] + self.name = target + self.productName = target + self.productType = "com.apple.product-type.application" + self.productReference = PBXFileReference(target, node.abspath(), 'wrapper.application', 'BUILT_PRODUCTS_DIR') + +# Root project object +class PBXProject(XCodeNode): + def __init__(self, name, version): + XCodeNode.__init__(self) + self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) + self.compatibilityVersion = version[0] + self.hasScannedForEncodings = 1; + self.mainGroup = PBXGroup(name) + self.projectRoot = "" + self.projectDirPath = "" + self.targets = [] + self._objectVersion = version[1] + self._output = PBXGroup('out') + self.mainGroup.children.append(self._output) + + def write(self, file): + w = file.write + w("// !$*UTF8*$!\n") + w("{\n") + w("\tarchiveVersion = 1;\n") + w("\tclasses = {\n") + w("\t};\n") + w("\tobjectVersion = %d;\n" % self._objectVersion) + w("\tobjects = {\n\n") + + XCodeNode.write(self, file) + + w("\t};\n") + w("\trootObject = %s;\n" % self._id) + w("}\n") + + def add_task_gen(self, tg): + if not getattr(tg, 'mac_app', False): + self.targets.append(PBXLegacyTarget('build', tg.name)) + else: + target = PBXNativeTarget('build', tg.name, tg.link_task.outputs[0].change_ext('.app'), tg.env) + self.targets.append(target) + self._output.children.append(target.productReference) + +class xcode(Build.BuildContext): + cmd = 'xcode' + fun = 'build' + + def collect_source(self, tg): + source_files = tg.to_nodes(getattr(tg, 'source', [])) + plist_files = tg.to_nodes(getattr(tg, 'mac_plist', [])) + resource_files = [tg.path.find_node(i) for i in Utils.to_list(getattr(tg, 'mac_resources', []))] + include_dirs = Utils.to_list(getattr(tg, 'includes', [])) + Utils.to_list(getattr(tg, 'export_dirs', [])) + include_files = [] + for x in include_dirs: + if not isinstance(x, str): + include_files.append(x) + continue + d = tg.path.find_node(x) + if d: + lst = [y for y in d.ant_glob(HEADERS_GLOB, flat=False)] + include_files.extend(lst) + + # remove duplicates + source = list(set(source_files + plist_files + resource_files + include_files)) + source.sort(key=lambda x: x.abspath()) + return source + + def execute(self): + """ + Entry point + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + + appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) + p = PBXProject(appname, ('Xcode 3.2', 46)) + + for g in self.groups: + for tg in g: + if not isinstance(tg, TaskGen.task_gen): + continue + + tg.post() + + features = Utils.to_list(getattr(tg, 'features', '')) + + group = PBXGroup(tg.name) + group.add(tg.path, self.collect_source(tg)) + p.mainGroup.children.append(group) + + if 'cprogram' or 'cxxprogram' in features: + p.add_task_gen(tg) + + + # targets that don't produce the executable but that you might want to run + p.targets.append(PBXLegacyTarget('configure')) + p.targets.append(PBXLegacyTarget('dist')) + p.targets.append(PBXLegacyTarget('install')) + p.targets.append(PBXLegacyTarget('check')) + node = self.srcnode.make_node('%s.xcodeproj' % appname) + node.mkdir() + node = node.make_node('project.pbxproj') + p.write(open(node.abspath(), 'w')) + + diff --git a/waflib/extras/xcode6.py b/waflib/extras/xcode6.py new file mode 100644 index 00000000..ea299ab9 --- /dev/null +++ b/waflib/extras/xcode6.py @@ -0,0 +1,656 @@ +#! /usr/bin/env python +# encoding: utf-8 +# XCode 3/XCode 4 generator for Waf +# Based on work by Nicolas Mercier 2011 +# Extended by Simon Warg 2015, https://github.com/mimon +# XCode project file format based on http://www.monobjc.net/xcode-project-file-format.html + +""" +Usage: + +See also demos/xcode6/ folder + +def options(opt): + opt.load('xcode6') + +def configure(cnf): + # <do your stuff> + + # For example + cnf.env.SDKROOT = 'macosx10.9' + + # Use cnf.PROJ_CONFIGURATION to completely set/override + # global project settings + # cnf.env.PROJ_CONFIGURATION = { + # 'Debug': { + # 'SDKROOT': 'macosx10.9' + # } + # 'MyCustomReleaseConfig': { + # 'SDKROOT': 'macosx10.10' + # } + # } + + # In the end of configure() do + cnf.load('xcode6') + +def build(bld): + + # Make a Framework target + bld.framework( + source_files={ + 'Include': bld.path.ant_glob('include/MyLib/*.h'), + 'Source': bld.path.ant_glob('src/MyLib/*.cpp') + }, + includes='include', + export_headers=bld.path.ant_glob('include/MyLib/*.h'), + target='MyLib', + ) + + # You can also make bld.dylib, bld.app, bld.stlib ... + +$ waf configure xcode6 +""" + +# TODO: support iOS projects + +from waflib import Context, TaskGen, Build, Utils, ConfigSet, Configure, Errors +from waflib.Build import BuildContext +import os, sys, random, time + +HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' + +MAP_EXT = { + '': "folder", + '.h' : "sourcecode.c.h", + + '.hh': "sourcecode.cpp.h", + '.inl': "sourcecode.cpp.h", + '.hpp': "sourcecode.cpp.h", + + '.c': "sourcecode.c.c", + + '.m': "sourcecode.c.objc", + + '.mm': "sourcecode.cpp.objcpp", + + '.cc': "sourcecode.cpp.cpp", + + '.cpp': "sourcecode.cpp.cpp", + '.C': "sourcecode.cpp.cpp", + '.cxx': "sourcecode.cpp.cpp", + '.c++': "sourcecode.cpp.cpp", + + '.l': "sourcecode.lex", # luthor + '.ll': "sourcecode.lex", + + '.y': "sourcecode.yacc", + '.yy': "sourcecode.yacc", + + '.plist': "text.plist.xml", + ".nib": "wrapper.nib", + ".xib": "text.xib", +} + +# Used in PBXNativeTarget elements +PRODUCT_TYPE_APPLICATION = 'com.apple.product-type.application' +PRODUCT_TYPE_FRAMEWORK = 'com.apple.product-type.framework' +PRODUCT_TYPE_EXECUTABLE = 'com.apple.product-type.tool' +PRODUCT_TYPE_LIB_STATIC = 'com.apple.product-type.library.static' +PRODUCT_TYPE_LIB_DYNAMIC = 'com.apple.product-type.library.dynamic' +PRODUCT_TYPE_EXTENSION = 'com.apple.product-type.kernel-extension' +PRODUCT_TYPE_IOKIT = 'com.apple.product-type.kernel-extension.iokit' + +# Used in PBXFileReference elements +FILE_TYPE_APPLICATION = 'wrapper.cfbundle' +FILE_TYPE_FRAMEWORK = 'wrapper.framework' +FILE_TYPE_LIB_DYNAMIC = 'compiled.mach-o.dylib' +FILE_TYPE_LIB_STATIC = 'archive.ar' +FILE_TYPE_EXECUTABLE = 'compiled.mach-o.executable' + +# Tuple packs of the above +TARGET_TYPE_FRAMEWORK = (PRODUCT_TYPE_FRAMEWORK, FILE_TYPE_FRAMEWORK, '.framework') +TARGET_TYPE_APPLICATION = (PRODUCT_TYPE_APPLICATION, FILE_TYPE_APPLICATION, '.app') +TARGET_TYPE_DYNAMIC_LIB = (PRODUCT_TYPE_LIB_DYNAMIC, FILE_TYPE_LIB_DYNAMIC, '.dylib') +TARGET_TYPE_STATIC_LIB = (PRODUCT_TYPE_LIB_STATIC, FILE_TYPE_LIB_STATIC, '.a') +TARGET_TYPE_EXECUTABLE = (PRODUCT_TYPE_EXECUTABLE, FILE_TYPE_EXECUTABLE, '') + +# Maps target type string to its data +TARGET_TYPES = { + 'framework': TARGET_TYPE_FRAMEWORK, + 'app': TARGET_TYPE_APPLICATION, + 'dylib': TARGET_TYPE_DYNAMIC_LIB, + 'stlib': TARGET_TYPE_STATIC_LIB, + 'exe' :TARGET_TYPE_EXECUTABLE, +} + +""" +Configuration of the global project settings. Sets an environment variable 'PROJ_CONFIGURATION' +which is a dictionary of configuration name and buildsettings pair. +E.g.: +env.PROJ_CONFIGURATION = { + 'Debug': { + 'ARCHS': 'x86', + ... + } + 'Release': { + 'ARCHS' x86_64' + ... + } +} +The user can define a completely customized dictionary in configure() stage. Otherwise a default Debug/Release will be created +based on env variable +""" +def configure(self): + if not self.env.PROJ_CONFIGURATION: + self.to_log("A default project configuration was created since no custom one was given in the configure(conf) stage. Define your custom project settings by adding PROJ_CONFIGURATION to env. The env.PROJ_CONFIGURATION must be a dictionary with at least one key, where each key is the configuration name, and the value is a dictionary of key/value settings.\n") + + # Check for any added config files added by the tool 'c_config'. + if 'cfg_files' in self.env: + self.env.INCLUDES = Utils.to_list(self.env.INCLUDES) + [os.path.abspath(os.path.dirname(f)) for f in self.env.cfg_files] + + # Create default project configuration? + if 'PROJ_CONFIGURATION' not in self.env: + self.env.PROJ_CONFIGURATION = { + "Debug": self.env.get_merged_dict(), + "Release": self.env.get_merged_dict(), + } + + # Some build settings are required to be present by XCode. We will supply default values + # if user hasn't defined any. + defaults_required = [('PRODUCT_NAME', '$(TARGET_NAME)')] + for cfgname,settings in self.env.PROJ_CONFIGURATION.iteritems(): + for default_var, default_val in defaults_required: + if default_var not in settings: + settings[default_var] = default_val + + # Error check customization + if not isinstance(self.env.PROJ_CONFIGURATION, dict): + raise Errors.ConfigurationError("The env.PROJ_CONFIGURATION must be a dictionary with at least one key, where each key is the configuration name, and the value is a dictionary of key/value settings.") + +part1 = 0 +part2 = 10000 +part3 = 0 +id = 562000999 +def newid(): + global id + id = id + 1 + return "%04X%04X%04X%012d" % (0, 10000, 0, id) + +class XCodeNode: + def __init__(self): + self._id = newid() + self._been_written = False + + def tostring(self, value): + if isinstance(value, dict): + result = "{\n" + for k,v in value.items(): + result = result + "\t\t\t%s = %s;\n" % (k, self.tostring(v)) + result = result + "\t\t}" + return result + elif isinstance(value, str): + return "\"%s\"" % value + elif isinstance(value, list): + result = "(\n" + for i in value: + result = result + "\t\t\t%s,\n" % self.tostring(i) + result = result + "\t\t)" + return result + elif isinstance(value, XCodeNode): + return value._id + else: + return str(value) + + def write_recursive(self, value, file): + if isinstance(value, dict): + for k,v in value.items(): + self.write_recursive(v, file) + elif isinstance(value, list): + for i in value: + self.write_recursive(i, file) + elif isinstance(value, XCodeNode): + value.write(file) + + def write(self, file): + if not self._been_written: + self._been_written = True + for attribute,value in self.__dict__.items(): + if attribute[0] != '_': + self.write_recursive(value, file) + w = file.write + w("\t%s = {\n" % self._id) + w("\t\tisa = %s;\n" % self.__class__.__name__) + for attribute,value in self.__dict__.items(): + if attribute[0] != '_': + w("\t\t%s = %s;\n" % (attribute, self.tostring(value))) + w("\t};\n\n") + +# Configurations +class XCBuildConfiguration(XCodeNode): + def __init__(self, name, settings = {}, env=None): + XCodeNode.__init__(self) + self.baseConfigurationReference = "" + self.buildSettings = settings + self.name = name + if env and env.ARCH: + settings['ARCHS'] = " ".join(env.ARCH) + + +class XCConfigurationList(XCodeNode): + def __init__(self, configlst): + """ :param configlst: list of XCConfigurationList """ + XCodeNode.__init__(self) + self.buildConfigurations = configlst + self.defaultConfigurationIsVisible = 0 + self.defaultConfigurationName = configlst and configlst[0].name or "" + +# Group/Files +class PBXFileReference(XCodeNode): + def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"): + XCodeNode.__init__(self) + self.fileEncoding = 4 + if not filetype: + _, ext = os.path.splitext(name) + filetype = MAP_EXT.get(ext, 'text') + self.lastKnownFileType = filetype + self.name = name + self.path = path + self.sourceTree = sourcetree + + def __hash__(self): + return (self.path+self.name).__hash__() + + def __eq__(self, other): + return (self.path, self.name) == (other.path, other.name) + +class PBXBuildFile(XCodeNode): + """ This element indicate a file reference that is used in a PBXBuildPhase (either as an include or resource). """ + def __init__(self, fileRef, settings={}): + XCodeNode.__init__(self) + + # fileRef is a reference to a PBXFileReference object + self.fileRef = fileRef + + # A map of key/value pairs for additionnal settings. + self.settings = settings + + def __hash__(self): + return (self.fileRef).__hash__() + + def __eq__(self, other): + return self.fileRef == other.fileRef + +class PBXGroup(XCodeNode): + def __init__(self, name, sourcetree = "<group>"): + XCodeNode.__init__(self) + self.children = [] + self.name = name + self.sourceTree = sourcetree + + def add(self, sources): + """ sources param should be a list of PBXFileReference objects """ + self.children.extend(sources) + +class PBXContainerItemProxy(XCodeNode): + """ This is the element for to decorate a target item. """ + def __init__(self, containerPortal, remoteGlobalIDString, remoteInfo='', proxyType=1): + XCodeNode.__init__(self) + self.containerPortal = containerPortal # PBXProject + self.remoteGlobalIDString = remoteGlobalIDString # PBXNativeTarget + self.remoteInfo = remoteInfo # Target name + self.proxyType = proxyType + + +class PBXTargetDependency(XCodeNode): + """ This is the element for referencing other target through content proxies. """ + def __init__(self, native_target, proxy): + XCodeNode.__init__(self) + self.target = native_target + self.targetProxy = proxy + +class PBXFrameworksBuildPhase(XCodeNode): + """ This is the element for the framework link build phase, i.e. linking to frameworks """ + def __init__(self, pbxbuildfiles): + XCodeNode.__init__(self) + self.buildActionMask = 2147483647 + self.runOnlyForDeploymentPostprocessing = 0 + self.files = pbxbuildfiles #List of PBXBuildFile (.o, .framework, .dylib) + +class PBXHeadersBuildPhase(XCodeNode): + """ This is the element for adding header files to be packaged into the .framework """ + def __init__(self, pbxbuildfiles): + XCodeNode.__init__(self) + self.buildActionMask = 2147483647 + self.runOnlyForDeploymentPostprocessing = 0 + self.files = pbxbuildfiles #List of PBXBuildFile (.o, .framework, .dylib) + +class PBXCopyFilesBuildPhase(XCodeNode): + """ + Represents the PBXCopyFilesBuildPhase section. PBXBuildFile + can be added to this node to copy files after build is done. + """ + def __init__(self, pbxbuildfiles, dstpath, dstSubpathSpec=0, *args, **kwargs): + XCodeNode.__init__(self) + self.files = pbxbuildfiles + self.dstPath = dstpath + self.dstSubfolderSpec = dstSubpathSpec + +class PBXSourcesBuildPhase(XCodeNode): + """ Represents the 'Compile Sources' build phase in a Xcode target """ + def __init__(self, buildfiles): + XCodeNode.__init__(self) + self.files = buildfiles # List of PBXBuildFile objects + +class PBXLegacyTarget(XCodeNode): + def __init__(self, action, target=''): + XCodeNode.__init__(self) + self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) + if not target: + self.buildArgumentsString = "%s %s" % (sys.argv[0], action) + else: + self.buildArgumentsString = "%s %s --targets=%s" % (sys.argv[0], action, target) + self.buildPhases = [] + self.buildToolPath = sys.executable + self.buildWorkingDirectory = "" + self.dependencies = [] + self.name = target or action + self.productName = target or action + self.passBuildSettingsInEnvironment = 0 + +class PBXShellScriptBuildPhase(XCodeNode): + def __init__(self, action, target): + XCodeNode.__init__(self) + self.buildActionMask = 2147483647 + self.files = [] + self.inputPaths = [] + self.outputPaths = [] + self.runOnlyForDeploymentPostProcessing = 0 + self.shellPath = "/bin/sh" + self.shellScript = "%s %s %s --targets=%s" % (sys.executable, sys.argv[0], action, target) + +class PBXNativeTarget(XCodeNode): + """ Represents a target in XCode, e.g. App, DyLib, Framework etc. """ + def __init__(self, target, node, target_type=TARGET_TYPE_APPLICATION, configlist=[], buildphases=[]): + XCodeNode.__init__(self) + product_type = target_type[0] + file_type = target_type[1] + + self.buildConfigurationList = XCConfigurationList(configlist) + self.buildPhases = buildphases + self.buildRules = [] + self.dependencies = [] + self.name = target + self.productName = target + self.productType = product_type # See TARGET_TYPE_ tuples constants + self.productReference = PBXFileReference(node.name, node.abspath(), file_type, '') + + def add_configuration(self, cf): + """ :type cf: XCBuildConfiguration """ + self.buildConfigurationList.buildConfigurations.append(cf) + + def add_build_phase(self, phase): + # Some build phase types may appear only once. If a phase type already exists, then merge them. + if ( (phase.__class__ == PBXFrameworksBuildPhase) + or (phase.__class__ == PBXSourcesBuildPhase) ): + for b in self.buildPhases: + if b.__class__ == phase.__class__: + b.files.extend(phase.files) + return + self.buildPhases.append(phase) + + def add_dependency(self, depnd): + self.dependencies.append(depnd) + +# Root project object +class PBXProject(XCodeNode): + def __init__(self, name, version, env): + XCodeNode.__init__(self) + + if not isinstance(env.PROJ_CONFIGURATION, dict): + raise Errors.WafError("Error: env.PROJ_CONFIGURATION must be a dictionary. This is done for you if you do not define one yourself. However, did you load the xcode module at the end of your wscript configure() ?") + + # Retreive project configuration + configurations = [] + for config_name, settings in env.PROJ_CONFIGURATION.items(): + cf = XCBuildConfiguration(config_name, settings) + configurations.append(cf) + + self.buildConfigurationList = XCConfigurationList(configurations) + self.compatibilityVersion = version[0] + self.hasScannedForEncodings = 1; + self.mainGroup = PBXGroup(name) + self.projectRoot = "" + self.projectDirPath = "" + self.targets = [] + self._objectVersion = version[1] + + def create_target_dependency(self, target, name): + """ : param target : PXBNativeTarget """ + proxy = PBXContainerItemProxy(self, target, name) + dependecy = PBXTargetDependency(target, proxy) + return dependecy + + def write(self, file): + + # Make sure this is written only once + if self._been_written: + return + + w = file.write + w("// !$*UTF8*$!\n") + w("{\n") + w("\tarchiveVersion = 1;\n") + w("\tclasses = {\n") + w("\t};\n") + w("\tobjectVersion = %d;\n" % self._objectVersion) + w("\tobjects = {\n\n") + + XCodeNode.write(self, file) + + w("\t};\n") + w("\trootObject = %s;\n" % self._id) + w("}\n") + + def add_target(self, target): + self.targets.append(target) + + def get_target(self, name): + """ Get a reference to PBXNativeTarget if it exists """ + for t in self.targets: + if t.name == name: + return t + return None + +class xcode(Build.BuildContext): + cmd = 'xcode6' + fun = 'build' + + file_refs = dict() + build_files = dict() + + def as_nodes(self, files): + """ Returns a list of waflib.Nodes from a list of string of file paths """ + nodes = [] + for x in files: + if not isinstance(x, str): + d = x + else: + d = self.srcnode.find_node(x) + nodes.append(d) + return nodes + + def create_group(self, name, files): + """ + Returns a new PBXGroup containing the files (paths) passed in the files arg + :type files: string + """ + group = PBXGroup(name) + """ + Do not use unique file reference here, since XCode seem to allow only one file reference + to be referenced by a group. + """ + files = [(PBXFileReference(d.name, d.abspath())) for d in self.as_nodes(files)] + group.add(files) + return group + + def unique_filereference(self, fileref): + """ + Returns a unique fileref, possibly an existing one if the paths are the same. + Use this after you've constructed a PBXFileReference to make sure there is + only one PBXFileReference for the same file in the same project. + """ + if fileref not in self.file_refs: + self.file_refs[fileref] = fileref + return self.file_refs[fileref] + + def unique_buildfile(self, buildfile): + """ + Returns a unique buildfile, possibly an existing one. + Use this after you've constructed a PBXBuildFile to make sure there is + only one PBXBuildFile for the same file in the same project. + """ + if buildfile not in self.build_files: + self.build_files[buildfile] = buildfile + return self.build_files[buildfile] + + def execute(self): + """ + Entry point + """ + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + + appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) + + p = PBXProject(appname, ('Xcode 3.2', 46), self.env) + + # If we don't create a Products group, then + # XCode will create one, which entails that + # we'll start to see duplicate files in the UI + # for some reason. + products_group = PBXGroup('Products') + p.mainGroup.children.append(products_group) + + for g in self.groups: + for tg in g: + if not isinstance(tg, TaskGen.task_gen): + continue + + tg.post() + + target_group = PBXGroup(tg.name) + p.mainGroup.children.append(target_group) + + # Determine what type to build - framework, app bundle etc. + target_type = getattr(tg, 'target_type', 'app') + if target_type not in TARGET_TYPES: + raise Errors.WafError("Target type '%s' does not exists. Available options are '%s'. In target '%s'" % (target_type, "', '".join(TARGET_TYPES.keys()), tg.name)) + else: + target_type = TARGET_TYPES[target_type] + file_ext = target_type[2] + + # Create the output node + target_node = tg.path.find_or_declare(tg.name+file_ext) + + target = PBXNativeTarget(tg.name, target_node, target_type, [], []) + + products_group.children.append(target.productReference) + + if hasattr(tg, 'source_files'): + # Create list of PBXFileReferences + sources = [] + if isinstance(tg.source_files, dict): + for grpname,files in tg.source_files.items(): + group = self.create_group(grpname, files) + target_group.children.append(group) + sources.extend(group.children) + elif isinstance(tg.source_files, list): + group = self.create_group("Source", tg.source_files) + target_group.children.append(group) + sources.extend(group.children) + else: + self.to_log("Argument 'source_files' passed to target '%s' was not a dictionary. Hence, some source files may not be included. Please provide a dictionary of source files, with group name as key and list of source files as value.\n" % tg.name) + + supported_extensions = ['.c', '.cpp', '.m', '.mm'] + sources = filter(lambda fileref: os.path.splitext(fileref.path)[1] in supported_extensions, sources) + buildfiles = [self.unique_buildfile(PBXBuildFile(fileref)) for fileref in sources] + target.add_build_phase(PBXSourcesBuildPhase(buildfiles)) + + # Create build settings which can override the project settings. Defaults to none if user + # did not pass argument. However, this will be filled up further below with target specfic + # search paths, libs to link etc. + settings = getattr(tg, 'settings', {}) + + # Check if any framework to link against is some other target we've made + libs = getattr(tg, 'tmp_use_seen', []) + for lib in libs: + use_target = p.get_target(lib) + if use_target: + # Create an XCode dependency so that XCode knows to build the other target before this target + target.add_dependency(p.create_target_dependency(use_target, use_target.name)) + target.add_build_phase(PBXFrameworksBuildPhase([PBXBuildFile(use_target.productReference)])) + if lib in tg.env.LIB: + tg.env.LIB = list(filter(lambda x: x != lib, tg.env.LIB)) + + # If 'export_headers' is present, add files to the Headers build phase in xcode. + # These are files that'll get packed into the Framework for instance. + exp_hdrs = getattr(tg, 'export_headers', []) + hdrs = self.as_nodes(Utils.to_list(exp_hdrs)) + files = [self.unique_filereference(PBXFileReference(n.name, n.abspath())) for n in hdrs] + target.add_build_phase(PBXHeadersBuildPhase([PBXBuildFile(f, {'ATTRIBUTES': ('Public',)}) for f in files])) + + # Install path + installpaths = Utils.to_list(getattr(tg, 'install', [])) + prodbuildfile = PBXBuildFile(target.productReference) + for instpath in installpaths: + target.add_build_phase(PBXCopyFilesBuildPhase([prodbuildfile], instpath)) + + # Merge frameworks and libs into one list, and prefix the frameworks + ld_flags = ['-framework %s' % lib.split('.framework')[0] for lib in Utils.to_list(tg.env.FRAMEWORK)] + ld_flags.extend(Utils.to_list(tg.env.STLIB) + Utils.to_list(tg.env.LIB)) + + # Override target specfic build settings + bldsettings = { + 'HEADER_SEARCH_PATHS': ['$(inherited)'] + tg.env['INCPATHS'], + 'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(tg.env.LIBPATH) + Utils.to_list(tg.env.STLIBPATH), + 'FRAMEWORK_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(tg.env.FRAMEWORKPATH), + 'OTHER_LDFLAGS': r'\n'.join(ld_flags) + } + + # The keys represents different build configuration, e.g. Debug, Release and so on.. + # Insert our generated build settings to all configuration names + keys = set(settings.keys() + self.env.PROJ_CONFIGURATION.keys()) + for k in keys: + if k in settings: + settings[k].update(bldsettings) + else: + settings[k] = bldsettings + + for k,v in settings.items(): + target.add_configuration(XCBuildConfiguration(k, v)) + + p.add_target(target) + + node = self.bldnode.make_node('%s.xcodeproj' % appname) + node.mkdir() + node = node.make_node('project.pbxproj') + p.write(open(node.abspath(), 'w')) + + def build_target(self, tgtype, *k, **kw): + """ + Provide user-friendly methods to build different target types + E.g. bld.framework(source='..', ...) to build a Framework target. + E.g. bld.dylib(source='..', ...) to build a Dynamic library target. etc... + """ + self.load('ccroot') + kw['features'] = 'cxx cxxprogram' + kw['target_type'] = tgtype + return self(*k, **kw) + + def app(self, *k, **kw): return self.build_target('app', *k, **kw) + def framework(self, *k, **kw): return self.build_target('framework', *k, **kw) + def dylib(self, *k, **kw): return self.build_target('dylib', *k, **kw) + def stlib(self, *k, **kw): return self.build_target('stlib', *k, **kw) + def exe(self, *k, **kw): return self.build_target('exe', *k, **kw) diff --git a/windows/JackNetWinSocket.cpp b/windows/JackNetWinSocket.cpp index de7580c2..6c1e6f5e 100644 --- a/windows/JackNetWinSocket.cpp +++ b/windows/JackNetWinSocket.cpp @@ -322,6 +322,7 @@ namespace Jack int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip) { fSendAddr.sin_addr.s_addr = inet_addr(ip); + fSendAddr.sin_port = htons(fPort); return SendTo(buffer, nbytes, flags); } @@ -387,6 +387,9 @@ def options(opt): opt.load('compiler_cxx') opt.load('compiler_c') + opt.load('xcode') + opt.load('xcode6') + # install directories opt.add_option('--htmldir', type='string', default=None, help="HTML documentation directory [Default: <prefix>/share/jack-audio-connection-kit/reference/html/") opt.add_option('--libdir', type='string', help="Library directory [Default: <prefix>/lib]") @@ -478,6 +481,9 @@ def configure(conf): conf.env.append_unique('CXXFLAGS', '-Wall') conf.env.append_unique('CFLAGS', '-Wall') + if conf.env['IS_MACOSX']: + conf.check(lib='aften', uselib='AFTEN', define_name='AFTEN') + # configure all auto options configure_auto_options(conf) @@ -488,6 +494,12 @@ def configure(conf): defines=['_GNU_SOURCE'], mandatory=False) + # Check for backtrace support + conf.check( + header_name='execinfo.h', + define_name='HAVE_EXECINFO_H', + mandatory=False) + conf.recurse('common') if Options.options.dbus: conf.recurse('dbus') @@ -496,6 +508,21 @@ def configure(conf): conf.recurse('example-clients') + # test for the availability of ucontext, and how it should be used + for t in ("gp_regs", "uc_regs", "mc_gregs", "gregs"): + fragment = "#include <ucontext.h>\n" + fragment += "int main() { ucontext_t *ucontext; return (int) ucontext->uc_mcontext.%s[0]; }" % t + confvar = "HAVE_UCONTEXT_%s" % t.upper() + conf.check_cc(fragment=fragment, define_name=confvar, mandatory=False, + msg="Checking for ucontext->uc_mcontext.%s" % t) + if conf.is_defined(confvar): + conf.define('HAVE_UCONTEXT', 1) + + fragment = "#include <ucontext.h>\n" + fragment += "int main() { return NGREG; }" + conf.check_cc(fragment=fragment, define_name="HAVE_NGREG", mandatory=False, + msg="Checking for NGREG") + conf.env['LIB_PTHREAD'] = ['pthread'] conf.env['LIB_DL'] = ['dl'] conf.env['LIB_RT'] = ['rt'] @@ -701,7 +728,8 @@ def build_jackd(bld): includes = ['.', 'common', 'common/jack'], target = 'jackd', source = ['common/Jackdmp.cpp'], - use = ['serverlib']) + use = ['serverlib'] + ) if bld.env['BUILD_JACKDBUS']: jackd.source += ['dbus/audio_reserve.c', 'dbus/reserve.c'] @@ -711,8 +739,8 @@ def build_jackd(bld): jackd.use += ['DL', 'M', 'PTHREAD', 'RT', 'STDC++'] if bld.env['IS_MACOSX']: - bld.framework = ['CoreFoundation'] jackd.use += ['DL', 'PTHREAD'] + jackd.framework = ['CoreFoundation'] if bld.env['IS_SUN']: jackd.use += ['DL', 'PTHREAD'] @@ -723,6 +751,15 @@ def build_jackd(bld): # FIXME: Is SERVER_SIDE needed? def create_driver_obj(bld, **kw): + if bld.env['IS_MACOSX'] or bld.env['IS_WINDOWS']: + # On MacOSX this is necessary. + # I do not know if this is necessary on Windows. + # Note added on 2015-12-13 by lilrc. + if 'use' in kw: + kw['use'] += ['serverlib'] + else: + kw['use'] = ['serverlib'] + driver = bld( features = ['c', 'cshlib', 'cxx', 'cxxshlib'], defines = ['HAVE_CONFIG_H', 'SERVER_SIDE'], @@ -793,19 +830,20 @@ def build_drivers(bld): ] coreaudio_src = [ - 'macosx/coreaudio/JackCoreAudioDriver.cpp' + 'macosx/coreaudio/JackCoreAudioDriver.mm', + 'common/JackAC3Encoder.cpp' ] coremidi_src = [ - 'macosx/coremidi/JackCoreMidiInputPort.cpp', - 'macosx/coremidi/JackCoreMidiOutputPort.cpp', - 'macosx/coremidi/JackCoreMidiPhysicalInputPort.cpp', - 'macosx/coremidi/JackCoreMidiPhysicalOutputPort.cpp', - 'macosx/coremidi/JackCoreMidiVirtualInputPort.cpp', - 'macosx/coremidi/JackCoreMidiVirtualOutputPort.cpp', - 'macosx/coremidi/JackCoreMidiPort.cpp', - 'macosx/coremidi/JackCoreMidiUtil.cpp', - 'macosx/coremidi/JackCoreMidiDriver.cpp' + 'macosx/coremidi/JackCoreMidiInputPort.mm', + 'macosx/coremidi/JackCoreMidiOutputPort.mm', + 'macosx/coremidi/JackCoreMidiPhysicalInputPort.mm', + 'macosx/coremidi/JackCoreMidiPhysicalOutputPort.mm', + 'macosx/coremidi/JackCoreMidiVirtualInputPort.mm', + 'macosx/coremidi/JackCoreMidiVirtualOutputPort.mm', + 'macosx/coremidi/JackCoreMidiPort.mm', + 'macosx/coremidi/JackCoreMidiUtil.mm', + 'macosx/coremidi/JackCoreMidiDriver.mm' ] ffado_src = [ @@ -908,21 +946,21 @@ def build_drivers(bld): bld, target = 'portaudio', source = portaudio_src, - use = ['serverlib', 'PORTAUDIO']) # FIXME: Is serverlib needed here? + use = ['PORTAUDIO']) if bld.env['BUILD_DRIVER_WINMME']: create_driver_obj( bld, target = 'winmme', source = winmme_src, - use = ['serverlib', 'WINMME']) # FIXME: Is serverlib needed here? + use = ['WINMME']) if bld.env['IS_MACOSX']: create_driver_obj( bld, target = 'coreaudio', source = coreaudio_src, - use = ['serverlib'], # FIXME: Is this needed? + use = ['AFTEN'], framework = ['AudioUnit', 'CoreAudio', 'CoreServices']) create_driver_obj( @@ -930,7 +968,7 @@ def build_drivers(bld): target = 'coremidi', source = coremidi_src, use = ['serverlib'], # FIXME: Is this needed? - framework = ['AudioUnit', 'CoreMIDI', 'CoreServices']) + framework = ['AudioUnit', 'CoreMIDI', 'CoreServices', 'Foundation']) if bld.env['IS_SUN']: create_driver_obj( @@ -1050,3 +1088,9 @@ def dist(ctx): # This code blindly assumes it is working in the toplevel source directory. if not os.path.exists('svnversion.h'): os.system('./svnversion_regenerate.sh svnversion.h') + +from waflib import TaskGen +@TaskGen.extension('.mm') +def mm_hook(self, node): + """Alias .mm files to be compiled the same as .cpp files, gcc will do the right thing.""" + return self.create_compiled_task('cxx', node) |