summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Koch <martin.koch@ese.de>2020-06-19 16:01:19 +0200
committerMartin Koch <martin.koch@ese.de>2020-07-01 14:37:32 +0200
commit066c3f7f16ef69e80376942e8d6b8c4944b8ed08 (patch)
treed7d6ee7e5591e6915865ff0b0fa67191091032ca
parent4b34f9dc67e4ff1948d233346c2e5e3b14b8e78a (diff)
downloadaudiomanager-066c3f7f16ef69e80376942e8d6b8c4944b8ed08.tar.gz
Add support for announcement and handling of pre-established audio connections through routing side
As the complete initialization of the cockpit system takes some time, a few use-cases exist where information needs to be audible (or visible) right before the system is fully started. Here we mainly have: - system alerts + door open + seat belt missing + engine faults - parking assistant warnings + rear view camera screen + beeps if distance goes below limit Both routing- and control-side are extended to allow notifying about such connections Signed-off-by: Martin Koch <martin.koch@ese.de>
-rw-r--r--AudioManagerCore/include/CAmControlReceiver.h2
-rw-r--r--AudioManagerCore/include/CAmControlSender.h2
-rw-r--r--AudioManagerCore/include/CAmDatabaseHandlerMap.h1
-rw-r--r--AudioManagerCore/include/CAmRoutingReceiver.h3
-rw-r--r--AudioManagerCore/include/CAmRoutingSender.h2
-rw-r--r--AudioManagerCore/include/IAmDatabaseHandler.h1
-rw-r--r--AudioManagerCore/src/CAmControlReceiver.cpp34
-rw-r--r--AudioManagerCore/src/CAmControlSender.cpp7
-rw-r--r--AudioManagerCore/src/CAmDatabaseHandlerMap.cpp74
-rw-r--r--AudioManagerCore/src/CAmRoutingReceiver.cpp47
-rw-r--r--AudioManagerCore/src/CAmRoutingSender.cpp13
-rw-r--r--include/IAmControl.h45
-rw-r--r--include/IAmRouting.h47
13 files changed, 261 insertions, 17 deletions
diff --git a/AudioManagerCore/include/CAmControlReceiver.h b/AudioManagerCore/include/CAmControlReceiver.h
index bd897de..a7cb394 100644
--- a/AudioManagerCore/include/CAmControlReceiver.h
+++ b/AudioManagerCore/include/CAmControlReceiver.h
@@ -127,6 +127,8 @@ public:
void setRoutingRundown();
void confirmControllerReady(const am_Error_e error);
void confirmControllerRundown(const am_Error_e error);
+ am_Error_e transferConnection(const am_Handle_s handle, am_mainConnectionID_t mainConnectionID
+ , am_domainID_t domainID) override;
am_Error_e getSocketHandler(CAmSocketHandler * &socketHandler);
void getInterfaceVersion(std::string &version) const;
am_Error_e changeSourceDB(const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_SoundProperty_s> &listSoundProperties, const std::vector<am_CustomConnectionFormat_t> &listConnectionFormats, const std::vector<am_MainSoundProperty_s> &listMainSoundProperties);
diff --git a/AudioManagerCore/include/CAmControlSender.h b/AudioManagerCore/include/CAmControlSender.h
index 77e8e2c..494f7f3 100644
--- a/AudioManagerCore/include/CAmControlSender.h
+++ b/AudioManagerCore/include/CAmControlSender.h
@@ -71,6 +71,8 @@ public:
am_Error_e hookSystemDeregisterConverter(const am_converterID_t converterID);
am_Error_e hookSystemRegisterCrossfader(const am_Crossfader_s &crossfaderData, am_crossfaderID_t &crossfaderID);
am_Error_e hookSystemDeregisterCrossfader(const am_crossfaderID_t crossfaderID);
+ am_Error_e hookSystemRegisterEarlyConnection(am_domainID_t domainID
+ , const am_MainConnection_s &mainConnectionData);
void hookSystemSinkVolumeTick(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume);
void hookSystemSourceVolumeTick(const am_Handle_s handle, const am_sourceID_t sourceID, const am_volume_t volume);
void hookSystemInterruptStateChange(const am_sourceID_t sourceID, const am_InterruptState_e interruptState);
diff --git a/AudioManagerCore/include/CAmDatabaseHandlerMap.h b/AudioManagerCore/include/CAmDatabaseHandlerMap.h
index 46da560..a1ec6a3 100644
--- a/AudioManagerCore/include/CAmDatabaseHandlerMap.h
+++ b/AudioManagerCore/include/CAmDatabaseHandlerMap.h
@@ -175,6 +175,7 @@ public:
am_Error_e getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s &sinkData) const;
am_Error_e getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s &sourceData) const;
am_Error_e getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s &crossfaderData) const;
+ am_Error_e getConnectionInfoDB(const am_connectionID_t connectionID, am_Connection_s &connectionData) const;
am_Error_e getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s &mainConnectionData) const;
am_Error_e getSinkMainVolume(const am_sinkID_t sinkID, am_mainVolume_t &mainVolume) const;
am_Error_e getSinkVolume(const am_sinkID_t sinkID, am_volume_t &volume) const;
diff --git a/AudioManagerCore/include/CAmRoutingReceiver.h b/AudioManagerCore/include/CAmRoutingReceiver.h
index 42f3e89..3f85ba7 100644
--- a/AudioManagerCore/include/CAmRoutingReceiver.h
+++ b/AudioManagerCore/include/CAmRoutingReceiver.h
@@ -44,6 +44,7 @@ public:
CAmRoutingReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler);
CAmRoutingReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmControlSender *iControlSender, CAmSocketHandler *iSocketHandler, CAmDbusWrapper *iDBusWrapper);
~CAmRoutingReceiver();
+ void ackTransferConnection(const am_Handle_s handle, const am_Error_e errorID);
void ackConnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error);
void ackDisconnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error);
void ackSetSinkVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error);
@@ -59,6 +60,8 @@ public:
am_Error_e peekDomain(const std::string &name, am_domainID_t &domainID);
am_Error_e registerDomain(const am_Domain_s &domainData, am_domainID_t &domainID);
am_Error_e deregisterDomain(const am_domainID_t domainID);
+ am_Error_e registerEarlyConnection(am_domainID_t domainID, const std::vector< am_Connection_s > &route
+ , am_ConnectionState_e state);
am_Error_e registerGateway(const am_Gateway_s &gatewayData, am_gatewayID_t &gatewayID);
am_Error_e registerConverter(const am_Converter_s &converterData, am_converterID_t &converterID);
am_Error_e deregisterGateway(const am_gatewayID_t gatewayID);
diff --git a/AudioManagerCore/include/CAmRoutingSender.h b/AudioManagerCore/include/CAmRoutingSender.h
index 39b5c23..7756ccc 100644
--- a/AudioManagerCore/include/CAmRoutingSender.h
+++ b/AudioManagerCore/include/CAmRoutingSender.h
@@ -62,6 +62,8 @@ public:
am_Error_e startupInterfaces(CAmRoutingReceiver *iRoutingReceiver);
void setRoutingReady();
void setRoutingRundown();
+ am_Error_e asyncTransferConnection(const am_Handle_s handle, am_domainID_t domainID
+ , const std::vector<std::pair<std::string, std::string>> &route, am_ConnectionState_e state);
am_Error_e asyncAbort(const am_Handle_s &handle);
am_Error_e asyncConnect(am_Handle_s &handle, am_connectionID_t &connectionID, const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_CustomConnectionFormat_t connectionFormat);
am_Error_e asyncDisconnect(am_Handle_s &handle, const am_connectionID_t connectionID);
diff --git a/AudioManagerCore/include/IAmDatabaseHandler.h b/AudioManagerCore/include/IAmDatabaseHandler.h
index 8e4118e..495f4e6 100644
--- a/AudioManagerCore/include/IAmDatabaseHandler.h
+++ b/AudioManagerCore/include/IAmDatabaseHandler.h
@@ -114,6 +114,7 @@ public:
virtual am_Error_e getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s &sinkData) const = 0;
virtual am_Error_e getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s &sourceData) const = 0;
virtual am_Error_e getCrossfaderInfoDB(const am_crossfaderID_t crossfaderID, am_Crossfader_s &crossfaderData) const = 0;
+ virtual am_Error_e getConnectionInfoDB(const am_connectionID_t connectionID, am_Connection_s &connectionData) const = 0;
virtual am_Error_e getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s &mainConnectionData) const = 0;
virtual am_Error_e getSinkMainVolume(const am_sinkID_t sinkID, am_mainVolume_t &mainVolume) const = 0;
virtual am_Error_e getSinkVolume(const am_sinkID_t sinkID, am_volume_t &volume) const = 0;
diff --git a/AudioManagerCore/src/CAmControlReceiver.cpp b/AudioManagerCore/src/CAmControlReceiver.cpp
index 7a6072c..bbd1116 100644
--- a/AudioManagerCore/src/CAmControlReceiver.cpp
+++ b/AudioManagerCore/src/CAmControlReceiver.cpp
@@ -451,6 +451,40 @@ void CAmControlReceiver::confirmControllerRundown(const am_Error_e error)
mSocketHandler->exit_mainloop();
}
+am_Error_e CAmControlReceiver::transferConnection(const am_Handle_s handle
+ , am_mainConnectionID_t mainConnectionID, am_domainID_t domainID)
+{
+ am_MainConnection_s mainConnectionData;
+ if (mDatabaseHandler->getMainConnectionInfoDB(mainConnectionID, mainConnectionData) != E_OK)
+ {
+ return E_DATABASE_ERROR;
+ }
+
+ std::vector<std::pair<std::string, std::string>> route;
+ route.reserve(mainConnectionData.listConnectionID.size());
+ for (auto iter : mainConnectionData.listConnectionID)
+ {
+ am_Connection_s connectionData;
+ if (mDatabaseHandler->getConnectionInfoDB(iter, connectionData) != E_OK)
+ {
+ return E_DATABASE_ERROR;
+ }
+
+ // determine source and sink name, even if they are only peeked, but not fully registered
+ am_Source_s sourceData;
+ am_Sink_s sinkData;
+ if ( (mDatabaseHandler->getSourceInfoDB(connectionData.sourceID, sourceData) == E_NON_EXISTENT)
+ || (mDatabaseHandler->getSinkInfoDB(connectionData.sinkID, sinkData) == E_NON_EXISTENT))
+ {
+ return E_DATABASE_ERROR;
+ }
+
+ route.push_back({sourceData.name, sinkData.name});
+ }
+
+ return mRoutingSender->asyncTransferConnection(handle, domainID, route, mainConnectionData.connectionState);
+}
+
am_Error_e CAmControlReceiver::getSocketHandler(CAmSocketHandler * &socketHandler)
{
socketHandler = mSocketHandler;
diff --git a/AudioManagerCore/src/CAmControlSender.cpp b/AudioManagerCore/src/CAmControlSender.cpp
index 0fa84ef..0d28dfb 100644
--- a/AudioManagerCore/src/CAmControlSender.cpp
+++ b/AudioManagerCore/src/CAmControlSender.cpp
@@ -319,6 +319,13 @@ am_Error_e CAmControlSender::hookSystemDeregisterCrossfader(const am_crossfaderI
return (mController->hookSystemDeregisterCrossfader(crossfaderID));
}
+am_Error_e CAmControlSender::hookSystemRegisterEarlyConnection(am_domainID_t domainID
+ , const am_MainConnection_s &mainConnectionData)
+{
+ assert(mController);
+ return mController->hookSystemRegisterEarlyMainConnection(domainID, mainConnectionData);
+}
+
void CAmControlSender::hookSystemSinkVolumeTick(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume)
{
assert(mController);
diff --git a/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
index 6e6e3f9..95d7b1a 100644
--- a/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
+++ b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
@@ -611,6 +611,20 @@ am_Error_e CAmDatabaseHandlerMap::enterMainConnectionDB(const am_MainConnection_
return (E_NOT_POSSIBLE);
}
+ // check if we already have this connection
+ for (auto &mapped : mMappedData.mMainConnectionMap)
+ {
+ if ((mapped.second.sourceID != mainConnectionData.sourceID) || (mapped.second.sinkID != mainConnectionData.sinkID))
+ {
+ continue;
+ }
+
+ connectionID = mapped.second.mainConnectionID;
+ logWarning(__METHOD_NAME__, "main connection from source", mainConnectionData.sourceID
+ , "to sink", mainConnectionData.sinkID, "already exists with ID", connectionID);
+ return E_ALREADY_EXISTS;
+ }
+
int16_t delay = 0;
int16_t nextID = 0;
if (mMappedData.increaseMainConnectionID(nextID))
@@ -1169,6 +1183,20 @@ am_Error_e CAmDatabaseHandlerMap::enterConnectionDB(const am_Connection_s &conne
return (E_NOT_POSSIBLE);
}
+ // check if we already have this connection
+ for (auto &mapped : mMappedData.mConnectionMap)
+ {
+ if ((mapped.second.sourceID != connection.sourceID) || (mapped.second.sinkID != connection.sinkID))
+ {
+ continue;
+ }
+
+ connectionID = mapped.second.connectionID;
+ logWarning(__METHOD_NAME__, "connection from source", connection.sourceID
+ , "to sink", connection.sinkID, "already exists with ID", connectionID);
+ return E_ALREADY_EXISTS;
+ }
+
// connection format is not checked, because it's project specific
int16_t nextID = 0;
if (mMappedData.increaseConnectionID(nextID))
@@ -1917,54 +1945,66 @@ am_Error_e CAmDatabaseHandlerMap::getSourceClassInfoDB(const am_sourceID_t sourc
am_Error_e CAmDatabaseHandlerMap::getSinkInfoDB(const am_sinkID_t sinkID, am_Sink_s &sinkData) const
{
-
- if (!existSink(sinkID))
+ auto iter = mMappedData.mSinkMap.find(sinkID);
+ if (iter == mMappedData.mSinkMap.end())
{
logWarning(__METHOD_NAME__, "sinkID", sinkID, "does not exist");
return (E_NON_EXISTENT);
}
- am_Sink_Database_s mappedSink = mMappedData.mSinkMap.at(sinkID);
- if ( true == mappedSink.reserved )
+ sinkData = iter->second; // copy to output parameter even if only ID and name are valid
+ if ( iter->second.reserved )
{
- return (E_NON_EXISTENT);
+ logWarning(__METHOD_NAME__, "sinkID", sinkID, "reserved for", sinkData.name, "but details are E_UNKNOWN");
+ return E_UNKNOWN;
}
- sinkData = mappedSink;
-
return (E_OK);
}
am_Error_e CAmDatabaseHandlerMap::getSourceInfoDB(const am_sourceID_t sourceID, am_Source_s &sourceData) const
{
-
- if (!existSource(sourceID))
+ auto iter = mMappedData.mSourceMap.find(sourceID);
+ if (iter == mMappedData.mSourceMap.end())
{
logWarning(__METHOD_NAME__, "sourceID", sourceID, "does not exist");
return (E_NON_EXISTENT);
}
- am_Source_Database_s mappedSource = mMappedData.mSourceMap.at(sourceID);
- if ( true == mappedSource.reserved )
+ sourceData = iter->second; // copy to output parameter even if only ID and name are valid
+ if ( true == iter->second.reserved )
{
+ logWarning(__METHOD_NAME__, "sourceID", sourceID, "reserved for", sourceData.name, "but details are E_UNKNOWN");
+ return E_UNKNOWN;
+ }
+
+ return (E_OK);
+}
+
+am_Error_e am::CAmDatabaseHandlerMap::getConnectionInfoDB(const am_connectionID_t connectionID, am_Connection_s &connectionData) const
+{
+ auto iter = mMappedData.mConnectionMap.find(connectionID);
+ if (iter == mMappedData.mConnectionMap.end())
+ {
+ logError(__METHOD_NAME__, "connectionID", connectionID, "does not exist");
return (E_NON_EXISTENT);
}
- sourceData = mappedSource;
+ connectionData = iter->second;
- return (E_OK);
+ return E_OK;
}
am_Error_e am::CAmDatabaseHandlerMap::getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s &mainConnectionData) const
{
- if (!existMainConnection(mainConnectionID))
+ auto iter = mMappedData.mMainConnectionMap.find(mainConnectionID);
+ if (iter == mMappedData.mMainConnectionMap.end())
{
- logError(__METHOD_NAME__, "mainConnectionID must exist");
+ logError(__METHOD_NAME__, "mainConnectionID", mainConnectionID, "does not exist");
return (E_NON_EXISTENT);
}
- am_MainConnection_s temp = mMappedData.mMainConnectionMap.at(mainConnectionID);
- mainConnectionData = temp;
+ mainConnectionData = iter->second;
return (E_OK);
}
diff --git a/AudioManagerCore/src/CAmRoutingReceiver.cpp b/AudioManagerCore/src/CAmRoutingReceiver.cpp
index be13474..8f4d1ba 100644
--- a/AudioManagerCore/src/CAmRoutingReceiver.cpp
+++ b/AudioManagerCore/src/CAmRoutingReceiver.cpp
@@ -124,6 +124,19 @@ void CAmRoutingReceiver::ackDisconnect(const am_Handle_s handle, const am_connec
mpControlSender->cbAckDisconnect(handle, error);
}
+/**
+ * Support hand-over acknowledgment of connections surviving shutdown of the AM
+ *
+ * @param handle: composite identifier used in the request
+ * @param errorID:success indicator (E_OK if application takes over,
+ * E_NOT_POSSIBLE if the routing adapter is not prepared to take over
+ * full responsibility for all involved sources and sinks)
+ */
+void CAmRoutingReceiver::ackTransferConnection(const am_Handle_s handle, const am_Error_e errorID)
+{
+
+}
+
void CAmRoutingReceiver::ackSetSinkVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error)
{
logInfo(__METHOD_NAME__, "handle=", handle, "volume=", volume, "error=", error);
@@ -233,6 +246,40 @@ am_Error_e CAmRoutingReceiver::deregisterDomain(const am_domainID_t domainID)
return (mpControlSender->hookSystemDeregisterDomain(domainID));
}
+am_Error_e CAmRoutingReceiver::registerEarlyConnection(am_domainID_t domainID
+ , const std::vector< am_Connection_s > &route, am_ConnectionState_e state)
+{
+ if (route.size() < 1)
+ {
+ logWarning(__METHOD_NAME__, "route empty");
+ return E_NOT_POSSIBLE;
+ }
+
+ am_MainConnection_s mainConnectionData;
+ mainConnectionData.sourceID = route.front().sourceID;
+ mainConnectionData.sinkID = route.back().sinkID;
+ mainConnectionData.connectionState = state;
+ mainConnectionData.listConnectionID.reserve(route.size());
+ for (auto & conn : route)
+ {
+ am_connectionID_t connectionID;
+ am_Error_e success = mpDatabaseHandler->enterConnectionDB(conn, connectionID);
+ switch (success)
+ {
+ case E_OK:
+ case E_ALREADY_EXISTS:
+ case E_NO_CHANGE:
+ mainConnectionData.listConnectionID.push_back(connectionID);
+ break;
+
+ default:
+ return success;
+ }
+ }
+
+ return mpControlSender->hookSystemRegisterEarlyConnection(domainID, mainConnectionData);
+}
+
am_Error_e CAmRoutingReceiver::registerGateway(const am_Gateway_s &gatewayData, am_gatewayID_t &gatewayID)
{
return (mpControlSender->hookSystemRegisterGateway(gatewayData, gatewayID));
diff --git a/AudioManagerCore/src/CAmRoutingSender.cpp b/AudioManagerCore/src/CAmRoutingSender.cpp
index 36f5c1a..399de9a 100644
--- a/AudioManagerCore/src/CAmRoutingSender.cpp
+++ b/AudioManagerCore/src/CAmRoutingSender.cpp
@@ -921,6 +921,19 @@ void CAmRoutingSender::setRoutingRundown()
}
}
+am_Error_e CAmRoutingSender::asyncTransferConnection(const am_Handle_s handle, am_domainID_t domainID
+ , const std::vector<std::pair<std::string, std::string>> &route, am_ConnectionState_e state)
+{
+ auto iter = mMapDomainInterface.find(domainID);
+ if (iter != mMapDomainInterface.end() && iter->second)
+ {
+ return iter->second->asyncTransferConnection(handle, route, state);
+ }
+
+ // given domain not found in map
+ return E_NON_EXISTENT;
+}
+
am_Error_e CAmRoutingSender::asyncSetVolumes(am_Handle_s &handle, const std::vector<am_Volumes_s> &listVolumes)
{
IAmRoutingSend *pRoutingInterface(NULL);
diff --git a/include/IAmControl.h b/include/IAmControl.h
index 32008a0..e8545ad 100644
--- a/include/IAmControl.h
+++ b/include/IAmControl.h
@@ -554,6 +554,20 @@ public:
* confirmRoutingRundown.
*/
virtual void setRoutingRundown() =0;
+
+ /**
+ * Hand-over to routing-side application any connection meant to survive AM shutdown
+ *
+ * @param handle: composite identifier used to map the response
+ * @param domainID: target domain which shall take over
+ * @param mainConnectionID: subject of this request
+ *
+ * @return E_OK if command was forwarded to routing adapter successfully,
+ * E_COMMUNICATION or other meaningful value otherwise
+ */
+ virtual am_Error_e transferConnection(const am_Handle_s handle
+ , am_mainConnectionID_t mainConnectionID, am_domainID_t domainID) = 0;
+
/**
* acknowledges the setControllerReady call.
*/
@@ -858,6 +872,24 @@ public:
* @return E_OK on success, E_UNKNOWN on error, E_NON_EXISTENT if not found
*/
virtual am_Error_e hookSystemDeregisterCrossfader(const am_crossfaderID_t crossfaderID) =0;
+
+ /**
+ * Support announcement of audio connections already active at AM startup
+ *
+ * @param domainID: home domain announcing this early connection
+ * @param mainConnectionData: details of main connection
+ *
+ * @return success indicator. Controller should use E_OK on success,
+ * E_ALREADY_EXISTS or E_NO_CHANGE if given connection is already registered,
+ * E_DATABASE_ERROR if any of the listed sources or sinks does not exist in the data base,
+ * E_NOT_POSSIBLE if feature is not supported by the controller
+ */
+ virtual am_Error_e hookSystemRegisterEarlyMainConnection(am_domainID_t domainID
+ , const am_MainConnection_s &mainConnectionData)
+ {
+ return E_NOT_POSSIBLE; // empty default implementation
+ }
+
/**
* volumeticks. therse are used to indicate volumechanges during a ramp
*/
@@ -905,6 +937,19 @@ public:
* ack for disconnect
*/
virtual void cbAckDisconnect(const am_Handle_s handle, const am_Error_e errorID) =0;
+
+ /**
+ * Hand-over acknowledgment of connections surviving shutdown of the AM,
+ * forwarded from routing side (see @ref IAmRoutingReceive::ackTransferConnection)
+ *
+ * @param handle: composite identifier mirrored from request
+ * @param errorID: success indicator as obtained from routing side application
+ */
+ virtual void cbAckTransferConnection(const am_Handle_s /* handle */, const am_Error_e /* errorID */)
+ {
+ // empty default implementation
+ }
+
/**
* ack for crossfading
*/
diff --git a/include/IAmRouting.h b/include/IAmRouting.h
index 1acaac6..28e8ac9 100644
--- a/include/IAmRouting.h
+++ b/include/IAmRouting.h
@@ -139,6 +139,34 @@ public:
* @return E_OK on succes, E_NON_EXISTENT if not found E_UNKOWN on error
*/
virtual am_Error_e deregisterDomain(const am_domainID_t domainID) =0;
+
+ /**
+ * Support announcement of audio connections already active at AM startup
+ *
+ * @param domainID: home domain announcing this early connection
+ * @param route: list of sub-connections (populated with unspecified connectionID=0 field)
+ * @param state: either stable CS_CONNECTED, CS_DISCONNECTED, CS_SUSPENDED
+ * or transient CS_CONNECTING, CS_DISCONNECTING
+ *
+ * @return success indicator as obtained from the controller
+ *
+ * @note If the connection is announced with one of the transient states
+ * CS_CONNECTING or CS_DISCONNECTING, a secondary registerEarlyConnection()
+ * call is expected once a stable state is reached
+ */
+ virtual am_Error_e registerEarlyConnection(am_domainID_t domainID, const std::vector< am_Connection_s > &route
+ , am_ConnectionState_e state) = 0;
+
+ /**
+ * Notify hand-over acknowledgment of connections surviving shutdown of the AM
+ *
+ * @param handle: composite identifier used in the request
+ * @param errorID: success indicator as obtained from the routing-side application,
+ * e.g. E_OK if the application assumes full responsibility,
+ * any meaningful error condition otherwise
+ */
+ virtual void ackTransferConnection(const am_Handle_s handle, const am_Error_e errorID) = 0;
+
/**
* registers a converter. @return E_OK on succes, E_ALREADY_EXISTENT if already
* registered E_UNKOWN on error
@@ -385,6 +413,25 @@ public:
* or be ready again.
*/
virtual void setRoutingRundown(const uint16_t handle) =0;
+
+ /**
+ * Forward hand-over of a connection meant to survive AM shutdown
+ * in routing-side application
+ *
+ * @param handle: composite identifier used to map the response
+ * @param route: names of involved sources and sinks including intermediate gateways
+ * @param state: either stable CS_CONNECTED, CS_DISCONNECTED, CS_SUSPENDED
+ * or transient CS_CONNECTING, CS_DISCONNECTING
+ *
+ * @return success indicator as obtained from the plugins, e.g E_OK or E_COMMUNICATION
+ */
+ virtual am_Error_e asyncTransferConnection(const am_Handle_s handle
+ , const std::vector<std::pair<std::string, std::string>> &route
+ , am_ConnectionState_e state)
+ {
+ return E_NOT_POSSIBLE; // default response if not supported by the plugin
+ }
+
/**
* aborts an asynchronous action.
* @return E_OK on success, E_UNKNOWN on error, E_NON_EXISTENT if handle was not