diff options
Diffstat (limited to 'PluginControlInterfacePulse/include')
-rw-r--r-- | PluginControlInterfacePulse/include/ControlConfig.h | 221 | ||||
-rw-r--r-- | PluginControlInterfacePulse/include/ControlSender.h | 334 |
2 files changed, 555 insertions, 0 deletions
diff --git a/PluginControlInterfacePulse/include/ControlConfig.h b/PluginControlInterfacePulse/include/ControlConfig.h new file mode 100644 index 0000000..8648c77 --- /dev/null +++ b/PluginControlInterfacePulse/include/ControlConfig.h @@ -0,0 +1,221 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2011-2014, Wind River Systems + * Copyright (C) 2014, GENIVI Alliance + * + * This file is part of Pulse Audio Interface Control Plugin. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License (MPL), v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * + * List of changes: + * + * 08.09.2014, Adrian Scarlat, First version of the code; + * Porting from AM ver 1.x; + */ + +#ifndef CONTROLCONFIG_H_ +#define CONTROLCONFIG_H_ + +#include "audiomanagertypes.h" +#include <string> + + +/* Defines */ + +#define SOURCE_TYPE_INTERRUPT (1) +#define SOURCE_TYPE_MAIN (2) +#define SINK_TYPE_MAIN (2) + +#define ACTION_TYPE_STR(x) (\ +(x == AT_MUTE) ? "AT_MUTE" : \ +(x == AT_UNMUTE) ? "AT_UNMUTE" : \ +(x == AT_PAUSE) ? "AT_PAUSE" : \ +(x == AT_RESUME) ? "AT_RESUME" : \ +(x == AT_VOLUME_DECREASE) ? "AT_VOLUME_DECREASE" : \ +(x == AT_VOLUME_INCREASE) ? "AT_VOLUME_INCREASE" : \ +(x == AT_DISCONNECT) ? "AT_DISCONNECT" : \ +(x == AT_CONNECT) ? "AT_CONNECT" : \ +#x":Unknown") + + +/** + * Action types sorted by priority: lowest - the most important + */ +enum am_ActionType_e +{ + AT_DISCONNECT=0, + AT_PAUSE=1, + AT_MUTE=2, + AT_UNMUTE=3, + AT_VOLUME_DECREASE=4, + AT_CONNECT=5, + AT_RESUME=6, + AT_VOLUME_INCREASE=7, + AT_MAX +}; + + +enum am_ActionTarget_e +{ + ATG_SINK=0, + ATG_SOURCE=1, + ATG_GW_SINK=2, + ATG_GW_SOURCE=3, + ATG_MAX +}; + + +/* + * e.g. Entertainment : Entertainment>HifiAudio Sink:Disconnect:Pulse:Source + */ +struct am_ConnectAction_s { + bool interrupting; /* The action is triggered by an interrupting source class: e.g. TTS, Phone */ + bool pending; /* The action was not applied yet. */ + /* e.g. there is an action with higher priority which is already applied to this connection */ + am::am_sourceClass_t activeSourceClassID; /* The name of the source class of existing connections - the one to be controlled */ + am::am_sinkID_t activeSinkID; /* The name of the sink of existing connections - the one to be controlled */ + am_ActionType_e actionType; /* What kind of action the controller decided: mute, pause, volume adjustment */ + am::am_domainID_t targetDomain; /* The domain of target element */ + am_ActionTarget_e targetElement; /* What element is controlled: sink, source or gateway */ + /** + * Define a list of inverse actions: if the controller applied an action during connection procedure, + * the inverse action (of any) shall be applied on disconnect. + */ + static am_ActionType_e inverseAction(am_ActionType_e type) + { + switch(type) + { + case AT_MUTE: return (AT_UNMUTE); + case AT_UNMUTE: return (AT_MUTE); + + case AT_PAUSE: return (AT_RESUME); + case AT_RESUME: return (AT_PAUSE); + + case AT_VOLUME_DECREASE: return (AT_VOLUME_INCREASE); + case AT_VOLUME_INCREASE: return (AT_VOLUME_DECREASE); + + case AT_DISCONNECT: return (AT_CONNECT);//disconnection is not an invertible action; maybe it is + case AT_CONNECT: return (AT_MAX);//connection is not an invertible action + + default: return (AT_MAX); // default return value + } + } + + + /** + * Compare everything except action type. + */ + bool weekCompare(struct am_ConnectAction_s &o) const + { + return ((this->activeSourceClassID == o.activeSourceClassID) && + (this->activeSinkID == o.activeSinkID) && + (this->targetDomain == o.targetDomain) && + (this->targetElement == o.targetElement)); + } + + /** + * Compare action type + */ + bool operator < (struct am_ConnectAction_s &o) const + { + return this->actionType < o.actionType; + } + +}; + + +struct am_MixingRule_s { + am::am_sourceClass_t mixingSourceClassID; /* the name of the source class to be connected/disconnected */ + std::vector<am_ConnectAction_s> actions; /* actions: e.g decrease volume for source of class Entertainment */ +}; + +#endif + + +/* +USE-CASE 1 +========== + +Start Entertainment(connectionID = 1) + +Start Phone (connectionID = 2) + (A1)- actions caused by connectionID[2]: action on connectionID = 1 - mute source + +Start Navigation (connectionID = 3) + (A2) - actions cause by connectionID[3]: action on connectionID = 1 - decrease volume (pending): A1 - higher priority than A2 + (A3) - action caused by connectionID[2]: action on connectionID = 3 - decrease volume (applied) + + +End Phone + - inverse action (A1) - unmute connectionID = 1 + - Check if there is any pending action that could be applied, but was blocked by A1 + (A2) - actions cause by connectionID[3]: action on connectionID = 1 - decrease volume + - inverse action (A3) - increase volume connectionID = 3 + - Check if there is any pending action that could be applied, but was blocked by A3 - none + + + +USE-CASE 2 +========== + + +Start Entertainment(connectionID = 1) + +Start Navigation (connectionID = 2) + (A1) - actions cause by connectionID[2]: action on connectionID = 1 - decrease volume (applied) + + +Start Phone (connectionID = 3) + (A2) - action caused by connectionID[3]: action on connectionID = 2 - decrease volume (applied) + (A3) - actions caused by connectionID[1]: action on connectionID = 1 - mute source; A1 - pending + + +End Phone + - inverse action (A2) - increase volume connectionID = 2 + - Check if there is any pending action that could be applied, but was blocked by A3 - none + - inverse action (A3) - unmute connectionID = 1 + - Check if there is any pending action that could be applied, but was blocked by A3 + (A1) - actions cause by connectionID[2]: action on connectionID = 1 - decrease volume (applied) + + + + +USE-CASE 3 +========== + + +Start Entertainment(connectionID = 1) + +Start Navigation (connectionID = 2) + (A1) - actions cause by connectionID[2]: action on connectionID = 1 - decrease volume (applied) + + +Start Phone (connectionID = 3) + (A2) - action caused by connectionID[3]: action on connectionID = 2 - decrease volume (applied) + (A3) - actions caused by connectionID[3]: action on connectionID = 1 - mute source; A1 - pending + +End Navigation + - inverse action (A1) - A1 is pending ... no action to apply + +End Phone + - inverse action (A2) - increase volume connectionID = 2 + - connection does not exits + - inverse action (A3) - unmute connectionID = 1 +*/ + + + +/* + +MainAction -> list of subconnection, each subconnection, a list of actions + each action has a triggering main connection (other) + +//what actions this main connection was causing +MainAction -> a map of subconnections and corresponding action + +*/ diff --git a/PluginControlInterfacePulse/include/ControlSender.h b/PluginControlInterfacePulse/include/ControlSender.h new file mode 100644 index 0000000..94b84af --- /dev/null +++ b/PluginControlInterfacePulse/include/ControlSender.h @@ -0,0 +1,334 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2011-2014, Wind River Systems + * Copyright (C) 2014, GENIVI Alliance + * + * This file is part of Pulse Audio Interface Control Plugin. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License (MPL), v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * + * List of changes: + * + * 08.09.2014, Adrian Scarlat, First version of the code; + * porting from AM ver 1.x; + */ + +#ifndef CONTROLSENDER_H_ +#define CONTROLSENDER_H_ + +#include "ControlConfig.h" +#include "control/IAmControlSend.h" +#include <map> + +using namespace am; + +class ControlSenderPlugin: public IAmControlSend +{ +public: + ControlSenderPlugin(); + + virtual ~ControlSenderPlugin(); + + am_Error_e startupController(IAmControlReceive* controlreceiveinterface); + + void setControllerReady(); + + void setControllerRundown(const int16_t signal); + + am_Error_e hookUserConnectionRequest( + const am_sourceID_t sourceID, + const am_sinkID_t sinkID, + am_mainConnectionID_t& mainConnectionID); + + am_Error_e hookUserDisconnectionRequest(const am_mainConnectionID_t connectionID); + + am_Error_e hookUserSetMainSinkSoundProperty( + const am_sinkID_t sinkID, + const am_MainSoundProperty_s& soundProperty); + + am_Error_e hookUserSetMainSourceSoundProperty( + const am_sourceID_t sourceID, + const am_MainSoundProperty_s& soundProperty); + + am_Error_e hookUserSetSystemProperty(const am_SystemProperty_s& property); + + am_Error_e hookUserVolumeChange( + const am_sinkID_t SinkID, + const am_mainVolume_t newVolume); + + am_Error_e hookUserVolumeStep( + const am_sinkID_t SinkID, + const int16_t increment); + + am_Error_e hookUserSetSinkMuteState( + const am_sinkID_t sinkID, + const am_MuteState_e muteState); + + am_Error_e hookSystemRegisterDomain( + const am_Domain_s& domainData, + am_domainID_t& domainID); + + am_Error_e hookSystemDeregisterDomain(const am_domainID_t domainID); + + void hookSystemDomainRegistrationComplete(const am_domainID_t domainID); + + am_Error_e hookSystemRegisterSink( + const am_Sink_s& sinkData, + am_sinkID_t& sinkID); + + am_Error_e hookSystemDeregisterSink(const am_sinkID_t sinkID); + + am_Error_e hookSystemRegisterSource( + const am_Source_s& sourceData, + am_sourceID_t& sourceID); + + am_Error_e hookSystemDeregisterSource(const am_sourceID_t sourceID); + + am_Error_e hookSystemRegisterGateway( + const am_Gateway_s& gatewayData, + am_gatewayID_t& gatewayID); + + am_Error_e hookSystemDeregisterGateway(const am_gatewayID_t gatewayID); + + am_Error_e hookSystemRegisterCrossfader( + const am_Crossfader_s& crossfaderData, + am_crossfaderID_t& crossfaderID); + + am_Error_e hookSystemDeregisterCrossfader( + const am_crossfaderID_t crossfaderID); + + 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); + + void hookSystemSinkAvailablityStateChange( + const am_sinkID_t sinkID, + const am_Availability_s& availability); + + void hookSystemSourceAvailablityStateChange( + const am_sourceID_t sourceID, + const am_Availability_s& availability); + + void hookSystemDomainStateChange( + const am_domainID_t domainID, + const am_DomainState_e state); + + void hookSystemReceiveEarlyData(const std::vector<am_EarlyData_s>& data); + + void hookSystemSpeedChange(const am_speed_t speed); + + void hookSystemTimingInformationChanged( + const am_mainConnectionID_t mainConnectionID, + const am_timeSync_t time); + + void cbAckConnect( + const am_Handle_s handle, + const am_Error_e errorID); + + void cbAckDisconnect( + const am_Handle_s handle, + const am_Error_e errorID); + + void cbAckCrossFade( + const am_Handle_s handle, + const am_HotSink_e hostsink, + const am_Error_e error); + + void cbAckSetSinkVolumeChange( + const am_Handle_s handle, + const am_volume_t volume, + const am_Error_e error); + + void cbAckSetSourceVolumeChange( + const am_Handle_s handle, + const am_volume_t voulme, + const am_Error_e error); + + void cbAckSetSourceState( + const am_Handle_s handle, + const am_Error_e error); + + void cbAckSetSourceSoundProperty( + const am_Handle_s handle, + const am_Error_e error); + + void cbAckSetSourceSoundProperties( + const am_Handle_s handle, + const am_Error_e error); + + void cbAckSetSinkSoundProperty( + const am_Handle_s handle, + const am_Error_e error); + + void cbAckSetSinkSoundProperties( + const am_Handle_s handle, + const am_Error_e error); + + am_Error_e getConnectionFormatChoice( + const am_sourceID_t sourceID, + const am_sinkID_t sinkID, + const am_Route_s listRoute, + const std::vector<am_CustomConnectionFormat_t> listPossibleConnectionFormats, + std::vector<am_CustomConnectionFormat_t>& listPrioConnectionFormats); + + void getInterfaceVersion(std::string& version) const; + void confirmCommandReady(const am_Error_e error); + void confirmRoutingReady(const am_Error_e error); + void confirmCommandRundown(const am_Error_e error); + void confirmRoutingRundown(const am_Error_e error); + + am_Error_e hookSystemUpdateSink( + const am_sinkID_t sinkID, + const am_sinkClass_t sinkClassID, + const std::vector<am_SoundProperty_s>& listSoundProperties, + const std::vector<am_CustomConnectionFormat_t>& listConnectionFormats, + const std::vector<am_MainSoundProperty_s>& listMainSoundProperties); + + am_Error_e hookSystemUpdateSource( + 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); + + am_Error_e hookSystemUpdateGateway( + const am_gatewayID_t gatewayID, + const std::vector<am_CustomConnectionFormat_t>& listSourceConnectionFormats, + const std::vector<am_CustomConnectionFormat_t>& listSinkConnectionFormats, + const std::vector<bool>& convertionMatrix); + + void cbAckSetVolumes( + const am_Handle_s handle, + const std::vector<am_Volumes_s>& listVolumes, + const am_Error_e error); + + void cbAckSetSinkNotificationConfiguration( + const am_Handle_s handle, + const am_Error_e error); + + void cbAckSetSourceNotificationConfiguration( + const am_Handle_s handle, + const am_Error_e error); + + void hookSinkNotificationDataChanged( + const am_sinkID_t sinkID, + const am_NotificationPayload_s& payload); + + void hookSourceNotificationDataChanged( + const am_sourceID_t sourceID, + const am_NotificationPayload_s& payload); + + am_Error_e hookUserSetMainSinkNotificationConfiguration( + const am_sinkID_t sinkID, + const am_NotificationConfiguration_s& notificationConfiguration); + + am_Error_e hookUserSetMainSourceNotificationConfiguration( + const am_sourceID_t sourceID, + const am_NotificationConfiguration_s& notificationConfiguration); + + void hookSystemNodeStateChanged(const NsmNodeState_e NodeStateId); + + void hookSystemNodeApplicationModeChanged( + const NsmApplicationMode_e ApplicationModeId); + + void hookSystemSessionStateChanged( + const std::string& sessionName, + const NsmSeat_e seatID, + const NsmSessionState_e sessionStateID); + + NsmErrorStatus_e hookSystemLifecycleRequest( + const uint32_t Request, + const uint32_t RequestId); + +private: + bool isStaticRoutingEnabled() {return true;} + + /** + * Load controller configuration file. The name and path of the configuration file + * should be identical to library (except the extensions which is .conf instead of .so) + */ + am_Error_e loadConfig(); + + /** + * Apply some actions on top of main connection specified by (connectionID) + * If interrupt=true, the action like "disconnect" is reversible (e.g. when the main connection + * triggering this action, is destroyed, connectionID will be re-established, otherwise actions like "disconnect" are permanent) + * If inverse = true, action is inversely applied: (e.g. action = MUTE and inverse = true, we apply UNMUTE) + */ + am_Error_e applyActionOnConnection( + am_mainConnectionID_t connectionID, + am_ConnectAction_s &action, + bool interrupt, + bool inverse, + bool force = false); + + am_Error_e applyActionOnSubConnection( + am_mainConnectionID_t connectionID, + am_Connection_s subConnection, + am_ConnectAction_s &action, + bool interrupt, + bool inverse); + + am_Error_e getStaticRoute( + const bool onlyfree, + const am_sourceID_t sourceID, + const am_sinkID_t sinkID, + std::vector<am_Route_s>& returnList); + + am_Error_e getSourceInfo( + const am_sourceID_t sourceID, + am_Source_s &sourceData); + +/* + * TODO: REVIEW DESCRIPTION + * A mapping between connection and controller actions taken during connection. + * To be used to apply inverse actions during disconnection: + * am_mainConnectionID_t - the main connection request triggering the action + * am_connectionID_t - the sub-connection target of the action + * list of am_ConnectAction_s - actions to be applied on this connection + * in this list, only one action is not pending + * and the non pending action has the higher priority + * (e.g. disconnect > mute > decrease volume) + */ + std::map<am_mainConnectionID_t, + std::map<am_mainConnectionID_t, + std::vector<am_ConnectAction_s> > > mConnectionID2Actions; +/* + * A mapping between main connection and and the list of associated sub-connections. + * First element in the list has the same connectionID as the map key. + */ + std::map<am_mainConnectionID_t, + std::vector<am_Connection_s> > mConnectionID2Subconnections; + + IAmControlReceive *mControlReceiveInterface; + std::vector<am_Route_s> mStaticRoutes; + std::vector<am_MixingRule_s> mMixingRules; + +/* + * map of structures registered during initialization/configuration phase; + * DO NOT USE DIRECTLY + */ + std::map<std::string, am_Source_s> mNames2Sources; + std::map<std::string, am_Sink_s> mNames2Sinks; + std::map<std::string, am_SinkClass_s> mNames2SinksClasses; + std::map<std::string, am_SourceClass_s> mNames2SourceClasses; + std::map<std::string, am_Domain_s> mNames2Domains; + std::map<std::string, am_Gateway_s> mNames2Gateways; +}; + +#endif /* CONTROLSENDER_H_ */ |