diff --git a/README.md b/README.md index cb84f995..ee3b2182 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ What AAP aims is to become like an inclusive standard for audio plugin, adoped t On the other hand it is designed so that cross-audio-plugin frameworks can support it. We have [JUCE](http://juce.com/) integration support, and once [iPlug2](https://iplug2.github.io/) supports Linux and Android it would become similarly possible. Namely, AAP is first designed so that JUCE audio processor can be implemented and JUCE-based audio plugins can be easily imported to AAP world. -Extensibility is provided like what LV2 does (but without RDF and Turtle complication). VST3-specifics, or AAX-specifics, can be represented as long as it can be represented through raw pointer of any type (`void*`) i.e. cast to any context you'd like to have, associalted with a URI. Those extensions can be used only with supported hosts. A host can query each plugin whether it supports certain feature or not and disable those not-supported plugins, and a plugin can query the host which features it provides. +AAP is extensible to some extent; plugins can query host for extension data which is represented as a pointer on shared memory (explained later), associated with certain extension URI. It is similar to how LV2 extensions works, but in AAP it is limited to **data** pointers (also without RDF and Turtle complication). Those extensions can be used only with supported hosts. A host can query each plugin whether it supports certain feature or not and disable those not-supported plugins, and a plugin can query the host which features it provides. It is limited to data i.e. no runnable code, because code in host application is simply not runnable on the plugin application. + +VST3 specifics, LV2 specifics, etc. should be processed by (so-called) plugin wrappers, with some help with extensions, if provided by anyone. Android is the first citizen in AAP, but we also support Linux desktop so that actual plugin development can be achieved on the desktop. diff --git a/aidl/org/androidaudioplugin/AudioPluginInterface.aidl b/aidl/org/androidaudioplugin/AudioPluginInterface.aidl index 752d04c3..0997f5f9 100644 --- a/aidl/org/androidaudioplugin/AudioPluginInterface.aidl +++ b/aidl/org/androidaudioplugin/AudioPluginInterface.aidl @@ -3,6 +3,7 @@ package org.androidaudioplugin; interface AudioPluginInterface { int create(String pluginId, int sampleRate); + void addExtension(int instanceID, String uri, in ParcelFileDescriptor sharedMemoryFD, int size); boolean isPluginAlive(int instanceID); diff --git a/java/.idea/.name b/java/.idea/.name new file mode 100644 index 00000000..b6e7ee87 --- /dev/null +++ b/java/.idea/.name @@ -0,0 +1 @@ +AndroidAudioPlugin \ No newline at end of file diff --git a/java/.idea/compiler.xml b/java/.idea/compiler.xml index 539cfcbc..3ce30546 100644 --- a/java/.idea/compiler.xml +++ b/java/.idea/compiler.xml @@ -8,6 +8,13 @@ + + + + + + + diff --git a/java/.idea/gradle.xml b/java/.idea/gradle.xml index f59c78a0..dd2dfbd1 100644 --- a/java/.idea/gradle.xml +++ b/java/.idea/gradle.xml @@ -21,6 +21,7 @@ diff --git a/java/.idea/misc.xml b/java/.idea/misc.xml index 37a75096..7bfef59d 100644 --- a/java/.idea/misc.xml +++ b/java/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginExtensionData.kt b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginExtensionData.kt new file mode 100644 index 00000000..552f7547 --- /dev/null +++ b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginExtensionData.kt @@ -0,0 +1,3 @@ +package org.androidaudioplugin + +public class AudioPluginExtensionData(val uri: String, val data: ByteArray) diff --git a/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginHost.kt b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginHost.kt index 2995431c..04541a88 100644 --- a/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginHost.kt +++ b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginHost.kt @@ -19,6 +19,8 @@ class AudioPluginHost(private var applicationContext: Context) { internal var connectedServices = mutableListOf() var instantiatedPlugins = mutableListOf() + val extensions = mutableListOf() + fun bindAudioPluginService(service: AudioPluginServiceInformation) { var intent = Intent(AudioPluginHostHelper.AAP_ACTION_NAME) intent.component = ComponentName( @@ -79,7 +81,7 @@ class AudioPluginHost(private var applicationContext: Context) { private fun instantiatePlugin(pluginInfo: PluginInformation, conn: PluginServiceConnection) { - var instance = conn.instantiatePlugin(pluginInfo, sampleRate) + var instance = conn.instantiatePlugin(pluginInfo, sampleRate, extensions) instantiatedPlugins.add(instance) pluginInstantiatedListeners.forEach { l -> l (instance) } } diff --git a/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginInterface.java b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginInterface.java index 531e02f8..eacef936 100644 --- a/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginInterface.java +++ b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/AudioPluginInterface.java @@ -11,6 +11,9 @@ public static class Default implements org.androidaudioplugin.AudioPluginInterfa { return 0; } + @Override public void addExtension(int instanceID, java.lang.String uri, android.os.ParcelFileDescriptor sharedMemoryFD, int size) throws android.os.RemoteException + { + } @Override public boolean isPluginAlive(int instanceID) throws android.os.RemoteException { return false; @@ -98,6 +101,26 @@ public static org.androidaudioplugin.AudioPluginInterface asInterface(android.os reply.writeInt(_result); return true; } + case TRANSACTION_addExtension: + { + data.enforceInterface(descriptor); + int _arg0; + _arg0 = data.readInt(); + java.lang.String _arg1; + _arg1 = data.readString(); + android.os.ParcelFileDescriptor _arg2; + if ((0!=data.readInt())) { + _arg2 = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(data); + } + else { + _arg2 = null; + } + int _arg3; + _arg3 = data.readInt(); + this.addExtension(_arg0, _arg1, _arg2, _arg3); + reply.writeNoException(); + return true; + } case TRANSACTION_isPluginAlive: { data.enforceInterface(descriptor); @@ -264,6 +287,34 @@ public java.lang.String getInterfaceDescriptor() } return _result; } + @Override public void addExtension(int instanceID, java.lang.String uri, android.os.ParcelFileDescriptor sharedMemoryFD, int size) throws android.os.RemoteException + { + android.os.Parcel _data = android.os.Parcel.obtain(); + android.os.Parcel _reply = android.os.Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(instanceID); + _data.writeString(uri); + if ((sharedMemoryFD!=null)) { + _data.writeInt(1); + sharedMemoryFD.writeToParcel(_data, 0); + } + else { + _data.writeInt(0); + } + _data.writeInt(size); + boolean _status = mRemote.transact(Stub.TRANSACTION_addExtension, _data, _reply, 0); + if (!_status && getDefaultImpl() != null) { + getDefaultImpl().addExtension(instanceID, uri, sharedMemoryFD, size); + return; + } + _reply.readException(); + } + finally { + _reply.recycle(); + _data.recycle(); + } + } @Override public boolean isPluginAlive(int instanceID) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); @@ -487,16 +538,17 @@ public java.lang.String getInterfaceDescriptor() public static org.androidaudioplugin.AudioPluginInterface sDefaultImpl; } static final int TRANSACTION_create = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); - static final int TRANSACTION_isPluginAlive = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); - static final int TRANSACTION_prepare = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); - static final int TRANSACTION_prepareMemory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3); - static final int TRANSACTION_activate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4); - static final int TRANSACTION_process = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5); - static final int TRANSACTION_deactivate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6); - static final int TRANSACTION_getStateSize = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7); - static final int TRANSACTION_getState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8); - static final int TRANSACTION_setState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9); - static final int TRANSACTION_destroy = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10); + static final int TRANSACTION_addExtension = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); + static final int TRANSACTION_isPluginAlive = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); + static final int TRANSACTION_prepare = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3); + static final int TRANSACTION_prepareMemory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4); + static final int TRANSACTION_activate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5); + static final int TRANSACTION_process = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6); + static final int TRANSACTION_deactivate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7); + static final int TRANSACTION_getStateSize = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8); + static final int TRANSACTION_getState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9); + static final int TRANSACTION_setState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10); + static final int TRANSACTION_destroy = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11); public static boolean setDefaultImpl(org.androidaudioplugin.AudioPluginInterface impl) { if (Stub.Proxy.sDefaultImpl == null && impl != null) { Stub.Proxy.sDefaultImpl = impl; @@ -509,6 +561,7 @@ public static org.androidaudioplugin.AudioPluginInterface getDefaultImpl() { } } public int create(java.lang.String pluginId, int sampleRate) throws android.os.RemoteException; + public void addExtension(int instanceID, java.lang.String uri, android.os.ParcelFileDescriptor sharedMemoryFD, int size) throws android.os.RemoteException; public boolean isPluginAlive(int instanceID) throws android.os.RemoteException; public void prepare(int instanceID, int frameCount, int portCount) throws android.os.RemoteException; public void prepareMemory(int instanceID, int shmFDIndex, android.os.ParcelFileDescriptor sharedMemoryFD) throws android.os.RemoteException; diff --git a/java/androidaudioplugin/src/main/java/org/androidaudioplugin/PluginServiceConnection.kt b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/PluginServiceConnection.kt index acdff3af..22170ce2 100644 --- a/java/androidaudioplugin/src/main/java/org/androidaudioplugin/PluginServiceConnection.kt +++ b/java/androidaudioplugin/src/main/java/org/androidaudioplugin/PluginServiceConnection.kt @@ -3,6 +3,8 @@ package org.androidaudioplugin import android.content.ComponentName import android.content.ServiceConnection import android.os.IBinder +import android.os.ParcelFileDescriptor +import android.os.SharedMemory import android.util.Log // FIXME: make it internal @@ -22,9 +24,14 @@ class PluginServiceConnection(var serviceInfo: AudioPluginServiceInformation, va override fun onServiceDisconnected(name: ComponentName?) { } - fun instantiatePlugin(pluginInfo : PluginInformation, sampleRate: Int) : AudioPluginInstance { - - var instanceId = AudioPluginInterface.Stub.asInterface(binder!!).create(pluginInfo.pluginId, sampleRate) + fun instantiatePlugin(pluginInfo : PluginInformation, sampleRate: Int, extensions: List) : AudioPluginInstance { + val aapSvc = AudioPluginInterface.Stub.asInterface(binder!!) + var instanceId = aapSvc.create(pluginInfo.pluginId, sampleRate) + var extensionSharedMemoryList = extensions.associateBy({ ext -> ext.uri}, { ext -> + val shm = SharedMemory.create(null, ext.data.size) + shm.mapReadWrite().put(ext.data) + shm }) + extensionSharedMemoryList.forEach { ext -> aapSvc.addExtension(instanceId, ext.key, ParcelFileDescriptor.fromFd(ext.value.describeContents()), ext.value.size) } var instance = AudioPluginInstance(instanceId, serviceInfo.plugins.first { p -> p.pluginId == pluginInfo.pluginId}, this) instances.add(instance) return instance diff --git a/java/build.gradle b/java/build.gradle index 1ae932b9..b4002021 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.61' + ext.kotlin_version = '1.3.72' ext.dokkaVersion = '0.9.17' repositories { google() @@ -9,7 +9,7 @@ buildscript { maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0-alpha01' + classpath 'com.android.tools.build:gradle:4.1.0-alpha07' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokkaVersion" // NOTE: Do not place your application dependencies here; they belong diff --git a/java/gradle/wrapper/gradle-wrapper.properties b/java/gradle/wrapper/gradle-wrapper.properties index 0c6611e9..cc60fe73 100644 --- a/java/gradle/wrapper/gradle-wrapper.properties +++ b/java/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Mar 09 01:52:42 JST 2020 +#Sun Apr 26 00:33:37 JST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip diff --git a/java/settings.gradle b/java/settings.gradle index 6585410d..3e22bd43 100644 --- a/java/settings.gradle +++ b/java/settings.gradle @@ -1,3 +1,4 @@ +rootProject.name = 'AndroidAudioPlugin' include ':androidaudioplugin', ':androidaudioplugin-lv2', ':aapbarebonepluginsample', ':aaphostsample', ':localpluginsample', ':aaplv2plugins', ':aappluginsample' project(':aaplv2plugins').projectDir = new File('samples/aaplv2plugins') project(':aapbarebonepluginsample').projectDir = new File('samples/aapbarebonepluginsample') diff --git a/native/androidaudioplugin/android/src/AudioPluginInterfaceImpl.h b/native/androidaudioplugin/android/src/AudioPluginInterfaceImpl.h index 0522ec04..ea5b0d87 100644 --- a/native/androidaudioplugin/android/src/AudioPluginInterfaceImpl.h +++ b/native/androidaudioplugin/android/src/AudioPluginInterfaceImpl.h @@ -40,8 +40,8 @@ class AudioPluginInterfaceImpl : public aidl::org::androidaudioplugin::BnAudioPl *_aidl_return = host->createInstance(in_pluginId.c_str(), in_sampleRate); auto instance = host->getInstance(*_aidl_return); auto shm = new SharedMemoryExtension(); - shm->getSharedMemoryFDs().resize(instance->getPluginInformation()->getNumPorts()); - AndroidAudioPluginExtension ext{SharedMemoryExtension::URI, shm}; + shm->getPortBufferFDs().resize(instance->getPluginInformation()->getNumPorts()); + AndroidAudioPluginExtension ext{SharedMemoryExtension::URI, 0, shm}; instance->addExtension(ext); buffers.resize(*_aidl_return + 1); auto & buffer = buffers[*_aidl_return]; @@ -51,6 +51,21 @@ class AudioPluginInterfaceImpl : public aidl::org::androidaudioplugin::BnAudioPl return ndk::ScopedAStatus::ok(); } + ::ndk::ScopedAStatus addExtension(int32_t in_instanceID, const std::string& in_uri, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD, int32_t in_size) override + { + assert(in_instanceID < host->getInstanceCount()); + AndroidAudioPluginExtension extension; + extension.uri = in_uri.c_str(); + auto shmExt = host->getInstance(in_instanceID)->getSharedMemoryExtension(); + assert(shmExt != nullptr); + auto dfd = dup(in_sharedMemoryFD.get()); + shmExt->getExtensionFDs().emplace_back(dfd); + extension.transmit_size = in_size; + extension.data = mmap(nullptr, in_size, PROT_READ | PROT_WRITE, MAP_SHARED, dfd, 0); + host->getInstance(in_instanceID)->addExtension(extension); + return ndk::ScopedAStatus::ok(); + } + ::ndk::ScopedAStatus isPluginAlive(int32_t in_instanceID, bool* _aidl_return) override { assert(in_instanceID < host->getInstanceCount()); @@ -63,9 +78,9 @@ class AudioPluginInterfaceImpl : public aidl::org::androidaudioplugin::BnAudioPl ::ndk::ScopedAStatus prepareMemory(int32_t in_instanceID, int32_t in_shmFDIndex, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD) override { assert(in_instanceID < host->getInstanceCount()); - auto shmExt = host->getInstance(in_instanceID)->getSharedMemory(); - if (shmExt != nullptr) - shmExt->getSharedMemoryFDs()[in_shmFDIndex] = dup(in_sharedMemoryFD.get()); + auto shmExt = host->getInstance(in_instanceID)->getSharedMemoryExtension(); + assert(shmExt != nullptr); + shmExt->getPortBufferFDs()[in_shmFDIndex] = dup(in_sharedMemoryFD.get()); return ndk::ScopedAStatus::ok(); } @@ -81,7 +96,7 @@ class AudioPluginInterfaceImpl : public aidl::org::androidaudioplugin::BnAudioPl void freeBuffers(PluginInstance* instance, AndroidAudioPluginBuffer& buffer) { if (buffer.buffers) - for (int i = 0; i < instance->getSharedMemory()->getSharedMemoryFDs().size(); i++) + for (int i = 0; i < instance->getSharedMemoryExtension()->getPortBufferFDs().size(); i++) if (buffer.buffers[i]) munmap(buffer.buffers[i], buffer.num_buffers * sizeof(float)); } @@ -100,7 +115,7 @@ class AudioPluginInterfaceImpl : public aidl::org::androidaudioplugin::BnAudioPl int resetBuffers(PluginInstance* instance, AndroidAudioPluginBuffer& buffer, int frameCount) { int nPorts = instance->getPluginInformation()->getNumPorts(); - auto& FDs = instance->getSharedMemory()->getSharedMemoryFDs(); + auto& FDs = instance->getSharedMemoryExtension()->getPortBufferFDs(); if (FDs.size() != nPorts) { freeBuffers(instance, buffer); FDs.resize(nPorts, 0); diff --git a/native/androidaudioplugin/android/src/android-audio-plugin-client-bridge.cpp b/native/androidaudioplugin/android/src/android-audio-plugin-client-bridge.cpp index 598cf397..45de63c4 100644 --- a/native/androidaudioplugin/android/src/android-audio-plugin-client-bridge.cpp +++ b/native/androidaudioplugin/android/src/android-audio-plugin-client-bridge.cpp @@ -65,7 +65,7 @@ void resetBuffers(AAPClientContext *ctx, AndroidAudioPluginBuffer* buffer) int n = buffer->num_buffers; auto prevBuf = ctx->previous_buffer; - auto &fds = ctx->shared_memory_extension->getSharedMemoryFDs(); + auto &fds = ctx->shared_memory_extension->getPortBufferFDs(); // close extra shm FDs that are (1)insufficient in size, or (2)not needed anymore. if (prevBuf != nullptr) { diff --git a/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/AudioPluginInterface.h b/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/AudioPluginInterface.h index f89499e9..94abb5ed 100644 --- a/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/AudioPluginInterface.h +++ b/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/AudioPluginInterface.h @@ -21,6 +21,7 @@ class IAudioPluginInterface : public ::ndk::ICInterface { static bool setDefaultImpl(std::shared_ptr impl); static const std::shared_ptr& getDefaultImpl(); virtual ::ndk::ScopedAStatus create(const std::string& in_pluginId, int32_t in_sampleRate, int32_t* _aidl_return) = 0; + virtual ::ndk::ScopedAStatus addExtension(int32_t in_instanceID, const std::string& in_uri, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD, int32_t in_size) = 0; virtual ::ndk::ScopedAStatus isPluginAlive(int32_t in_instanceID, bool* _aidl_return) = 0; virtual ::ndk::ScopedAStatus prepare(int32_t in_instanceID, int32_t in_frameCount, int32_t in_portCount) = 0; virtual ::ndk::ScopedAStatus prepareMemory(int32_t in_instanceID, int32_t in_shmFDIndex, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD) = 0; @@ -37,6 +38,7 @@ class IAudioPluginInterface : public ::ndk::ICInterface { class IAudioPluginInterfaceDefault : public IAudioPluginInterface { public: ::ndk::ScopedAStatus create(const std::string& in_pluginId, int32_t in_sampleRate, int32_t* _aidl_return) override; + ::ndk::ScopedAStatus addExtension(int32_t in_instanceID, const std::string& in_uri, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD, int32_t in_size) override; ::ndk::ScopedAStatus isPluginAlive(int32_t in_instanceID, bool* _aidl_return) override; ::ndk::ScopedAStatus prepare(int32_t in_instanceID, int32_t in_frameCount, int32_t in_portCount) override; ::ndk::ScopedAStatus prepareMemory(int32_t in_instanceID, int32_t in_shmFDIndex, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD) override; diff --git a/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/BpAudioPluginInterface.h b/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/BpAudioPluginInterface.h index c0d35232..4711a80d 100644 --- a/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/BpAudioPluginInterface.h +++ b/native/androidaudioplugin/android/src/gen/include/aidl/org/androidaudioplugin/BpAudioPluginInterface.h @@ -13,6 +13,7 @@ class BpAudioPluginInterface : public ::ndk::BpCInterface virtual ~BpAudioPluginInterface(); ::ndk::ScopedAStatus create(const std::string& in_pluginId, int32_t in_sampleRate, int32_t* _aidl_return) override; + ::ndk::ScopedAStatus addExtension(int32_t in_instanceID, const std::string& in_uri, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD, int32_t in_size) override; ::ndk::ScopedAStatus isPluginAlive(int32_t in_instanceID, bool* _aidl_return) override; ::ndk::ScopedAStatus prepare(int32_t in_instanceID, int32_t in_frameCount, int32_t in_portCount) override; ::ndk::ScopedAStatus prepareMemory(int32_t in_instanceID, int32_t in_shmFDIndex, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD) override; diff --git a/native/androidaudioplugin/android/src/gen/org/androidaudioplugin/AudioPluginInterface.cpp b/native/androidaudioplugin/android/src/gen/org/androidaudioplugin/AudioPluginInterface.cpp index 0d31361a..e50be546 100644 --- a/native/androidaudioplugin/android/src/gen/org/androidaudioplugin/AudioPluginInterface.cpp +++ b/native/androidaudioplugin/android/src/gen/org/androidaudioplugin/AudioPluginInterface.cpp @@ -33,7 +33,33 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 1 /*isPluginAlive*/): { + case (FIRST_CALL_TRANSACTION + 1 /*addExtension*/): { + int32_t in_instanceID; + std::string in_uri; + ::ndk::ScopedFileDescriptor in_sharedMemoryFD; + int32_t in_size; + + _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_instanceID); + if (_aidl_ret_status != STATUS_OK) break; + + _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_uri); + if (_aidl_ret_status != STATUS_OK) break; + + _aidl_ret_status = ::ndk::AParcel_readRequiredParcelFileDescriptor(_aidl_in, &in_sharedMemoryFD); + if (_aidl_ret_status != STATUS_OK) break; + + _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_size); + if (_aidl_ret_status != STATUS_OK) break; + + ::ndk::ScopedAStatus _aidl_status = _aidl_impl->addExtension(in_instanceID, in_uri, in_sharedMemoryFD, in_size); + _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get()); + if (_aidl_ret_status != STATUS_OK) break; + + if (!AStatus_isOk(_aidl_status.get())) break; + + break; + } + case (FIRST_CALL_TRANSACTION + 2 /*isPluginAlive*/): { int32_t in_instanceID; bool _aidl_return; @@ -51,7 +77,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 2 /*prepare*/): { + case (FIRST_CALL_TRANSACTION + 3 /*prepare*/): { int32_t in_instanceID; int32_t in_frameCount; int32_t in_portCount; @@ -73,7 +99,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 3 /*prepareMemory*/): { + case (FIRST_CALL_TRANSACTION + 4 /*prepareMemory*/): { int32_t in_instanceID; int32_t in_shmFDIndex; ::ndk::ScopedFileDescriptor in_sharedMemoryFD; @@ -95,7 +121,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 4 /*activate*/): { + case (FIRST_CALL_TRANSACTION + 5 /*activate*/): { int32_t in_instanceID; _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_instanceID); @@ -109,7 +135,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 5 /*process*/): { + case (FIRST_CALL_TRANSACTION + 6 /*process*/): { int32_t in_instanceID; int32_t in_timeoutInNanoseconds; @@ -127,7 +153,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 6 /*deactivate*/): { + case (FIRST_CALL_TRANSACTION + 7 /*deactivate*/): { int32_t in_instanceID; _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_instanceID); @@ -141,7 +167,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 7 /*getStateSize*/): { + case (FIRST_CALL_TRANSACTION + 8 /*getStateSize*/): { int32_t in_instanceID; int32_t _aidl_return; @@ -159,7 +185,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 8 /*getState*/): { + case (FIRST_CALL_TRANSACTION + 9 /*getState*/): { int32_t in_instanceID; ::ndk::ScopedFileDescriptor in_sharedMemoryFD; @@ -177,7 +203,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 9 /*setState*/): { + case (FIRST_CALL_TRANSACTION + 10 /*setState*/): { int32_t in_instanceID; ::ndk::ScopedFileDescriptor in_sharedMemoryFD; int32_t in_size; @@ -199,7 +225,7 @@ static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code break; } - case (FIRST_CALL_TRANSACTION + 10 /*destroy*/): { + case (FIRST_CALL_TRANSACTION + 11 /*destroy*/): { int32_t in_instanceID; _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_instanceID); @@ -260,6 +286,47 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::create(const std::string& in_plugin _aidl_status.set(AStatus_fromStatus(_aidl_ret_status)); return _aidl_status; } +::ndk::ScopedAStatus BpAudioPluginInterface::addExtension(int32_t in_instanceID, const std::string& in_uri, const ::ndk::ScopedFileDescriptor& in_sharedMemoryFD, int32_t in_size) { + binder_status_t _aidl_ret_status = STATUS_OK; + ::ndk::ScopedAStatus _aidl_status; + ::ndk::ScopedAParcel _aidl_in; + ::ndk::ScopedAParcel _aidl_out; + + _aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR()); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), in_instanceID); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_uri); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = ::ndk::AParcel_writeRequiredParcelFileDescriptor(_aidl_in.get(), in_sharedMemoryFD); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), in_size); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = AIBinder_transact( + asBinder().get(), + (FIRST_CALL_TRANSACTION + 1 /*addExtension*/), + _aidl_in.getR(), + _aidl_out.getR(), + 0); + if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && IAudioPluginInterface::getDefaultImpl()) { + return IAudioPluginInterface::getDefaultImpl()->addExtension(in_instanceID, in_uri, in_sharedMemoryFD, in_size); + } + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + _aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR()); + if (_aidl_ret_status != STATUS_OK) goto _aidl_error; + + if (!AStatus_isOk(_aidl_status.get())) return _aidl_status; + + _aidl_error: + _aidl_status.set(AStatus_fromStatus(_aidl_ret_status)); + return _aidl_status; +} ::ndk::ScopedAStatus BpAudioPluginInterface::isPluginAlive(int32_t in_instanceID, bool* _aidl_return) { binder_status_t _aidl_ret_status = STATUS_OK; ::ndk::ScopedAStatus _aidl_status; @@ -274,7 +341,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::isPluginAlive(int32_t in_instanceID _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 1 /*isPluginAlive*/), + (FIRST_CALL_TRANSACTION + 2 /*isPluginAlive*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -315,7 +382,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::prepare(int32_t in_instanceID, int3 _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 2 /*prepare*/), + (FIRST_CALL_TRANSACTION + 3 /*prepare*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -353,7 +420,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::prepareMemory(int32_t in_instanceID _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 3 /*prepareMemory*/), + (FIRST_CALL_TRANSACTION + 4 /*prepareMemory*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -385,7 +452,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::activate(int32_t in_instanceID) { _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 4 /*activate*/), + (FIRST_CALL_TRANSACTION + 5 /*activate*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -420,7 +487,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::process(int32_t in_instanceID, int3 _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 5 /*process*/), + (FIRST_CALL_TRANSACTION + 6 /*process*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -452,7 +519,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::deactivate(int32_t in_instanceID) { _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 6 /*deactivate*/), + (FIRST_CALL_TRANSACTION + 7 /*deactivate*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -484,7 +551,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::getStateSize(int32_t in_instanceID, _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 7 /*getStateSize*/), + (FIRST_CALL_TRANSACTION + 8 /*getStateSize*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -522,7 +589,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::getState(int32_t in_instanceID, con _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 8 /*getState*/), + (FIRST_CALL_TRANSACTION + 9 /*getState*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -560,7 +627,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::setState(int32_t in_instanceID, con _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 9 /*setState*/), + (FIRST_CALL_TRANSACTION + 10 /*setState*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -592,7 +659,7 @@ ::ndk::ScopedAStatus BpAudioPluginInterface::destroy(int32_t in_instanceID) { _aidl_ret_status = AIBinder_transact( asBinder().get(), - (FIRST_CALL_TRANSACTION + 10 /*destroy*/), + (FIRST_CALL_TRANSACTION + 11 /*destroy*/), _aidl_in.getR(), _aidl_out.getR(), 0); @@ -658,6 +725,11 @@ ::ndk::ScopedAStatus IAudioPluginInterfaceDefault::create(const std::string& /*i _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); return _aidl_status; } +::ndk::ScopedAStatus IAudioPluginInterfaceDefault::addExtension(int32_t /*in_instanceID*/, const std::string& /*in_uri*/, const ::ndk::ScopedFileDescriptor& /*in_sharedMemoryFD*/, int32_t /*in_size*/) { + ::ndk::ScopedAStatus _aidl_status; + _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); + return _aidl_status; +} ::ndk::ScopedAStatus IAudioPluginInterfaceDefault::isPluginAlive(int32_t /*in_instanceID*/, bool* /*_aidl_return*/) { ::ndk::ScopedAStatus _aidl_status; _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION)); diff --git a/native/androidaudioplugin/core/include/aap/android-audio-plugin-host.hpp b/native/androidaudioplugin/core/include/aap/android-audio-plugin-host.hpp index cc596e43..c94e70d6 100644 --- a/native/androidaudioplugin/core/include/aap/android-audio-plugin-host.hpp +++ b/native/androidaudioplugin/core/include/aap/android-audio-plugin-host.hpp @@ -313,19 +313,24 @@ PluginHostPAL* getPluginHostPAL(); class SharedMemoryExtension { - std::vector shared_memory_fds{}; + std::vector port_buffer_fds{}; + std::vector extension_fds{}; public: static char const *URI; SharedMemoryExtension() {} ~SharedMemoryExtension() { - for (int64_t fd : shared_memory_fds) + for (int64_t fd : port_buffer_fds) close(fd); - shared_memory_fds.clear(); + port_buffer_fds.clear(); + for (int64_t fd : extension_fds) + close(fd); + extension_fds.clear(); } - std::vector& getSharedMemoryFDs() { return shared_memory_fds; } + std::vector& getPortBufferFDs() { return port_buffer_fds; } + std::vector& getExtensionFDs() { return extension_fds; } }; class PluginHostManager; @@ -436,7 +441,7 @@ class PluginInstance return nullptr; } - inline SharedMemoryExtension* getSharedMemory() { return (SharedMemoryExtension*) getExtension(SharedMemoryExtension::URI); } + inline SharedMemoryExtension* getSharedMemoryExtension() { return (SharedMemoryExtension*) getExtension(SharedMemoryExtension::URI); } void prepare(int maximumExpectedSamplesPerBlock, AndroidAudioPluginBuffer *preparedBuffer) { diff --git a/native/androidaudioplugin/core/src/android-audio-plugin-host.cpp b/native/androidaudioplugin/core/src/android-audio-plugin-host.cpp index abf3136b..d9c794e3 100644 --- a/native/androidaudioplugin/core/src/android-audio-plugin-host.cpp +++ b/native/androidaudioplugin/core/src/android-audio-plugin-host.cpp @@ -75,7 +75,7 @@ std::vector PluginInformation::parsePluginMetadataXml(const void PluginHost::destroyInstance(PluginInstance* instance) { - auto shmExt = instance->getSharedMemory(); + auto shmExt = instance->getSharedMemoryExtension(); if (shmExt != nullptr) delete shmExt; delete instance; @@ -168,7 +168,7 @@ PluginInstance* PluginHost::instantiateRemotePlugin(const PluginInformation *des auto pluginFactory = factoryGetter(); assert (pluginFactory != nullptr); auto instance = new PluginInstance(this, descriptor, pluginFactory, sampleRate); - AndroidAudioPluginExtension ext{aap::SharedMemoryExtension::URI, new aap::SharedMemoryExtension()}; + AndroidAudioPluginExtension ext{aap::SharedMemoryExtension::URI, 0, new aap::SharedMemoryExtension()}; instance->addExtension (ext); return instance; } diff --git a/native/plugin-api/include/aap/android-audio-plugin.h b/native/plugin-api/include/aap/android-audio-plugin.h index 106373e0..7781f7fd 100644 --- a/native/plugin-api/include/aap/android-audio-plugin.h +++ b/native/plugin-api/include/aap/android-audio-plugin.h @@ -29,6 +29,7 @@ typedef struct { typedef struct { const char *uri; + int32_t transmit_size; void *data; } AndroidAudioPluginExtension;