summaryrefslogtreecommitdiff
path: root/PluginControlInterfacePulse/include/ControlConfig.h
blob: 8648c77b39327708d193c4eba6578daca12bbbd5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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

*/