return true;
}
+static void policy_get_buffer_attr(struct userdata *u,
+ audio_latency_t latency,
+ uint32_t samplerate,
+ audio_sample_format_t format,
+ uint32_t channels,
+ uint32_t *maxlength,
+ uint32_t *tlength,
+ uint32_t *prebuf,
+ uint32_t *minreq,
+ uint32_t *fragsize)
+{
+ assert(u);
+ assert(maxlength);
+ assert(tlength);
+ assert(prebuf);
+ assert(minreq);
+ assert(fragsize);
+
+ pa_log_debug("hal-latency : u->intf.audio_mgr.get_buffer_attr(%p)", u->audio_mgr.intf.get_buffer_attr);
+ if (u->audio_mgr.intf.get_buffer_attr != NULL) {
+ audio_return_t ret = u->audio_mgr.intf.get_buffer_attr(u->audio_mgr.data, latency, samplerate, format, channels, maxlength, tlength, prebuf, minreq, fragsize);
+ if (ret != AUDIO_RET_OK) {
+ pa_log_error("Failed get_buffer_attr() - ret:%d", ret);
+ }
+ }
+
+ return;
+}
#define EXT_VERSION 1
static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
return;
}
+
+static void __add_hal_buffer_attr_by_latency(struct userdata* u, pa_proplist* proplist, pa_sample_spec spec) {
+ assert(proplist);
+
+ int latency = 0;
+ uint32_t maxlength = -1,
+ tlength = -1,
+ prebuf = -1,
+ minreq = -1,
+ fragsize = -1;
+ const char* audio_latency = pa_proplist_gets(proplist, PA_PROP_MEDIA_TIZEN_AUDIO_LATENCY);
+
+ if (audio_latency == NULL) {
+ return;
+ }
+
+ pa_log_info("hal-latency - auido_latency : %s", audio_latency);
+
+ latency = atoi(audio_latency);
+ pa_log_info("hal-latency - policy_get_buffer_attr(latency:%d, rate:%d, format:%d, channels:%d)", latency, spec.rate, spec.format, spec.channels);
+ policy_get_buffer_attr(u, latency, spec.rate, spec.format, spec.channels,
+ &maxlength, &tlength, &prebuf, &minreq, &fragsize);
+
+ pa_log_info("hal-latency - buffer_attr -> (maxlength:%d, tlength:%d, prebuf:%d, minreq:%d, fragsize:%d)", maxlength, tlength, prebuf, minreq, fragsize);
+
+ pa_proplist_setf(proplist, "maxlength", "%d", maxlength);
+ pa_proplist_setf(proplist, "tlength", "%d", tlength);
+ pa_proplist_setf(proplist, "prebuf", "%d", prebuf);
+ pa_proplist_setf(proplist, "minreq", "%d", minreq);
+ pa_proplist_setf(proplist, "fragsize", "%d", fragsize);
+}
+
/* Called when new sink-input is creating */
static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u)
{
__free_audio_info(&audio_info);
}
+ /* get buffer_attr by audio latency */
+ pa_log_info("hal-latency - get buffer attr by audio latency");
+ __add_hal_buffer_attr_by_latency(u, new_data->proplist, new_data->sample_spec);
+
exit:
if (s) {
s_info = pa_strbuf_tostring_free(s);
/* Called when new source-output is creating */
static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
const char *policy = NULL;
+
pa_assert(c);
pa_assert(new_data);
pa_assert(u);
new_data->source= policy_select_proper_source (c, policy);*/
pa_log_debug("[POLICY][%s] set source of source-input to [%s]", __func__, (new_data->source)? new_data->source->name : "null");
+ /* get buffer_attr by audio latency */
+ pa_log_info("hal-latency - get buffer attr by audio latency");
+ __add_hal_buffer_attr_by_latency(u, new_data->proplist, new_data->sample_spec);
+
return PA_HOOK_OK;
}
u->audio_mgr.intf.set_route = dlsym(u->audio_mgr.dl_handle, "audio_set_route");
u->audio_mgr.intf.set_mixer_value_string = dlsym(u->audio_mgr.dl_handle, "audio_set_mixer_value_string");
+ u->audio_mgr.intf.get_buffer_attr = dlsym(u->audio_mgr.dl_handle, "audio_get_buffer_attr");
if (u->audio_mgr.intf.init) {
if (u->audio_mgr.intf.init(&u->audio_mgr.data, (void *)u) != AUDIO_RET_OK) {
pa_log_error("audio_mgr init failed");
AUDIO_GAIN_TYPE_MAX,
} audio_gain_t;
+/* audio format */
+typedef enum audio_sample_format {
+ AUDIO_SAMPLE_U8,
+ AUDIO_SAMPLE_ALAW,
+ AUDIO_SAMPLE_ULAW,
+ AUDIO_SAMPLE_S16LE,
+ AUDIO_SAMPLE_S16BE,
+ AUDIO_SAMPLE_FLOAT32LE,
+ AUDIO_SAMPLE_FLOAT32BE,
+ AUDIO_SAMPLE_S32LE,
+ AUDIO_SAMPLE_S32BE,
+ AUDIO_SAMPLE_S24LE,
+ AUDIO_SAMPLE_S24BE,
+ AUDIO_SAMPLE_S24_32LE,
+ AUDIO_SAMPLE_S24_32BE,
+ AUDIO_SAMPLE_MAX,
+ AUDIO_SAMPLE_INVALID = -1
+} audio_sample_format_t;
+
+/* stream latency */
+typedef enum audio_latency {
+ AUDIO_IN_LATENCY_LOW,
+ AUDIO_IN_LATENCY_MID,
+ AUDIO_IN_LATENCY_HIGH,
+ AUDIO_IN_LATENCY_VOIP,
+ AUDIO_OUT_LATENCY_LOW,
+ AUDIO_OUT_LATENCY_MID,
+ AUDIO_OUT_LATENCY_HIGH,
+ AUDIO_OUT_LATENCY_VOIP,
+ AUDIO_LATENCY_MAX
+} audio_latency_t;
+
typedef struct audio_stream_info {
char *name;
uint32_t samplerate;
audio_return_t (*pcm_avail)(void *pcm_handle);
audio_return_t (*pcm_write)(void *pcm_handle, const void *buffer, uint32_t frames);
audio_return_t (*set_mixer_value_string)(void *userdata, const char* ctl, const char* value);
-
+ audio_return_t (*get_buffer_attr)(void *userdata, audio_latency_t latency, uint32_t samplerate, audio_sample_format_t format, uint32_t channels, uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
} audio_interface_t;
int audio_get_revision (void);
audio_return_t audio_pcm_write(void *pcm_handle, const void *buffer, uint32_t frames);
audio_return_t audio_set_route (void *userdata, uint32_t session, uint32_t subsession, uint32_t device_in, uint32_t device_out, uint32_t route_flag);
+audio_return_t audio_get_buffer_attr(void *userdata, audio_latency_t latency, uint32_t samplerate, audio_sample_format_t format, uint32_t channels, uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
#endif
#define PA_PROP_MEDIA_TIZEN_FADE_RETURN_VOLUME "media.tizen_fade_return_volume"
/** For streams: the policy to ignore the preset sink rather use a sink picked by module-policy. One of the strings "yes", "no" */
#define PA_PROP_MEDIA_POLICY_IGNORE_PRESET_SINK "media.policy.ignore_preset_sink"
+#define PA_PROP_MEDIA_TIZEN_AUDIO_LATENCY "media.tizen_audio_latency"
+/** For streams: logic role of this media. One of the strings "auto", "phone" */
+#define PA_PROP_MEDIA_POLICY "media.policy"
#endif
/** For streams: localized media name, formatted as UTF-8. E.g. "Guns'N'Roses: Civil War".*/
/** For streams: logic role of this media. One of the strings "video", "music", "game", "event", "phone", "animation", "production", "a11y", "test" */
#define PA_PROP_MEDIA_ROLE "media.role"
-/** For streams: logic role of this media. One of the strings "auto", "phone" */
-#define PA_PROP_MEDIA_POLICY "media.policy"
-
/** For streams: the name of a filter that is desired, e.g.\ "echo-cancel" or "equalizer-sink". PulseAudio may choose to not apply the filter if it does not make sense (for example, applying echo-cancellation on a Bluetooth headset probably does not make sense. \since 1.0 */
#define PA_PROP_FILTER_WANT "filter.want"
s->buffer_attr.fragsize = s->buffer_attr.maxlength;
}
+#ifdef __TIZEN__
+static int get_buffer_attr_from_hal(pa_proplist* proplist, pa_buffer_attr* ret_attr) {
+ pa_log_debug("hal-latency - __TIZEN__ : get_buffer_attr_from_hal()");
+ uint32_t maxlength = 0;
+ uint32_t tlength = 0;
+ uint32_t prebuf = 0;
+ uint32_t minreq = 0;
+ uint32_t fragsize = 0;
+
+ pa_assert(ret_attr);
+
+ const char* _propStr = NULL;
+
+ if ((_propStr = pa_proplist_gets(proplist, "maxlength")) == NULL) {
+ pa_log_debug("hal-latency - Failed to get maxlength from HAL");
+ return 0;
+ }
+ maxlength = atoi(_propStr);
+
+ if ((_propStr = pa_proplist_gets(proplist, "tlength")) == NULL) {
+ pa_log_error("hal-latency - Failed to get tlength from HAL");
+ return 0;
+ }
+ tlength = atoi(pa_proplist_gets(proplist, "tlength"));
+
+ if ((_propStr = pa_proplist_gets(proplist, "prebuf")) == NULL) {
+ pa_log_error("hal-latency - Failed to get prebuf from HAL");
+ return 0;
+ }
+ prebuf = atoi(pa_proplist_gets(proplist, "prebuf"));
+
+ if ((_propStr = pa_proplist_gets(proplist, "minreq")) == NULL) {
+ pa_log_error("hal-latency - Failed to get minreq from HAL");
+ return 0;
+ }
+ minreq = atoi(pa_proplist_gets(proplist, "minreq"));
+
+ if ((_propStr = pa_proplist_gets(proplist, "fragsize")) == NULL) {
+ pa_log_error("hal-latency - Failed to get fragsize from HAL");
+ return 0;
+ }
+ fragsize = atoi(pa_proplist_gets(proplist, "fragsize"));
+
+ ret_attr->maxlength = maxlength;
+ ret_attr->tlength = tlength;
+ ret_attr->prebuf = prebuf;
+ ret_attr->minreq = minreq;
+ ret_attr->fragsize = fragsize;
+ pa_log_info("hal-latency - update ret_attr->buffer-attr value -> (maxlength:%d, tlength:%d, prebuf:%d, minreq:%d, fragsize:%d)",
+ ret_attr->maxlength, ret_attr->tlength, ret_attr->prebuf, ret_attr->minreq, ret_attr->fragsize);
+
+ return 1;
+}
+
+#endif
+
/* Called from main context */
static record_stream* record_stream_new(
pa_native_connection *c,
*ret = -pa_source_output_new(&source_output, c->protocol->core, &data);
+#ifdef __TIZEN__
+ /*
+ * TODO:
+ * Updates buffer_attr using HAL that is requested latency from client
+ */
+ {
+ pa_log_info("hal-latency - __TIZEN__ : playback_stream_new()");
+ pa_buffer_attr hal_attr;
+ if (get_buffer_attr_from_hal(source_output->proplist, &hal_attr) == 1) {
+ pa_log_info("hal-latency - __TIZEN__ : Updates buffer_attr");
+ *attr = hal_attr;
+ }
+ }
+#endif
+
pa_source_output_new_data_done(&data);
if (!source_output)
*ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data);
+#ifdef __TIZEN__
+ /*
+ * TODO:
+ * Updates buffer_attr using HAL that is requested latency from client
+ */
+ {
+ pa_log_info("hal-latency - __TIZEN__ : playback_stream_new()");
+ pa_buffer_attr hal_attr;
+ if (get_buffer_attr_from_hal(sink_input->proplist, &hal_attr) == 1) {
+ pa_log_info("hal-latency - __TIZEN__ : Updates buffer_attr");
+ *a = hal_attr;
+ }
+ }
+#endif
+
pa_sink_input_new_data_done(&data);
if (!sink_input)