pulseaudio changed latency type to string
[platform/upstream/pulseaudio.git] / src / modules / tizen / hal-manager.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2015 Sangchul Lee <sc11.lee@samsung.com>
5
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "hal-manager.h"
27 #include <pulsecore/shared.h>
28
29 /* Audio HAL library */
30 #define LIB_TIZEN_AUDIO "libtizen-audio.so"
31
32 pa_hal_manager* pa_hal_manager_get(pa_core *core, void *user_data) {
33     pa_hal_manager *h;
34
35     pa_assert(core);
36
37     if ((h = pa_shared_get(core, "hal-manager")))
38         return pa_hal_manager_ref(h);
39
40     h = pa_xnew0(pa_hal_manager, 1);
41     PA_REFCNT_INIT(h);
42     h->core = core;
43
44     /* Load library & init HAL manager */
45     h->dl_handle = dlopen(LIB_TIZEN_AUDIO, RTLD_NOW);
46     if (h->dl_handle) {
47         h->intf.init = dlsym(h->dl_handle, "audio_init");
48         h->intf.deinit = dlsym(h->dl_handle, "audio_deinit");
49         h->intf.reset_volume = dlsym(h->dl_handle, "audio_reset_volume");
50         h->intf.get_volume_level_max = dlsym(h->dl_handle, "audio_get_volume_level_max");
51         h->intf.get_volume_level = dlsym(h->dl_handle, "audio_get_volume_level");
52         h->intf.set_volume_level = dlsym(h->dl_handle, "audio_set_volume_level");
53         h->intf.get_volume_value = dlsym(h->dl_handle, "audio_get_volume_value");
54         h->intf.get_volume_mute = dlsym(h->dl_handle, "audio_get_volume_mute");
55         h->intf.set_volume_mute = dlsym(h->dl_handle, "audio_set_volume_mute");
56         h->intf.alsa_pcm_open = dlsym(h->dl_handle, "audio_alsa_pcm_open");
57         h->intf.alsa_pcm_close = dlsym(h->dl_handle, "audio_alsa_pcm_close");
58         h->intf.pcm_open = dlsym(h->dl_handle, "audio_pcm_open");
59         h->intf.pcm_close = dlsym(h->dl_handle, "audio_pcm_close");
60         h->intf.pcm_avail = dlsym(h->dl_handle, "audio_pcm_avail");
61         h->intf.pcm_write = dlsym(h->dl_handle, "audio_pcm_write");
62         h->intf.do_route = dlsym(h->dl_handle, "audio_do_route");
63         h->intf.update_route_option = dlsym(h->dl_handle, "audio_update_route_option");
64         h->intf.update_stream_connection_info  = dlsym(h->dl_handle, "audio_update_stream_connection_info");
65         h->intf.get_buffer_attr = dlsym(h->dl_handle, "audio_get_buffer_attr");
66         if (h->intf.init) {
67             /* TODO : no need to pass platform_data as second param. need to fix hal. */
68             if (h->intf.init(&h->data, user_data) != AUDIO_RET_OK) {
69                 pa_log_error("hal_manager init failed");
70             }
71         }
72 #if 1 /* remove comment after enable NEW_HAL */
73         pa_shared_set(core, "tizen-audio-data", h->data);
74         pa_shared_set(core, "tizen-audio-interface", &h->intf);
75 #endif
76
77      } else {
78          pa_log_error("open hal_manager failed :%s", dlerror());
79          return NULL;
80      }
81
82     pa_shared_set(core, "hal-manager", h);
83
84     return h;
85 }
86
87 pa_hal_manager* pa_hal_manager_ref(pa_hal_manager *h) {
88     pa_assert(h);
89     pa_assert(PA_REFCNT_VALUE(h) > 0);
90
91     PA_REFCNT_INC(h);
92
93     return h;
94 }
95
96 void pa_hal_manager_unref(pa_hal_manager *h) {
97     pa_assert(h);
98     pa_assert(PA_REFCNT_VALUE(h) > 0);
99
100     if (PA_REFCNT_DEC(h) > 0)
101         return;
102
103     /* Deinit HAL manager & unload library */
104     if (h->intf.deinit) {
105         if (h->intf.deinit(&h->data) != AUDIO_RET_OK) {
106             pa_log_error("hal_manager deinit failed");
107         }
108     }
109     if (h->dl_handle) {
110         dlclose(h->dl_handle);
111     }
112
113     if (h->core)
114         pa_shared_remove(h->core, "hal-manager");
115
116     pa_xfree(h);
117 }
118
119 int32_t pa_hal_manager_get_buffer_attribute(pa_hal_manager *h, io_direction_t direction, const char *latency, void *new_data, uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize) {
120     int32_t ret = 0;
121     audio_return_t hal_ret = AUDIO_RET_OK;
122     pa_sample_spec *sample_spec = NULL;
123
124     pa_assert(h);
125     pa_assert(new_data);
126
127     sample_spec = (direction==DIRECTION_OUT)?(&((pa_sink_input_new_data*)new_data)->sample_spec):(&((pa_source_output_new_data*)new_data)->sample_spec);
128     pa_log_info("latency:%s, rate:%u, format:%d, channels:%u", latency, sample_spec->rate, sample_spec->format, sample_spec->channels);
129
130     if (AUDIO_IS_ERROR(hal_ret = h->intf.get_buffer_attr(h->data, direction, latency, sample_spec->rate, sample_spec->format, sample_spec->channels, maxlength, tlength, prebuf, minreq, fragsize))) {
131         pa_log_error("get_buffer_attr returns error:0x%x", hal_ret);
132         ret = -1;
133     } else
134         pa_log_info("maxlength:%d, tlength:%d, prebuf:%d, minreq:%d, fragsize:%d", *maxlength, *tlength, *prebuf, *minreq, *fragsize);
135
136     return ret;
137 }
138
139 int32_t pa_hal_manager_reset_volume (pa_hal_manager *h) {
140     int32_t ret = 0;
141     audio_return_t hal_ret = AUDIO_RET_OK;
142
143     pa_assert(h);
144
145     if (AUDIO_IS_ERROR(hal_ret = h->intf.reset_volume(h->data))) {
146         pa_log_error("reset volume returns error:0x%x", hal_ret);
147         ret = -1;
148     }
149     return ret;
150 }
151
152 int32_t pa_hal_manager_get_volume_level_max (pa_hal_manager *h, const char *volume_type, io_direction_t direction, uint32_t *level) {
153     int32_t ret = 0;
154     audio_return_t hal_ret = AUDIO_RET_OK;
155     audio_volume_info_t info = {NULL, NULL, 0};
156
157     pa_assert(h);
158     pa_assert(volume_type);
159     pa_assert(level);
160
161     info.type = volume_type;
162     info.direction = direction;
163
164     if (AUDIO_IS_ERROR((hal_ret = h->intf.get_volume_level_max(h->data, &info, level)))) {
165         pa_log_error("get_volume_level_max returns error:0x%x", hal_ret);
166         ret = -1;
167     }
168     return ret;
169 }
170
171 int32_t pa_hal_manager_get_volume_level (pa_hal_manager *h, const char *volume_type, io_direction_t direction, uint32_t *level) {
172     int32_t ret = 0;
173     audio_return_t hal_ret = AUDIO_RET_OK;
174     audio_volume_info_t info = {NULL, NULL, 0};
175
176     pa_assert(h);
177     pa_assert(volume_type);
178     pa_assert(level);
179
180     info.type = volume_type;
181     info.direction = direction;
182
183     if (AUDIO_IS_ERROR((hal_ret = h->intf.get_volume_level(h->data, &info, level)))) {
184         pa_log_error("get_volume_level returns error:0x%x", hal_ret);
185         ret = -1;
186     }
187     return ret;
188 }
189
190 int32_t pa_hal_manager_set_volume_level (pa_hal_manager *h, const char *volume_type, io_direction_t direction, uint32_t level) {
191     int32_t ret = 0;
192     audio_return_t hal_ret = AUDIO_RET_OK;
193     audio_volume_info_t info = {NULL, NULL, 0};
194
195     pa_assert(h);
196     pa_assert(volume_type);
197
198     info.type = volume_type;
199     info.direction = direction;
200
201     if (AUDIO_IS_ERROR((hal_ret = h->intf.set_volume_level(h->data, &info, level)))) {
202         pa_log_error("set_volume_level returns error:0x%x", hal_ret);
203         ret = -1;
204     }
205
206     return ret;
207 }
208
209 int32_t pa_hal_manager_get_volume_value (pa_hal_manager *h, const char *volume_type, const char *gain_type, io_direction_t direction, uint32_t level, double *value) {
210     int32_t ret = 0;
211     audio_return_t hal_ret = AUDIO_RET_OK;
212     audio_volume_info_t info = {NULL, NULL, 0};
213
214     pa_assert(h);
215     pa_assert(volume_type);
216     pa_assert(value);
217
218     info.type = volume_type;
219     info.gain = gain_type;
220     info.direction = direction;
221
222     if (AUDIO_IS_ERROR((hal_ret = h->intf.get_volume_value(h->data, &info, level, value)))) {
223         pa_log_error("get_volume_value returns error:0x%x", hal_ret);
224         ret = -1;
225     }
226
227     return ret;
228 }
229
230 int32_t pa_hal_manager_get_mute (pa_hal_manager *h, const char *volume_type, io_direction_t direction, uint32_t *mute) {
231     int32_t ret = 0;
232     audio_return_t hal_ret = AUDIO_RET_OK;
233     audio_volume_info_t info = {NULL, NULL, 0};
234
235     pa_assert(h);
236     pa_assert(volume_type);
237     pa_assert(mute);
238
239     info.type = volume_type;
240     info.direction = direction;
241
242     if (AUDIO_IS_ERROR(hal_ret = h->intf.get_volume_mute(h->data, &info, mute))) {
243         pa_log_error("get_mute returns error:0x%x", hal_ret);
244         ret = -1;
245     }
246     return ret;
247 }
248
249 int32_t pa_hal_manager_set_mute (pa_hal_manager *h, const char *volume_type, io_direction_t direction, uint32_t mute) {
250     int32_t ret = 0;
251     audio_return_t hal_ret = AUDIO_RET_OK;
252     audio_volume_info_t info = {NULL, NULL, 0};
253
254     pa_assert(h);
255     pa_assert(volume_type);
256
257     info.type = volume_type;
258     info.direction = direction;
259
260     if (AUDIO_IS_ERROR(hal_ret = h->intf.set_volume_mute(h->data, &info, mute))) {
261         pa_log_error("set_mute returns error:0x%x", hal_ret);
262         ret = -1;
263     }
264     return ret;
265 }
266
267 int32_t pa_hal_manager_do_route (pa_hal_manager *h, hal_route_info *info) {
268     int32_t ret = 0;
269     audio_return_t hal_ret = AUDIO_RET_OK;
270
271     pa_assert(h);
272     pa_assert(info);
273
274     if (AUDIO_IS_ERROR(hal_ret = h->intf.do_route(h->data, (audio_route_info_t*)info))) {
275         pa_log_error("do_route returns error:0x%x", hal_ret);
276         ret = -1;
277     }
278     return ret;
279 }
280
281 int32_t pa_hal_manager_update_route_option (pa_hal_manager *h, hal_route_option *option) {
282     int32_t ret = 0;
283     audio_return_t hal_ret = AUDIO_RET_OK;
284
285     pa_assert(h);
286     pa_assert(option);
287
288     if (AUDIO_IS_ERROR(hal_ret = h->intf.update_route_option(h->data, (audio_route_option_t*)option))) {
289         pa_log_error("update_route_option returns error:0x%x", hal_ret);
290         ret = -1;
291     }
292     return ret;
293 }
294
295 int32_t pa_hal_manager_update_stream_connection_info (pa_hal_manager *h, hal_stream_connection_info *info) {
296     int32_t ret = 0;
297     audio_return_t hal_ret = AUDIO_RET_OK;
298     audio_stream_info_t hal_info;
299
300     pa_assert(h);
301     pa_assert(info);
302
303     hal_info.role = info->role;
304     hal_info.direction = info->direction;
305     hal_info.idx = info->idx;
306
307     if (AUDIO_IS_ERROR(hal_ret = h->intf.update_stream_connection_info(h->data, &hal_info, (uint32_t)info->is_connected))) {
308         pa_log_error("update_stream_connection_info returns error:0x%x", hal_ret);
309         ret = -1;
310     }
311     return ret;
312 }