create implicit audio resources for loopback streams
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / stream-state.c
1 /*
2  * module-murphy-ivi -- PulseAudio module for providing audio routing support
3  * Copyright (c) 2012, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU Lesser General Public License,
7  * version 2.1, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
17  * MA 02110-1301 USA.
18  *
19  */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24
25 #include <pulsecore/pulsecore-config.h>
26 #include <pulsecore/sink-input.h>
27 #include <pulsecore/source-output.h>
28
29 #include "stream-state.h"
30 #include "node.h"
31 #include "loopback.h"
32
33 static void sink_input_block(pa_sink_input *, pa_bool_t);
34
35 pa_bool_t pa_stream_state_start_corked(struct userdata *u,
36                                        pa_sink_input_new_data *data,
37                                        pa_nodeset_resdef *resdef)
38 {
39     if (resdef) {
40         data->flags |= PA_SINK_INPUT_START_CORKED;
41         return TRUE;
42     }
43
44     return FALSE;
45 }
46
47 void pa_stream_state_change(struct userdata *u, mir_node *node, int req)
48 {
49     pa_loopnode *loop;
50     uint32_t idx;
51     pa_sink_input *sinp;
52     pa_source_output *sout;
53     pa_core *core;
54
55     pa_assert(u);
56     pa_assert(node);
57
58     pa_assert_se((core = u->core));
59
60     loop = node->loop;
61
62     pa_assert((!loop && node->implement == mir_stream) ||
63               ( loop && node->implement == mir_device)   );
64     pa_assert(node->direction == mir_input || node->direction == mir_output);
65
66     if (loop) {
67         if (node->direction == mir_input) {
68             sinp = pa_idxset_get_by_index(core->sink_inputs,
69                                           loop->sink_input_index);
70             pa_assert(sinp);
71
72             switch (req) {
73             case PA_STREAM_KILL:
74             case PA_STREAM_BLOCK:
75                 pa_log("mute '%s'", node->amname);
76                 pa_sink_input_set_mute(sinp, TRUE, FALSE);
77                 break;
78                 
79             case PA_STREAM_RUN:
80                 pa_log("unmute '%s'", node->amname);
81                 pa_sink_input_set_mute(sinp, FALSE, FALSE);
82                 break;
83                 
84             default:
85                 pa_assert_not_reached();
86                 break;
87             }
88         }
89         else {
90             pa_log("no enforcement for loopback on '%s'", node->amname);
91             sout = pa_idxset_get_by_index(core->source_outputs,
92                                           loop->source_output_index);
93             pa_assert(sout);
94         }
95     }
96     else {
97         if (node->direction == mir_input) {
98             sinp = pa_idxset_get_by_index(core->sink_inputs, node->paidx);
99             pa_assert(sinp);
100
101             switch (req) {
102             case PA_STREAM_KILL:
103                 pa_log("killing '%s'", node->amname);
104                 sinp->kill(sinp);
105                 break;
106                 
107             case PA_STREAM_BLOCK:
108                 pa_log("blocking '%s'", node->amname);
109                 sink_input_block(sinp, TRUE);
110                 break;
111                 
112             case PA_STREAM_RUN:
113                 pa_log("unblock '%s'", node->amname);
114                 sink_input_block(sinp, FALSE);
115                 break;
116                 
117             default:
118                 pa_assert_not_reached();
119                 break;
120             }
121         }
122         else {
123             pa_log("no enforcement for stream '%s'", node->amname);
124             sout = pa_idxset_get_by_index(core->source_outputs, node->paidx);
125             pa_assert(sout);
126         }
127     }
128 }
129
130
131 static void sink_input_block(pa_sink_input *sinp, pa_bool_t block)
132 {
133     const char *event;
134     pa_proplist *pl;
135
136     pa_assert(sinp);
137
138     pa_sink_input_cork(sinp, block);
139
140     if (sinp->send_event) {
141         if (block)
142             event = PA_STREAM_EVENT_REQUEST_CORK;
143         else
144             event = PA_STREAM_EVENT_REQUEST_UNCORK;
145
146         pl = pa_proplist_new();
147
148         sinp->send_event(sinp, event, pl);
149
150         pa_proplist_free(pl);
151     }
152 }
153
154 /*
155  * Local Variables:
156  * c-basic-offset: 4
157  * indent-tabs-mode: nil
158  * End:
159  *
160  */