1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <cutils/log.h>
7 #include <semaphore.h>
8 #include "cras_expr.h"
9 #include "cras_dsp_ini.h"
10 #include "cras_dsp_pipeline.h"
11 #include "dsp_util.h"
12 #include "utlist.h"
13 
14 #define LOG_TAG "audio_cras_dsp"
15 
16 /* We have a dsp_context for each pipeline. The context records the
17  * parameters used to create a pipeline, so the pipeline can be
18  * (re-)loaded later. The pipeline is (re-)loaded in the following
19  * cases:
20  *
21  * (1) The client asks to (re-)load it with cras_load_pipeline().
22  * (2) The client asks to reload the ini with cras_reload_ini().
23  *
24  */
25 struct cras_dsp_context {
26 	struct pipeline *pipeline;
27 
28 	struct cras_expr_env env;
29 	int sample_rate;
30 	const char *purpose;
31 	struct cras_dsp_context *prev, *next;
32 };
33 
34 static const char *ini_filename;
35 static struct ini *ini;
36 static struct cras_dsp_context *context_list;
37 
initialize_environment(struct cras_expr_env * env)38 static void initialize_environment(struct cras_expr_env *env)
39 {
40 	cras_expr_env_install_builtins(env);
41 	cras_expr_env_set_variable_boolean(env, "disable_eq", 0);
42 	cras_expr_env_set_variable_boolean(env, "disable_drc", 0);
43 	cras_expr_env_set_variable_string(env, "dsp_name", "");
44 }
45 
prepare_pipeline(struct cras_dsp_context * ctx)46 static struct pipeline *prepare_pipeline(struct cras_dsp_context *ctx)
47 {
48 	struct pipeline *pipeline;
49 	const char *purpose = ctx->purpose;
50 
51 	if (!ini)
52 		return NULL;
53 
54 	pipeline = cras_dsp_pipeline_create(ini, &ctx->env, purpose);
55 
56 	if (pipeline) {
57 		ALOGI("pipeline created");
58 	} else {
59 		ALOGI("cannot create pipeline");
60 		goto bail;
61 	}
62 
63 	if (cras_dsp_pipeline_load(pipeline) != 0) {
64 		ALOGE("cannot load pipeline");
65 		goto bail;
66 	}
67 
68 	if (cras_dsp_pipeline_instantiate(pipeline, ctx->sample_rate) != 0) {
69 		ALOGE("cannot instantiate pipeline");
70 		goto bail;
71 	}
72 
73 	if (cras_dsp_pipeline_get_sample_rate(pipeline) != ctx->sample_rate) {
74 		ALOGE("pipeline sample rate mismatch (%d vs %d)",
75 		       cras_dsp_pipeline_get_sample_rate(pipeline),
76 		       ctx->sample_rate);
77 		goto bail;
78 	}
79 
80 	return pipeline;
81 
82 bail:
83 	if (pipeline)
84 		cras_dsp_pipeline_free(pipeline);
85 	return NULL;
86 }
87 
88 /* Exported functions */
cras_dsp_set_variable(struct cras_dsp_context * ctx,const char * key,const char * value)89 void cras_dsp_set_variable(struct cras_dsp_context *ctx, const char *key,
90 			     const char *value)
91 {
92 	cras_expr_env_set_variable_string(&ctx->env, key, value);
93 }
94 
cras_dsp_load_pipeline(struct cras_dsp_context * ctx)95 void cras_dsp_load_pipeline(struct cras_dsp_context *ctx)
96 {
97 	struct pipeline *pipeline, *old_pipeline;
98 
99 	pipeline = prepare_pipeline(ctx);
100 
101 	old_pipeline = ctx->pipeline;
102 	ctx->pipeline = pipeline;
103 
104 	if (old_pipeline)
105 		cras_dsp_pipeline_free(old_pipeline);
106 }
107 
cras_dsp_reload_ini()108 void cras_dsp_reload_ini()
109 {
110 	struct ini *old_ini = ini;
111 	struct cras_dsp_context *ctx;
112 
113 	ini = cras_dsp_ini_create(ini_filename);
114 	if (!ini)
115 		ALOGE("cannot create dsp ini");
116 
117 	DL_FOREACH(context_list, ctx) {
118 		cras_dsp_load_pipeline(ctx);
119 	}
120 
121 	if (old_ini)
122 		cras_dsp_ini_free(old_ini);
123 }
124 
cras_dsp_init(const char * filename)125 void cras_dsp_init(const char *filename)
126 {
127 	dsp_enable_flush_denormal_to_zero();
128 	ini_filename = strdup(filename);
129 	cras_dsp_reload_ini();
130 }
131 
cras_dsp_stop()132 void cras_dsp_stop()
133 {
134 	free((char *)ini_filename);
135 	if (ini) {
136 		cras_dsp_ini_free(ini);
137 		ini = NULL;
138 	}
139 }
140 
cras_dsp_context_new(int sample_rate,const char * purpose)141 struct cras_dsp_context *cras_dsp_context_new(int sample_rate,
142 					      const char *purpose)
143 {
144 	struct cras_dsp_context *ctx = calloc(1, sizeof(*ctx));
145 
146 	initialize_environment(&ctx->env);
147 	ctx->sample_rate = sample_rate;
148 	ctx->purpose = strdup(purpose);
149 
150 	DL_APPEND(context_list, ctx);
151 	return ctx;
152 }
153 
cras_dsp_context_free(struct cras_dsp_context * ctx)154 void cras_dsp_context_free(struct cras_dsp_context *ctx)
155 {
156 	DL_DELETE(context_list, ctx);
157 
158 	if (ctx->pipeline) {
159 		cras_dsp_pipeline_free(ctx->pipeline);
160 		ctx->pipeline = NULL;
161 	}
162 	cras_expr_env_free(&ctx->env);
163 	free((char *)ctx->purpose);
164 	free(ctx);
165 }
166 
cras_dsp_get_pipeline(struct cras_dsp_context * ctx)167 struct pipeline *cras_dsp_get_pipeline(struct cras_dsp_context *ctx)
168 {
169 	return ctx->pipeline;
170 }
171 
cras_dsp_put_pipeline(struct cras_dsp_context * ctx)172 void cras_dsp_put_pipeline(struct cras_dsp_context *ctx)
173 {
174 }
175 
cras_dsp_num_output_channels(const struct cras_dsp_context * ctx)176 unsigned int cras_dsp_num_output_channels(const struct cras_dsp_context *ctx)
177 {
178 	return cras_dsp_pipeline_get_num_output_channels(ctx->pipeline);
179 }
180 
cras_dsp_num_input_channels(const struct cras_dsp_context * ctx)181 unsigned int cras_dsp_num_input_channels(const struct cras_dsp_context *ctx)
182 {
183 	return cras_dsp_pipeline_get_num_input_channels(ctx->pipeline);
184 }
185 
cras_dsp_sync()186 void cras_dsp_sync()
187 {
188 }
189