summaryrefslogtreecommitdiff
path: root/AudioManagerCore/src
diff options
context:
space:
mode:
Diffstat (limited to 'AudioManagerCore/src')
-rw-r--r--AudioManagerCore/src/CAmControlReceiver.cpp41
-rw-r--r--AudioManagerCore/src/CAmControlSender.cpp13
-rw-r--r--AudioManagerCore/src/CAmDatabaseHandlerMap.cpp90
-rw-r--r--AudioManagerCore/src/CAmRoutingReceiver.cpp78
-rw-r--r--AudioManagerCore/src/CAmRoutingSender.cpp25
5 files changed, 222 insertions, 25 deletions
diff --git a/AudioManagerCore/src/CAmControlReceiver.cpp b/AudioManagerCore/src/CAmControlReceiver.cpp
index 7a6072c..7efee95 100644
--- a/AudioManagerCore/src/CAmControlReceiver.cpp
+++ b/AudioManagerCore/src/CAmControlReceiver.cpp
@@ -128,7 +128,7 @@ am_Error_e CAmControlReceiver::enterDomainDB(const am_Domain_s &domainData, am_d
am_Error_e CAmControlReceiver::enterMainConnectionDB(const am_MainConnection_s &mainConnectionData, am_mainConnectionID_t &connectionID)
{
- return (mDatabaseHandler->enterMainConnectionDB(mainConnectionData, connectionID));
+ return (mDatabaseHandler->enterMainConnectionDB(mainConnectionData, connectionID, false));
}
am_Error_e CAmControlReceiver::enterSinkDB(const am_Sink_s &sinkData, am_sinkID_t &sinkID)
@@ -291,6 +291,11 @@ am_Error_e CAmControlReceiver::getSourceInfoDB(const am_sourceID_t sourceID, am_
return (mDatabaseHandler->getSourceInfoDB(sourceID, sourceData));
}
+am_Error_e CAmControlReceiver::getConnectionInfoDB(const am_connectionID_t connectionID, am_Connection_s &connectionData) const
+{
+ return (mDatabaseHandler->getConnectionInfoDB(connectionID, connectionData));
+}
+
am_Error_e CAmControlReceiver::getMainConnectionInfoDB(const am_mainConnectionID_t mainConnectionID, am_MainConnection_s &mainConnectionData) const
{
return (mDatabaseHandler->getMainConnectionInfoDB(mainConnectionID, mainConnectionData));
@@ -451,6 +456,40 @@ void CAmControlReceiver::confirmControllerRundown(const am_Error_e error)
mSocketHandler->exit_mainloop();
}
+am_Error_e CAmControlReceiver::transferConnection(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..bb92198 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, const am_Route_s &route)
+{
+ assert(mController);
+ return mController->hookSystemRegisterEarlyMainConnection(domainID, mainConnectionData, route);
+}
+
void CAmControlSender::hookSystemSinkVolumeTick(const am_Handle_s handle, const am_sinkID_t sinkID, const am_volume_t volume)
{
assert(mController);
@@ -385,6 +392,12 @@ void CAmControlSender::cbAckDisconnect(const am_Handle_s handle, const am_Error_
mController->cbAckDisconnect(handle, errorID);
}
+void CAmControlSender::cbAckTransferConnection(const am_Handle_s handle, const am_Error_e errorID)
+{
+ assert(mController);
+ mController->cbAckTransferConnection(handle, errorID);
+}
+
void CAmControlSender::cbAckCrossFade(const am_Handle_s handle, const am_HotSink_e hostsink, const am_Error_e error)
{
assert(mController);
diff --git a/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
index 6e6e3f9..fc539bb 100644
--- a/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
+++ b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
@@ -585,7 +585,7 @@ int16_t CAmDatabaseHandlerMap::calculateDelayForRoute(const std::vector<am_conne
return delay;
}
-am_Error_e CAmDatabaseHandlerMap::enterMainConnectionDB(const am_MainConnection_s &mainConnectionData, am_mainConnectionID_t &connectionID)
+am_Error_e CAmDatabaseHandlerMap::enterMainConnectionDB(const am_MainConnection_s &mainConnectionData, am_mainConnectionID_t &connectionID, bool allowReserved)
{
if (mainConnectionData.mainConnectionID != 0)
{
@@ -599,18 +599,34 @@ am_Error_e CAmDatabaseHandlerMap::enterMainConnectionDB(const am_MainConnection_
return (E_NOT_POSSIBLE);
}
- if (!existSink(mainConnectionData.sinkID))
+ auto itMappedSink = mMappedData.mSinkMap.find(mainConnectionData.sinkID);
+ if ((itMappedSink == mMappedData.mSinkMap.end()) || (itMappedSink->second.reserved && !allowReserved))
{
logError(__METHOD_NAME__, "sinkID must be valid!");
return (E_NOT_POSSIBLE);
}
- if (!existSource(mainConnectionData.sourceID))
+ auto itMappedSource = mMappedData.mSourceMap.find(mainConnectionData.sourceID);
+ if ((itMappedSource == mMappedData.mSourceMap.end()) || (itMappedSource->second.reserved && !allowReserved))
{
logError(__METHOD_NAME__, "sourceID must be valid!");
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))
@@ -1149,7 +1165,7 @@ am_Error_e CAmDatabaseHandlerMap::enterSourceDB(const am_Source_s &sourceData, a
return (E_OK);
}
-am_Error_e CAmDatabaseHandlerMap::enterConnectionDB(const am_Connection_s &connection, am_connectionID_t &connectionID)
+am_Error_e CAmDatabaseHandlerMap::enterConnectionDB(const am_Connection_s &connection, am_connectionID_t &connectionID, bool allowReserved)
{
if (connection.connectionID != 0)
{
@@ -1157,18 +1173,34 @@ am_Error_e CAmDatabaseHandlerMap::enterConnectionDB(const am_Connection_s &conne
return (E_NOT_POSSIBLE);
}
- if (!existSink(connection.sinkID))
+ const AmMapSink::const_iterator &itMappedSink = mMappedData.mSinkMap.find(connection.sinkID);
+ if ((itMappedSink == mMappedData.mSinkMap.end()) || (itMappedSink->second.reserved && !allowReserved))
{
logError(__METHOD_NAME__, "sinkID must exist!");
return (E_NOT_POSSIBLE);
}
- if (!existSource(connection.sourceID))
+ const AmMapSource::const_iterator &itMappedSource = mMappedData.mSourceMap.find(connection.sourceID);
+ if ((itMappedSource == mMappedData.mSourceMap.end()) || (itMappedSource->second.reserved && !allowReserved))
{
logError(__METHOD_NAME__, "sourceID must exist!");
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 +1949,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..56fb5e2 100644
--- a/AudioManagerCore/src/CAmRoutingReceiver.cpp
+++ b/AudioManagerCore/src/CAmRoutingReceiver.cpp
@@ -124,6 +124,28 @@ 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 error)
+{
+ if (error == E_OK)
+ {
+ mpRoutingSender->writeToDatabaseAndRemove(handle);
+ }
+ else
+ {
+ mpRoutingSender->removeHandle(handle);
+ }
+
+ mpControlSender->cbAckTransferConnection(handle, error);
+}
+
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 +255,62 @@ am_Error_e CAmRoutingReceiver::deregisterDomain(const am_domainID_t domainID)
return (mpControlSender->hookSystemDeregisterDomain(domainID));
}
+am_Error_e CAmRoutingReceiver::registerEarlyConnection(am_domainID_t domainID
+ , const am_Route_s &route, am_ConnectionState_e state)
+{
+ const auto &segmentList = route.route;
+ if (segmentList.size() < 1)
+ {
+ logError(__METHOD_NAME__, "empty route from domain", domainID);
+ return E_NOT_POSSIBLE;
+ }
+
+ am_MainConnection_s mainConnectionData;
+ mainConnectionData.mainConnectionID = 0;
+ mainConnectionData.sourceID = segmentList.front().sourceID;
+ mainConnectionData.sinkID = segmentList.back().sinkID;
+ mainConnectionData.connectionState = state;
+ mainConnectionData.listConnectionID.reserve(segmentList.size());
+ for (const auto &segment : segmentList)
+ {
+ am_Connection_s conn;
+ conn.sourceID = segment.sourceID;
+ conn.sinkID = segment.sinkID;
+ conn.connectionFormat = segment.connectionFormat;
+ conn.connectionID = 0;
+ am_Error_e success = mpDatabaseHandler->enterConnectionDB(conn, conn.connectionID, true);
+ switch (success)
+ {
+ case E_OK:
+ case E_ALREADY_EXISTS:
+ case E_NO_CHANGE:
+ mainConnectionData.listConnectionID.push_back(conn.connectionID);
+ break;
+
+ default:
+ logError(__METHOD_NAME__, "failed to enter connection segment", conn.sourceID
+ , "to", conn.sinkID, "from domain", domainID, "error=", success);
+ return success;
+ }
+ }
+
+ am_Error_e success = mpDatabaseHandler->enterMainConnectionDB(mainConnectionData, mainConnectionData.mainConnectionID, true);
+ switch (success)
+ {
+ case E_OK:
+ case E_ALREADY_EXISTS:
+ case E_NO_CHANGE:
+ break;
+
+ default:
+ logError(__METHOD_NAME__, "failed to enter main connection", mainConnectionData.sourceID
+ , "to", mainConnectionData.sinkID, "from domain", domainID, "error=", success);
+ return success;
+ }
+
+ return mpControlSender->hookSystemRegisterEarlyConnection(domainID, mainConnectionData, route);
+}
+
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..fc9f879 100644
--- a/AudioManagerCore/src/CAmRoutingSender.cpp
+++ b/AudioManagerCore/src/CAmRoutingSender.cpp
@@ -285,7 +285,7 @@ am_Error_e CAmRoutingSender::asyncConnect(am_Handle_s &handle, am_connectionID_t
tempConnection.connectionID = 0;
tempConnection.delay = -1;
- am_Error_e connError(mpDatabaseHandler->enterConnectionDB(tempConnection, connectionID));
+ am_Error_e connError(mpDatabaseHandler->enterConnectionDB(tempConnection, connectionID, false));
if (connError)
{
return(connError);
@@ -921,6 +921,29 @@ void CAmRoutingSender::setRoutingRundown()
}
}
+am_Error_e CAmRoutingSender::asyncTransferConnection(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)
+ {
+ auto handleData = std::make_shared<handleTransfer>(iter->second, route, state, mpDatabaseHandler);
+ handle = createHandle(handleData, H_TRANSFERCONNECTION);
+
+ logInfo(__METHOD_NAME__, "handle=", handle);
+
+ am_Error_e success = iter->second->asyncTransferConnection(handle, domainID, route, state);
+ if (success != E_OK)
+ {
+ removeHandle(handle);
+ }
+ return success;
+ }
+
+ // 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);