GST_LOG_OBJECT (psink, "creating sample spec");
/* convert the gstreamer sample spec to the pulseaudio format */
- if (!gst_pulse_fill_format_info (spec, &pbuf->format, &pbuf->channels))
+ if (!gst_pulse_fill_format_info (spec, &pbuf->format, NULL, &pbuf->channels))
goto invalid_spec;
pbuf->is_pcm = pa_format_info_is_pcm (pbuf->format);
if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
goto out;
- if (!gst_pulse_fill_format_info (&spec, &format, &channels))
+ if (!gst_pulse_fill_format_info (&spec, &format, NULL, &channels))
goto out;
/* Make sure input is framed (one frame per buffer) and can be payloaded */
pulsesrc->read_buffer = NULL;
pulsesrc->read_buffer_length = 0;
- pa_sample_spec_init (&pulsesrc->sample_spec);
+ pulsesrc->format = NULL;
pulsesrc->operation_success = FALSE;
pulsesrc->paused = TRUE;
gst_structure_free (pulsesrc->properties);
if (pulsesrc->proplist)
pa_proplist_free (pulsesrc->proplist);
+ if (pulsesrc->format)
+ pa_format_info_free (pulsesrc->format);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
GST_DEBUG_OBJECT (pulsesrc, "setting volume to %f", volume);
- gst_pulse_cvolume_from_linear (&v, pulsesrc->sample_spec.channels, volume);
+ gst_pulse_cvolume_from_linear (&v, pulsesrc->channels, volume);
if (!(o = pa_context_set_source_output_volume (pulsesrc->context,
pulsesrc->source_output_idx, &v, NULL, NULL)))
if (negative)
result = 0;
else
- result = (guint) ((t * pulsesrc->sample_spec.rate) / 1000000LL);
+ result = (guint) ((t * pulsesrc->rate) / 1000000LL);
}
return result;
GstAudioRingBufferSpec * rspec)
{
pa_channel_map channel_map;
- const pa_channel_map *m;
+ pa_format_info *formats[1];
GstStructure *s;
gboolean need_channel_layout = FALSE;
GstAudioRingBufferSpec new_spec, *spec = NULL;
g_assert_not_reached ();
}
- if (!gst_pulse_fill_sample_spec (spec, &pulsesrc->sample_spec))
+ if (!gst_pulse_fill_format_info (spec, &pulsesrc->format, &pulsesrc->rate,
+ &pulsesrc->channels))
goto invalid_spec;
+ if (need_channel_layout) {
+ pa_channel_map_init_auto (&channel_map, pulsesrc->channels,
+ PA_CHANNEL_MAP_DEFAULT);
+ }
+
+ pa_format_info_set_channel_map (pulsesrc->format, &channel_map);
+
pa_threaded_mainloop_lock (pulsesrc->mainloop);
if (!pulsesrc->context)
goto bad_context;
name = "Record Stream";
- if (pulsesrc->proplist) {
- if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context,
- name, &pulsesrc->sample_spec,
- (need_channel_layout) ? NULL : &channel_map,
- pulsesrc->proplist)))
- goto create_failed;
-
- } else if (!(pulsesrc->stream = pa_stream_new (pulsesrc->context,
- name, &pulsesrc->sample_spec,
- (need_channel_layout) ? NULL : &channel_map)))
+
+ formats[0] = pulsesrc->format;
+
+ if (!(pulsesrc->stream = pa_stream_new_extended (pulsesrc->context,
+ name, formats, 1, pulsesrc->proplist)))
goto create_failed;
if (caps) {
- m = pa_stream_get_channel_map (pulsesrc->stream);
- gst_pulse_channel_map_to_gst (m, &new_spec);
+ gst_pulse_channel_map_to_gst (&channel_map, &new_spec);
gst_audio_channel_positions_to_valid_order (new_spec.info.position,
new_spec.info.channels);
gst_caps_unref (*caps);
- *caps = gst_audio_info_to_caps (&new_spec.info);
+ *caps = gst_pulse_format_info_to_caps (pulsesrc->format);
GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps);
}
{
GstAudioRingBufferSpec s = *spec;
- const pa_channel_map *m;
+ pa_channel_map m;
+
+ if (gst_pulse_format_info_get_channel_map (pulsesrc->format, &m) < 0) {
+ GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
+ ("Could not get channel map for stream"), (NULL));
+ goto unlock_and_fail;
+ }
- m = pa_stream_get_channel_map (pulsesrc->stream);
- gst_pulse_channel_map_to_gst (m, &s);
+ gst_pulse_channel_map_to_gst (&m, &s);
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
(pulsesrc)->ringbuffer, s.info.position);
}
gboolean
gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f,
- guint * channels)
+ guint * rate, guint * channels)
{
pa_format_info *format;
pa_sample_format_t sf = PA_SAMPLE_INVALID;
goto fail;
*f = format;
- *channels = GST_AUDIO_INFO_CHANNELS (ainfo);
+ if (rate)
+ *rate = GST_AUDIO_INFO_RATE (ainfo);
+ if (channels)
+ *channels = GST_AUDIO_INFO_CHANNELS (ainfo);
return TRUE;
return TRUE;
}
+/* FIXME: switch to PA API when it is available */
+int
+gst_pulse_format_info_get_channel_map (pa_format_info * f, pa_channel_map * map)
+{
+ int r;
+ char *map_str;
+
+ r = pa_format_info_get_prop_string (f, PA_PROP_FORMAT_CHANNEL_MAP, &map_str);
+ if (r < 0)
+ return r;
+
+ map = pa_channel_map_parse (map, map_str);
+ pa_xfree (map_str);
+
+ if (!map)
+ return -PA_ERR_INVALID;
+
+ return 0;
+}
+
GstCaps *
gst_pulse_format_info_to_caps (pa_format_info * format)
{
GstCaps *ret = NULL;
GValue v = { 0, };
pa_sample_spec ss;
+ pa_channel_map map;
+ int channels = 0;
switch (format->encoding) {
case PA_ENCODING_PCM:{
&v))
gst_caps_set_value (ret, "channels", &v);
+ if (pa_format_info_get_prop_int (format, PA_PROP_FORMAT_CHANNELS,
+ &channels) == 0
+ && gst_pulse_format_info_get_channel_map (format, &map) == 0) {
+ guint64 channel_mask;
+ GstAudioRingBufferSpec spec;
+
+ GST_AUDIO_INFO_CHANNELS (&spec.info) = channels;
+
+ if (gst_pulse_channel_map_to_gst (&map, &spec) &&
+ !(GST_AUDIO_INFO_IS_UNPOSITIONED (&spec.info)) &&
+ gst_audio_channel_positions_to_mask (&GST_AUDIO_INFO_POSITION
+ (&spec.info, 0), channels, FALSE, &channel_mask)) {
+ gst_caps_set_simple (ret, "channel-mask", GST_TYPE_BITMASK,
+ channel_mask, NULL);
+ } else {
+ GST_WARNING ("Could not convert channel map to channel mask");
+ }
+ }
+
out:
return ret;
}
gboolean gst_pulse_fill_sample_spec (GstAudioRingBufferSpec * spec,
pa_sample_spec * ss);
gboolean gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec,
- pa_format_info ** f, guint * channels);
+ pa_format_info ** f, guint * rate, guint * channels);
const char * gst_pulse_sample_format_to_caps_format (pa_sample_format_t sf);
gchar *gst_pulse_client_name (void);
pa_proplist *gst_pulse_make_proplist (const GstStructure *properties);
GstStructure *gst_pulse_make_structure (pa_proplist *properties);
+int gst_pulse_format_info_get_channel_map (pa_format_info * format,
+ pa_channel_map *map);
GstCaps * gst_pulse_format_info_to_caps (pa_format_info * format);
GstCaps * gst_pulse_fix_pcm_caps (GstCaps * incaps);