Skip to content

Initialize atomic_flag #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
cd531f7
Bump version number for future development
sgretscher Nov 7, 2022
01b9347
Merge IPCDemo into TestHost (initially limited to test cases that don…
sgretscher Nov 7, 2022
bf91af3
Minor cleanup for more consistency
sgretscher Nov 7, 2022
9a14408
Move common initialization of ARA_SUPPORT_VERSION_1 to DispatchBase
sgretscher Nov 7, 2022
d3c736b
Move draft of IPC proxies from ARA_Examples to ARA_Library, decouplin…
sgretscher Nov 7, 2022
5abdb1c
Make IPC proxies C compatible (for Audio Unit code in ObjC/Swift)
sgretscher Nov 7, 2022
a619cc1
Enable hosts to use of multiple different plug-ins through IPC proxie…
sgretscher Nov 7, 2022
e2bd483
Move CF-based IPC en/decoding from ARA_Examples to ARA_Library
sgretscher Nov 7, 2022
cf45460
Make locks in IPC context-dependent to allow for stacked messages (e.…
sgretscher Nov 7, 2022
5e5273b
IPC encoding fixes for optional name members such as the various name…
sgretscher Nov 7, 2022
64aa0bb
Hide IPC proxy internal mappings by generalzing the binding call in t…
sgretscher Nov 7, 2022
e5bf6a5
Add proper support of ARA (un)initialization to IPC proxy
sgretscher Nov 7, 2022
3feecf1
Add draft of channel arrangement to IPC
sgretscher Nov 7, 2022
c53aa69
Add draft of isAudioModificationPreservingAudioSourceSignal() to IPC
sgretscher Nov 7, 2022
419267b
Unify remoteCallWith/WithoutReply() by adding an intermediate wrapper…
sgretscher Nov 7, 2022
5cf7a14
Initial draft of channeling ARA IPC through upcoming macOS 13 AudioUn…
sgretscher Nov 7, 2022
d98dd12
Add workaround for macOS 13 destroying remote Audio Units asynchronously
sgretscher Nov 7, 2022
8bc292f
Initialize atomic_flag
danra Nov 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -86,6 +86,19 @@ function(configure_ARA_Library_target target)
PRIVATE
-DNOMINMAX=1
)
elseif(APPLE)
if(XCODE)
set_target_properties(${target} PROPERTIES
XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN YES
XCODE_ATTRIBUTE_GCC_INLINES_ARE_PRIVATE_EXTERN YES
)
else()
set_target_properties(${target} PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)
endif()
elseif(UNIX AND NOT APPLE)
set_target_properties(${target} PROPERTIES
POSITION_INDEPENDENT_CODE ON
@@ -99,7 +112,7 @@ endfunction()

# ======================

# files used in both targets
# files used in both host and plug-in target
set(ARA_Library_Common_Files
"${CMAKE_CURRENT_SOURCE_DIR}/Debug/ARADebug.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Debug/ARADebug.c"
@@ -150,4 +163,36 @@ add_library(ARA_PlugIn_Library ${ARA_LIBRARY_TARGET_TYPE}
"${CMAKE_CURRENT_SOURCE_DIR}/PlugIn/ARAPlug.h"
"${CMAKE_CURRENT_SOURCE_DIR}/PlugIn/ARAPlug.cpp"
)

configure_ARA_Library_target(ARA_PlugIn_Library)

# ======================

add_library(ARA_IPC_Library ${ARA_LIBRARY_TARGET_TYPE}
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPC.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCEncoding.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCLockingContext.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCLockingContext.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCProxyHost.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCProxyHost.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCProxyPlugIn.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCProxyPlugIn.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCProxyHost.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCProxyHost.cpp"
)

if(APPLE)
target_sources(ARA_IPC_Library PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCAudioUnit_v3.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCAudioUnit_v3.m"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCCFEncoding.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IPC/ARAIPCCFEncoding.cpp"
)
endif()

target_link_libraries(ARA_IPC_Library PRIVATE
ARA_Host_Library
ARA_PlugIn_Library
)

configure_ARA_Library_target(ARA_IPC_Library)
9 changes: 9 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
This is a development build of the ARA Library 2.3.
=== PRELIMINARY - DO NOT USE FOR SHIPPING PRODUCTS! ===


Changes since previous releases:
- initial draft of generic ARA IPC library providing a proxy host and a proxy plug-in,
based on heavily refactored IPC Example from earlier SDK releases


=== ARA SDK 2.2 release (aka 2.2.001) (2022/11/07) ===
- added surround support for audio sources
- added API to determine whether an audio modification actually modifies the underlying audio source
3 changes: 2 additions & 1 deletion Debug/ARADebug.h
Original file line number Diff line number Diff line change
@@ -69,7 +69,8 @@ extern "C"
// logs to the debugger console and/or to the error output (e.g. stderr)
void ARADebugMessage(ARADebugLevel level, const char * file, int line, const char * text, ...);
// this logging can be prefixed by a custom static string if desired, which is useful e.g.
// if multiple plug-ins are build using the same compiled library, or in the IPC Demo example
// if multiple plug-ins are build using the same compiled library, or if using the IPC
// capabilities of the ARATestHost example
// typically, this setup call is made once when loading the final binary and passes its name
void ARASetupDebugMessagePrefix(const char * prefix);
#if defined(__cplusplus)
30 changes: 30 additions & 0 deletions Dispatch/ARADispatchBase.h
Original file line number Diff line number Diff line change
@@ -31,6 +31,36 @@
#include "ARA_API/ARAInterface.h"


/*******************************************************************************/
/** Optional ARA 1 backwards compatibility.
Hosts and plug-ins can choose support ARA 1 hosts in addition to ARA 2 hosts.
This feature is being phased out as all vendors move to ARA 2, and is not
available on architectures where ARA 1 was not available, such as ARM.

For hosts, using ARA 1 plug-ins through the implementation provided here
imposes several implicit restrictions:
- each plug-in instance assumes all possible roles (see ARAPlugInInstanceRoleFlags)
- each plug-in instance only is associated with at most one playback region at any time
- the ARA 1 API is mapped to PlaybackRenderer*, the other interfaces will not be provided
- archiving must use ARA 1 style monolithic persistency calls

Plug-ins will have to implement a several fallbacks in order to work in ARA 1 hosts,
in addition to the support provided by this implementation they need to:
- create dummy region sequences for the playback regions, utilizing the
context information provided via the companion APIs
- implicitly derive ARA selection state from companion API actions
*/
/*******************************************************************************/

#if !defined (ARA_SUPPORT_VERSION_1)
#define ARA_SUPPORT_VERSION_1 0
#endif

#if ARA_SUPPORT_VERSION_1 && ARA_CPU_ARM
#error "ARA v1 is not supported on ARM architecture"
#endif


namespace ARA {

/*******************************************************************************/
19 changes: 0 additions & 19 deletions Dispatch/ARAHostDispatch.h
Original file line number Diff line number Diff line change
@@ -30,25 +30,6 @@ namespace Host {
//! @addtogroup ARA_Library_Host_Dispatch
//! @{

/*******************************************************************************/
/** Optional ARA 1 backwards compatibility.
Host can choose support ARA 1 plug-ins in addition to ARA 2 plug-ins.
This results in several restrictions being implicitly imposed when using such plug-ins
through the implementation provided here:
- each plug-in instance assumes all possible roles (see ARAPlugInInstanceRoleFlags)
- each plug-in instance only is associated with at most one playback region at any time
- the ARA 1 API is mapped to PlaybackRenderer*, the other interfaces will not be provided
- archiving must use ARA 1 style monolithic persistency calls
*/
/*******************************************************************************/

#if !defined (ARA_SUPPORT_VERSION_1)
#define ARA_SUPPORT_VERSION_1 0
#endif

#if ARA_SUPPORT_VERSION_1 && ARA_CPU_ARM
#error "ARA v1 is not supported on ARM architecture"
#endif

/*******************************************************************************/
/** Type safe conversions to/from host ref: toHostRef () and fromHostRef<> ().
18 changes: 0 additions & 18 deletions Dispatch/ARAPlugInDispatch.h
Original file line number Diff line number Diff line change
@@ -27,24 +27,6 @@ namespace PlugIn {
//! @addtogroup ARA_Library_PlugIn_Dispatch
//! @{

/*******************************************************************************/
/** Optional ARA 1 backwards compatibility.
Plug-ins can choose support ARA 1 hosts in addition to ARA 2 hosts.
Plug-ins will have to implement a lot of fallbacks in addition to the support
provided by this implementation:
- create dummy region sequences for the playback regions, utilizing the
context information provided via the companion APIs
- implicitly derive ARA selection state from companion API actions
*/
/*******************************************************************************/
#if !defined (ARA_SUPPORT_VERSION_1)
#define ARA_SUPPORT_VERSION_1 0
#endif

#if ARA_SUPPORT_VERSION_1 && ARA_CPU_ARM
#error "ARA v1 is not supported on ARM architecture"
#endif

/*******************************************************************************/
/** Type safe conversions to/from ref: toRef () and fromRef<> ().
This macro defines custom overloads of the toRef () and fromRef<> () conversion functions
218 changes: 218 additions & 0 deletions IPC/ARAIPC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
//------------------------------------------------------------------------------
//! \file ARAIPC.h
//! Abstractions shared by both the ARA IPC proxy host and plug-in
//! Typically, this file is not included directly - either ARAIPCProxyHost.h
//! ARAIPCProxyPlugIn.h will be used instead.
//! \project ARA SDK Library
//! \copyright Copyright (c) 2021-2022, Celemony Software GmbH, All Rights Reserved.
//! \license Licensed under the Apache License, Version 2.0 (the "License");
//! you may not use this file except in compliance with the License.
//! You may obtain a copy of the License at
//!
//! http://www.apache.org/licenses/LICENSE-2.0
//!
//! Unless required by applicable law or agreed to in writing, software
//! distributed under the License is distributed on an "AS IS" BASIS,
//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//! See the License for the specific language governing permissions and
//! limitations under the License.
//------------------------------------------------------------------------------

#ifndef ARAIPC_h
#define ARAIPC_h


#include "ARA_API/ARAInterface.h"


//! @addtogroup ARA_Library_IPC
//! @{

//! switch to bypass all IPC code
#if !defined (ARA_ENABLE_IPC)
#if defined (__APPLE__) || defined (_WIN32)
#define ARA_ENABLE_IPC 1
#else
#define ARA_ENABLE_IPC 0
#endif
#endif


#if ARA_ENABLE_IPC


#if defined(__cplusplus)
namespace ARA {
namespace IPC {
extern "C" {
#endif


//! ID type for messages, IDs must be >= kARAIPCMessageIDRangeStart and < kARAIPCMessageIDRangeEnd
typedef ARAInt32 ARAIPCMessageID;
#if defined(__cplusplus)
constexpr ARAIPCMessageID kARAIPCMessageIDRangeStart { 1 };
constexpr ARAIPCMessageID kARAIPCMessageIDRangeEnd { 8*16*16 - 1 };
#else
#define kARAIPCMessageIDRangeStart ((ARAIPCMessageID) 1)
#define kARAIPCMessageIDRangeEnd ((ARAIPCMessageID) 8*16*16 - 1)
#endif


//! key type for message dictionaries - negative keys are reserved for the implementation
typedef ARAInt32 ARAIPCMessageKey;


//! Message Encoder
//! @{
typedef struct ARAIPCMessageEncoderImplementation * ARAIPCMessageEncoderRef;

typedef struct ARAIPCMessageEncoderInterface
{
//! destructor
void (ARA_CALL *destroyEncoder) (ARAIPCMessageEncoderRef encoderRef);

//! number types
//! The size variant will also be used for the pointer-sized ARA (host) refs.
//@{
void (ARA_CALL *appendInt32) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey, int32_t argValue);
void (ARA_CALL *appendInt64) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey, int64_t argValue);
void (ARA_CALL *appendSize) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey, size_t argValue);
void (ARA_CALL *appendFloat) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey, float argValue);
void (ARA_CALL *appendDouble) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey, double argValue);
//@}

//! UTF8-encoded C strings
void (ARA_CALL *appendString) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey, const char * argValue);

//! raw bytes
//! As optimization, disable copying if the memory containing the bytes stays
//! alive&unchanged until the message has been sent.
void (ARA_CALL *appendBytes) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey, const uint8_t * argValue, size_t argSize, bool copy);

//! sub-messages to encode compound types
//! The caller is responsible for deleting the encoder after use.
ARAIPCMessageEncoderRef (ARA_CALL *appendSubMessage) (ARAIPCMessageEncoderRef messageEncoderRef, ARAIPCMessageKey argKey);
} ARAIPCMessageEncoderInterface;

typedef struct ARAIPCMessageEncoder
{
ARAIPCMessageEncoderRef ref;
const ARAIPCMessageEncoderInterface * methods; // this preferably would be called "interface", but there's a system-defined macro in Windows with that name...
} ARAIPCMessageEncoder;
//! @}


//! Message Decoder
//! @{
typedef struct ARAIPCMessageDecoderImplementation * ARAIPCMessageDecoderRef;

typedef struct ARAIPCMessageDecoderInterface
{
//! destructor
void (ARA_CALL *destroyDecoder) (ARAIPCMessageDecoderRef messageDecoderRef);

//! only for debugging/validation: test if the message contains any key/value pairs
bool (ARA_CALL *isEmpty) (ARAIPCMessageDecoderRef messageDecoderRef);

//! number types
//! The size variant will also be used for the pointer-sized ARA (host) refs.
//! Will return false and set argValue to 0 if key not found.
//@{
bool (ARA_CALL *readInt32) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, int32_t * argValue);
bool (ARA_CALL *readInt64) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, int64_t * argValue);
bool (ARA_CALL *readSize) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, size_t * argValue);
bool (ARA_CALL *readFloat) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, float * argValue);
bool (ARA_CALL *readDouble) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, double * argValue);
//@}

//! UTF8-encoded C strings
//! Will return false and set argValue to NULL if key not found.
bool (ARA_CALL *readString) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, const char ** argValue);

//! raw bytes
//! first query size, then provide a buffer large enough to copy the bytes to.
//! readBytesSize () will return false and set argSize to 0 if key not found.
//@{
bool (ARA_CALL *readBytesSize) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, size_t * argSize);
void (ARA_CALL *readBytes) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey, uint8_t * argValue);
//@}

//! sub-messages to decode compound types
//! returns nullptr if key not found or if the value for the key is not representing a sub-message
//! The caller is responsible for deleting the encoder after use.
ARAIPCMessageDecoderRef (ARA_CALL *readSubMessage) (ARAIPCMessageDecoderRef messageDecoderRef, ARAIPCMessageKey argKey);
} ARAIPCMessageDecoderInterface;

typedef struct ARAIPCMessageDecoder
{
ARAIPCMessageDecoderRef ref;
const ARAIPCMessageDecoderInterface * methods; // this preferably would be called "interface", but there's a system-defined macro in Windows with that name...
} ARAIPCMessageDecoder;
//! @}


//! Message Receiver: a function that receives a message readable through the decoder, optionally creating a reply
//! Not using the replyEncoder will return a valid empty message to the sender (useful for void calls).
//! Depending on the underlying implementation, replyEncoder may be nullptr if no reply has been
//! requested by the sender, but providing a dummy encoder in this case is valid too.
//! The sender thread will be blocked until the (possibly empty) reply has been received.
//! A receive function can be called from any thread, but not concurrently.
typedef void (ARA_CALL *ARAIPCMessageReceiver) (const ARAIPCMessageID messageID, const ARAIPCMessageDecoder decoder, ARAIPCMessageEncoder * replyEncoder);

//! Reply Handler: a function that is called to process the reply to a message
typedef void (ARA_CALL *ARAIPCReplyHandler) (const ARAIPCMessageDecoder decoder, void * userData);

//! Message Sender: gateway for sending messages
//! @{
typedef struct ARAIPCMessageSenderImplementation * ARAIPCMessageSenderRef;

typedef struct ARAIPCMessageSenderInterface
{
//! generate an encoder to encode a new message
//! An encoder can be reused if the same message is sent several times,
//! but it must not be modified after sending.
//! The caller is responsible for deleting the encoder after use.
ARAIPCMessageEncoder (ARA_CALL *createEncoder) (ARAIPCMessageSenderRef messageSenderRef);

//! send function: send message create using the encoder, blocking until a reply has been received.
//! If an empty reply ("void") is expected, the replyHandler should be nullptr.
//! A send function can be called from any thread, but not concurrently.
void (ARA_CALL *sendMessage) (const bool stackable, ARAIPCMessageSenderRef messageSenderRef, ARAIPCMessageID messageID,
const ARAIPCMessageEncoder * encoder, ARAIPCReplyHandler * const replyHandler, void * replyHandlerUserData);

//! Test if the receiver runs on a different architecture with different endianess.
bool (ARA_CALL *receiverEndianessMatches) (ARAIPCMessageSenderRef messageSenderRef);
} ARAIPCMessageSenderInterface;

typedef struct ARAIPCMessageSender
{
ARAIPCMessageSenderRef ref;
const ARAIPCMessageSenderInterface * methods; // this preferably would be called "interface", but there's a system-defined macro in Windows with that name...
} ARAIPCMessageSender;
//! @}


//! Companion API: opaque encapsulation
//! @{
//! to keep the IPC decoupled from the Companion API in use, the IPC code uses an opaque token to represent a plug-in instance
typedef size_t ARAIPCPlugInInstanceRef;

//! callback that the proxy uses to execute the binding of an opaque Companion API plug-in instance to the given document controller
typedef const ARAPlugInExtensionInstance* (*ARAIPCBindingHandler) (ARAIPCPlugInInstanceRef plugInInstanceRef,
ARADocumentControllerRef controllerRef, ARAPlugInInstanceRoleFlags knownRoles, ARAPlugInInstanceRoleFlags assignedRoles);
//! @}


#if defined(__cplusplus)
} // extern "C"
} // namespace IPC
} // namespace ARA
#endif


#endif // ARA_ENABLE_IPC

//! @} ARA_Library_IPC

#endif // ARAIPC_h
Loading