*
* You should have received a copy of the GNU Lesser General Public
* License along with gst-pulse; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA.
*/
#include "config.h"
#endif
+#include <gst/audio/audio.h>
+
#include "pulseutil.h"
-#include <gst/audio/multichannel.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h> /* getpid on UNIX */
# include <process.h> /* getpid on win32 */
#endif
-static const pa_channel_position_t gst_pos_to_pa[GST_AUDIO_CHANNEL_POSITION_NUM]
- = {
- [GST_AUDIO_CHANNEL_POSITION_FRONT_MONO] = PA_CHANNEL_POSITION_MONO,
- [GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT] = PA_CHANNEL_POSITION_FRONT_LEFT,
- [GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT] = PA_CHANNEL_POSITION_FRONT_RIGHT,
- [GST_AUDIO_CHANNEL_POSITION_REAR_CENTER] = PA_CHANNEL_POSITION_REAR_CENTER,
- [GST_AUDIO_CHANNEL_POSITION_REAR_LEFT] = PA_CHANNEL_POSITION_REAR_LEFT,
- [GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT] = PA_CHANNEL_POSITION_REAR_RIGHT,
- [GST_AUDIO_CHANNEL_POSITION_LFE] = PA_CHANNEL_POSITION_LFE,
- [GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER] = PA_CHANNEL_POSITION_FRONT_CENTER,
- [GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] =
- PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
- [GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] =
- PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
- [GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT] = PA_CHANNEL_POSITION_SIDE_LEFT,
- [GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT] = PA_CHANNEL_POSITION_SIDE_RIGHT,
- [GST_AUDIO_CHANNEL_POSITION_TOP_CENTER] = PA_CHANNEL_POSITION_TOP_CENTER,
- [GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT] =
- PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
- [GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT] =
- PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
- [GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER] =
- PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
- [GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT] =
- PA_CHANNEL_POSITION_TOP_REAR_LEFT,
- [GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT] =
- PA_CHANNEL_POSITION_TOP_REAR_RIGHT,
- [GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER] =
- PA_CHANNEL_POSITION_TOP_REAR_CENTER,
- [GST_AUDIO_CHANNEL_POSITION_NONE] = PA_CHANNEL_POSITION_INVALID
+static const struct
+{
+ GstAudioChannelPosition gst_pos;
+ pa_channel_position_t pa_pos;
+} gst_pa_pos_table[] = {
+ {
+ GST_AUDIO_CHANNEL_POSITION_MONO, PA_CHANNEL_POSITION_MONO}, {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_LEFT}, {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_FRONT_RIGHT}, {
+ GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, PA_CHANNEL_POSITION_REAR_CENTER}, {
+ GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_LEFT}, {
+ GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_REAR_RIGHT}, {
+ GST_AUDIO_CHANNEL_POSITION_LFE1, PA_CHANNEL_POSITION_LFE}, {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_FRONT_CENTER}, {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
+ PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
+ PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
+ GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_LEFT}, {
+ GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, PA_CHANNEL_POSITION_SIDE_RIGHT}, {
+ GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, PA_CHANNEL_POSITION_TOP_CENTER}, {
+ GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT,
+ PA_CHANNEL_POSITION_TOP_FRONT_LEFT}, {
+ GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT,
+ PA_CHANNEL_POSITION_TOP_FRONT_RIGHT}, {
+ GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER,
+ PA_CHANNEL_POSITION_TOP_FRONT_CENTER}, {
+ GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, PA_CHANNEL_POSITION_TOP_REAR_LEFT}, {
+ GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT,
+ PA_CHANNEL_POSITION_TOP_REAR_RIGHT}, {
+ GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER,
+ PA_CHANNEL_POSITION_TOP_REAR_CENTER}, {
+ GST_AUDIO_CHANNEL_POSITION_NONE, PA_CHANNEL_POSITION_INVALID}
};
-/* All index are increased by one because PA_CHANNEL_POSITION_INVALID == -1 */
-static const GstAudioChannelPosition
- pa_to_gst_pos[GST_AUDIO_CHANNEL_POSITION_NUM]
- = {
- [PA_CHANNEL_POSITION_MONO + 1] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO,
- [PA_CHANNEL_POSITION_FRONT_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- [PA_CHANNEL_POSITION_FRONT_RIGHT + 1] =
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- [PA_CHANNEL_POSITION_REAR_CENTER + 1] =
- GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
- [PA_CHANNEL_POSITION_REAR_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- [PA_CHANNEL_POSITION_REAR_RIGHT + 1] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
- [PA_CHANNEL_POSITION_LFE + 1] = GST_AUDIO_CHANNEL_POSITION_LFE,
- [PA_CHANNEL_POSITION_FRONT_CENTER + 1] =
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER + 1] =
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
- [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER + 1] =
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
- [PA_CHANNEL_POSITION_SIDE_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
- [PA_CHANNEL_POSITION_SIDE_RIGHT + 1] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
- [PA_CHANNEL_POSITION_INVALID + 1] = GST_AUDIO_CHANNEL_POSITION_NONE,
-};
+static gboolean
+gstaudioformat_to_pasampleformat (GstAudioFormat format,
+ pa_sample_format_t * sf)
+{
+ switch (format) {
+ case GST_AUDIO_FORMAT_U8:
+ *sf = PA_SAMPLE_U8;
+ break;
+ case GST_AUDIO_FORMAT_S16LE:
+ *sf = PA_SAMPLE_S16LE;
+ break;
+ case GST_AUDIO_FORMAT_S16BE:
+ *sf = PA_SAMPLE_S16BE;
+ break;
+ case GST_AUDIO_FORMAT_F32LE:
+ *sf = PA_SAMPLE_FLOAT32LE;
+ break;
+ case GST_AUDIO_FORMAT_F32BE:
+ *sf = PA_SAMPLE_FLOAT32BE;
+ break;
+ case GST_AUDIO_FORMAT_S32LE:
+ *sf = PA_SAMPLE_S32LE;
+ break;
+ case GST_AUDIO_FORMAT_S32BE:
+ *sf = PA_SAMPLE_S32BE;
+ break;
+ case GST_AUDIO_FORMAT_S24LE:
+ *sf = PA_SAMPLE_S24LE;
+ break;
+ case GST_AUDIO_FORMAT_S24BE:
+ *sf = PA_SAMPLE_S24BE;
+ break;
+ case GST_AUDIO_FORMAT_S24_32LE:
+ *sf = PA_SAMPLE_S24_32LE;
+ break;
+ case GST_AUDIO_FORMAT_S24_32BE:
+ *sf = PA_SAMPLE_S24_32BE;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
gboolean
-gst_pulse_fill_sample_spec (GstRingBufferSpec * spec, pa_sample_spec * ss)
+gst_pulse_fill_sample_spec (GstAudioRingBufferSpec * spec, pa_sample_spec * ss)
{
-
- if (spec->type == GST_BUFTYPE_RAW) {
- switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
- case GST_AUDIO_FORMAT_U8:
- ss->format = PA_SAMPLE_U8;
- break;
- case GST_AUDIO_FORMAT_S16LE:
- ss->format = PA_SAMPLE_S16LE;
- break;
- case GST_AUDIO_FORMAT_S16BE:
- ss->format = PA_SAMPLE_S16BE;
- break;
- case GST_AUDIO_FORMAT_F32LE:
- ss->format = PA_SAMPLE_FLOAT32LE;
- break;
- case GST_AUDIO_FORMAT_F32BE:
- ss->format = PA_SAMPLE_FLOAT32BE;
- break;
- case GST_AUDIO_FORMAT_S32LE:
- ss->format = PA_SAMPLE_S32LE;
- break;
- case GST_AUDIO_FORMAT_S32BE:
- ss->format = PA_SAMPLE_S32BE;
- break;
- case GST_AUDIO_FORMAT_S24LE:
- ss->format = PA_SAMPLE_S24LE;
- break;
- case GST_AUDIO_FORMAT_S24BE:
- ss->format = PA_SAMPLE_S24BE;
- break;
- case GST_AUDIO_FORMAT_S24_32LE:
- ss->format = PA_SAMPLE_S24_32LE;
- break;
- case GST_AUDIO_FORMAT_S24_32BE:
- ss->format = PA_SAMPLE_S24_32BE;
- break;
- default:
- return FALSE;
- }
- } else if (spec->type == GST_BUFTYPE_MU_LAW) {
+ if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
+ if (!gstaudioformat_to_pasampleformat (GST_AUDIO_INFO_FORMAT (&spec->info),
+ &ss->format))
+ return FALSE;
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW) {
ss->format = PA_SAMPLE_ULAW;
- } else if (spec->type == GST_BUFTYPE_A_LAW) {
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW) {
ss->format = PA_SAMPLE_ALAW;
} else
return FALSE;
return TRUE;
}
-#ifdef HAVE_PULSE_1_0
gboolean
-gst_pulse_fill_format_info (GstRingBufferSpec * spec, pa_format_info ** f,
+gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f,
guint * channels)
{
pa_format_info *format;
pa_sample_format_t sf = PA_SAMPLE_INVALID;
+ GstAudioInfo *ainfo = &spec->info;
format = pa_format_info_new ();
- if (spec->format == GST_MU_LAW && spec->width == 8) {
+ if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_ULAW;
- } else if (spec->format == GST_A_LAW && spec->width == 8) {
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_ALAW;
- } else if (spec->format == GST_U8 && spec->width == 8) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_U8;
- } else if (spec->format == GST_S16_LE && spec->width == 16) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S16LE;
- } else if (spec->format == GST_S16_BE && spec->width == 16) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S16BE;
- } else if (spec->format == GST_FLOAT32_LE && spec->width == 32) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_FLOAT32LE;
- } else if (spec->format == GST_FLOAT32_BE && spec->width == 32) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_FLOAT32BE;
- } else if (spec->format == GST_S32_LE && spec->width == 32) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S32LE;
- } else if (spec->format == GST_S32_BE && spec->width == 32) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S32BE;
- } else if (spec->format == GST_S24_3LE && spec->width == 24) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S24LE;
- } else if (spec->format == GST_S24_3BE && spec->width == 24) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S24BE;
- } else if (spec->format == GST_S24_LE && spec->width == 32) {
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S24_32LE;
- } else if (spec->format == GST_S24_BE && spec->width == 32) {
- format->encoding = PA_ENCODING_PCM;
- sf = PA_SAMPLE_S24_32BE;
- } else if (spec->format == GST_AC3) {
+ if (!gstaudioformat_to_pasampleformat (GST_AUDIO_INFO_FORMAT (ainfo), &sf))
+ goto fail;
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3) {
format->encoding = PA_ENCODING_AC3_IEC61937;
- } else if (spec->format == GST_EAC3) {
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3) {
format->encoding = PA_ENCODING_EAC3_IEC61937;
- } else if (spec->format == GST_DTS) {
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS) {
format->encoding = PA_ENCODING_DTS_IEC61937;
- } else if (spec->format == GST_MPEG) {
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG) {
format->encoding = PA_ENCODING_MPEG_IEC61937;
+#if PA_CHECK_VERSION(3,99,0)
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG2_AAC) {
+ format->encoding = PA_ENCODING_MPEG2_AAC_IEC61937;
+ } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG4_AAC) {
+ /* HACK. treat MPEG4 AAC as MPEG2 AAC for the moment */
+ format->encoding = PA_ENCODING_MPEG2_AAC_IEC61937;
+#endif
} else {
goto fail;
}
if (format->encoding == PA_ENCODING_PCM) {
pa_format_info_set_sample_format (format, sf);
- pa_format_info_set_channels (format, spec->channels);
+ pa_format_info_set_channels (format, GST_AUDIO_INFO_CHANNELS (ainfo));
}
- pa_format_info_set_rate (format, spec->rate);
+ pa_format_info_set_rate (format, GST_AUDIO_INFO_RATE (ainfo));
if (!pa_format_info_valid (format))
goto fail;
*f = format;
- *channels = spec->channels;
+ *channels = GST_AUDIO_INFO_CHANNELS (ainfo);
return TRUE;
pa_format_info_free (format);
return FALSE;
}
-#endif
+
+const char *
+gst_pulse_sample_format_to_caps_format (pa_sample_format_t sf)
+{
+ switch (sf) {
+ case PA_SAMPLE_U8:
+ return "U8";
+
+ case PA_SAMPLE_S16LE:
+ return "S16LE";
+
+ case PA_SAMPLE_S16BE:
+ return "S16BE";
+
+ case PA_SAMPLE_FLOAT32LE:
+ return "F32LE";
+
+ case PA_SAMPLE_FLOAT32BE:
+ return "F32BE";
+
+ case PA_SAMPLE_S32LE:
+ return "S32LE";
+
+ case PA_SAMPLE_S32BE:
+ return "S32BE";
+
+ case PA_SAMPLE_S24LE:
+ return "S24LE";
+
+ case PA_SAMPLE_S24BE:
+ return "S24BE";
+
+ case PA_SAMPLE_S24_32LE:
+ return "S24_32LE";
+
+ case PA_SAMPLE_S24_32BE:
+ return "S24_32BE";
+
+ default:
+ return NULL;
+ }
+}
/* PATH_MAX is not defined everywhere, e.g. on GNU Hurd */
#ifndef PATH_MAX
pa_channel_map *
gst_pulse_gst_to_channel_map (pa_channel_map * map,
- const GstRingBufferSpec * spec)
+ const GstAudioRingBufferSpec * spec)
{
- int i;
- GstAudioChannelPosition *pos;
+ gint i, j;
+ gint channels;
+ const GstAudioChannelPosition *pos;
pa_channel_map_init (map);
- if (!(pos =
- gst_audio_get_channel_positions (gst_caps_get_structure (spec->caps,
- 0)))) {
- return NULL;
- }
+ channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
+ pos = spec->info.position;
- for (i = 0; i < spec->info.channels; i++) {
- if (pos[i] == GST_AUDIO_CHANNEL_POSITION_NONE) {
- /* no valid mappings for these channels */
- g_free (pos);
+ for (j = 0; j < channels; j++) {
+ for (i = 0; i < G_N_ELEMENTS (gst_pa_pos_table); i++) {
+ if (pos[j] == gst_pa_pos_table[i].gst_pos) {
+ map->map[j] = gst_pa_pos_table[i].pa_pos;
+ break;
+ }
+ }
+ if (i == G_N_ELEMENTS (gst_pa_pos_table))
return NULL;
- } else if (pos[i] < GST_AUDIO_CHANNEL_POSITION_NUM)
- map->map[i] = gst_pos_to_pa[pos[i]];
- else
- map->map[i] = PA_CHANNEL_POSITION_INVALID;
}
- g_free (pos);
+ if (j != spec->info.channels) {
+ return NULL;
+ }
+
map->channels = spec->info.channels;
if (!pa_channel_map_valid (map)) {
return map;
}
-GstRingBufferSpec *
+GstAudioRingBufferSpec *
gst_pulse_channel_map_to_gst (const pa_channel_map * map,
- GstRingBufferSpec * spec)
+ GstAudioRingBufferSpec * spec)
{
- int i;
- GstAudioChannelPosition *pos;
+ gint i, j;
gboolean invalid = FALSE;
gint channels;
+ GstAudioChannelPosition *pos;
channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
g_return_val_if_fail (map->channels == channels, NULL);
- pos = g_new0 (GstAudioChannelPosition, channels + 1);
+ pos = spec->info.position;
- for (i = 0; i < channels; i++) {
- if (map->map[i] == PA_CHANNEL_POSITION_INVALID) {
- invalid = TRUE;
- break;
- } else if ((int) map->map[i] < (int) GST_AUDIO_CHANNEL_POSITION_NUM) {
- pos[i] = pa_to_gst_pos[map->map[i] + 1];
- } else {
- invalid = TRUE;
- break;
+ for (j = 0; j < channels; j++) {
+ for (i = 0; j < channels && i < G_N_ELEMENTS (gst_pa_pos_table); i++) {
+ if (map->map[j] == gst_pa_pos_table[i].pa_pos) {
+ pos[j] = gst_pa_pos_table[i].gst_pos;
+ break;
+ }
}
+ if (i == G_N_ELEMENTS (gst_pa_pos_table))
+ return NULL;
}
- if (!invalid && !gst_audio_check_channel_positions (pos, channels))
+ if (!invalid
+ && !gst_audio_check_valid_channel_positions (pos, channels, FALSE))
invalid = TRUE;
if (invalid) {
for (i = 0; i < channels; i++)
pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+ } else {
+ if (pos[0] != GST_AUDIO_CHANNEL_POSITION_NONE)
+ spec->info.flags &= ~GST_AUDIO_FLAG_UNPOSITIONED;
}
- gst_audio_set_channel_positions (gst_caps_get_structure (spec->caps, 0), pos);
-
- g_free (pos);
-
return spec;
}
case G_TYPE_STRING:
pa_proplist_sets (p, prop_id, g_value_get_string (value));
break;
+#ifdef __TIZEN__
+ case G_TYPE_INT:
+ pa_proplist_setf (p, prop_id, "%d", g_value_get_int (value));
+ break;
+#endif
default:
GST_WARNING ("unmapped property type %s", G_VALUE_TYPE_NAME (value));
break;
gst_structure_foreach (properties, make_proplist_item, proplist);
return proplist;
}
+
+GstStructure *
+gst_pulse_make_structure (pa_proplist * properties)
+{
+ GstStructure *str;
+ void *state = NULL;
+
+ str = gst_structure_new_empty ("pulse-proplist");
+
+ while (TRUE) {
+ const char *key, *val;
+
+ key = pa_proplist_iterate (properties, &state);
+ if (key == NULL)
+ break;
+
+ val = pa_proplist_gets (properties, key);
+
+ gst_structure_set (str, key, G_TYPE_STRING, val, NULL);
+ }
+ return str;
+}
+
+static gboolean
+gst_pulse_format_info_int_prop_to_value (pa_format_info * format,
+ const char *key, GValue * value)
+{
+ GValue v = { 0, };
+ int i;
+ int *a, n;
+ int min, max;
+
+ if (pa_format_info_get_prop_int (format, key, &i) == 0) {
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, i);
+
+ } else if (pa_format_info_get_prop_int_array (format, key, &a, &n) == 0) {
+ g_value_init (value, GST_TYPE_LIST);
+ g_value_init (&v, G_TYPE_INT);
+
+ for (i = 0; i < n; i++) {
+ g_value_set_int (&v, a[i]);
+ gst_value_list_append_value (value, &v);
+ }
+
+ pa_xfree (a);
+
+ } else if (pa_format_info_get_prop_int_range (format, key, &min, &max) == 0) {
+ g_value_init (value, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (value, min, max);
+
+ } else {
+ /* Property not available or is not an int type */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+GstCaps *
+gst_pulse_format_info_to_caps (pa_format_info * format)
+{
+ GstCaps *ret = NULL;
+ GValue v = { 0, };
+ pa_sample_spec ss;
+
+ switch (format->encoding) {
+ case PA_ENCODING_PCM:{
+ char *tmp = NULL;
+
+ pa_format_info_to_sample_spec (format, &ss, NULL);
+
+ if (pa_format_info_get_prop_string (format,
+ PA_PROP_FORMAT_SAMPLE_FORMAT, &tmp)) {
+ /* No specific sample format means any sample format */
+ ret = gst_pulse_fix_pcm_caps (gst_caps_from_string (_PULSE_CAPS_PCM));
+ goto out;
+
+ } else if (ss.format == PA_SAMPLE_ALAW) {
+ ret = gst_caps_from_string (_PULSE_CAPS_ALAW);
+
+ } else if (ss.format == PA_SAMPLE_ULAW) {
+ ret = gst_caps_from_string (_PULSE_CAPS_MULAW);
+
+ } else {
+ /* Linear PCM format */
+ const char *sformat =
+ gst_pulse_sample_format_to_caps_format (ss.format);
+
+ ret = gst_caps_from_string (_PULSE_CAPS_LINEAR);
+
+ if (sformat)
+ gst_caps_set_simple (ret, "format", G_TYPE_STRING, sformat, NULL);
+ }
+
+ pa_xfree (tmp);
+ break;
+ }
+
+ case PA_ENCODING_AC3_IEC61937:
+ ret = gst_caps_from_string (_PULSE_CAPS_AC3);
+ break;
+
+ case PA_ENCODING_EAC3_IEC61937:
+ ret = gst_caps_from_string (_PULSE_CAPS_EAC3);
+ break;
+
+ case PA_ENCODING_DTS_IEC61937:
+ ret = gst_caps_from_string (_PULSE_CAPS_DTS);
+ break;
+
+ case PA_ENCODING_MPEG_IEC61937:
+ ret = gst_caps_from_string (_PULSE_CAPS_MP3);
+ break;
+
+ default:
+ GST_WARNING ("Found a PA format that we don't support yet");
+ goto out;
+ }
+
+ if (gst_pulse_format_info_int_prop_to_value (format, PA_PROP_FORMAT_RATE, &v))
+ gst_caps_set_value (ret, "rate", &v);
+
+ g_value_unset (&v);
+
+ if (gst_pulse_format_info_int_prop_to_value (format, PA_PROP_FORMAT_CHANNELS,
+ &v))
+ gst_caps_set_value (ret, "channels", &v);
+
+out:
+ return ret;
+}
+
+#ifdef __TIZEN__
+#include <gio/gio.h>
+#define PA_BUS_NAME "org.pulseaudio.Server"
+#define PA_STREAM_MANAGER_OBJECT_PATH "/org/pulseaudio/StreamManager"
+#define PA_STREAM_MANAGER_INTERFACE "org.pulseaudio.StreamManager"
+#define PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_RATIO "SetVolumeRatio"
+void
+gst_pulse_set_volume_ratio (uint32_t stream_index, const char *direction, double ratio)
+{
+ GDBusConnection *conn = NULL;
+ GError *err = NULL;
+ GVariant *result = NULL;
+ const gchar *dbus_ret = NULL;
+
+ conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (!conn || err) {
+ GST_ERROR ("g_bus_get_sync() error (%s)", err ? err->message : NULL);
+ if (err)
+ g_error_free (err);
+ return;
+ }
+
+ result = g_dbus_connection_call_sync (conn,
+ PA_BUS_NAME,
+ PA_STREAM_MANAGER_OBJECT_PATH,
+ PA_STREAM_MANAGER_INTERFACE,
+ PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_RATIO,
+ g_variant_new("(sud)", direction, stream_index, ratio),
+ G_VARIANT_TYPE("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ 1000,
+ NULL,
+ &err);
+ if (!result || err) {
+ GST_ERROR ("g_dbus_connection_call_sync() for SET_VOLUME_RATIO error (%s)", err ? err->message : NULL);
+ if (err)
+ g_error_free (err);
+ goto finish;
+ }
+ g_variant_get (result, "(&s)", &dbus_ret);
+ GST_DEBUG ("SET_VOLUME_RATIO returns value(%s) for stream index(%u), ratio(%f)", dbus_ret, stream_index, ratio);
+
+finish:
+ g_variant_unref(result);
+ g_object_unref(conn);
+
+ return;
+}
+#endif
+
+GstCaps *
+gst_pulse_fix_pcm_caps (GstCaps * incaps)
+{
+ GstCaps *outcaps;
+ int i;
+
+ outcaps = gst_caps_make_writable (incaps);
+
+ for (i = 0; i < gst_caps_get_size (outcaps); i++) {
+ GstStructure *st = gst_caps_get_structure (outcaps, i);
+ const gchar *format = gst_structure_get_name (st);
+ const GValue *value;
+ GValue new_value = G_VALUE_INIT;
+ gint min, max, step;
+
+ if (!(g_str_equal (format, "audio/x-raw") ||
+ g_str_equal (format, "audio/x-alaw") ||
+ g_str_equal (format, "audio/x-mulaw")))
+ continue;
+
+ value = gst_structure_get_value (st, "rate");
+
+ if (!GST_VALUE_HOLDS_INT_RANGE (value))
+ continue;
+
+ min = gst_value_get_int_range_min (value);
+ max = gst_value_get_int_range_max (value);
+ step = gst_value_get_int_range_step (value);
+
+ if (min > PA_RATE_MAX)
+ min = PA_RATE_MAX;
+ if (max > PA_RATE_MAX)
+ max = PA_RATE_MAX;
+
+ g_value_init (&new_value, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range_step (&new_value, min, max, step);
+
+ gst_structure_take_value (st, "rate", &new_value);
+ }
+
+ return outcaps;
+}