mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-06 10:42:22 +00:00
Alsasink is no longer bitrotten anymore, yay!
Original commit message from CVS: Alsasink is no longer bitrotten anymore, yay! Alsasrc untested. Also, fixed a logic error in the main loop regarding proper interpretation of avail_update. This fix came from jack.
This commit is contained in:
parent
d734006e3c
commit
941073b31f
2 changed files with 176 additions and 155 deletions
|
@ -1,7 +1,8 @@
|
||||||
|
/* -*- c-basic-offset: 4 -*- */
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001 CodeFactory AB
|
Copyright (C) 2001 CodeFactory AB
|
||||||
Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
|
Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
|
||||||
Copyright (C) 2001 Andy Wingo <apwingo@eos.ncsu.edu>
|
Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public
|
modify it under the terms of the GNU General Public
|
||||||
|
@ -57,7 +58,7 @@ static GstPad* gst_alsa_request_new_pad (GstElement *element, GstPadTemplate *te
|
||||||
static void gst_alsa_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
static void gst_alsa_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||||
static void gst_alsa_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
static void gst_alsa_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||||
static GstElementStateReturn gst_alsa_change_state(GstElement *element);
|
static GstElementStateReturn gst_alsa_change_state(GstElement *element);
|
||||||
/*static GstPadNegotiateReturn gst_alsa_negotiate(GstPad *pad, GstCaps **caps, gpointer *user_data); */
|
static GstPadConnectReturn gst_alsa_connect(GstPad *pad, GstCaps *caps);
|
||||||
|
|
||||||
static GstCaps* gst_alsa_caps (GstAlsa *this);
|
static GstCaps* gst_alsa_caps (GstAlsa *this);
|
||||||
|
|
||||||
|
@ -87,73 +88,99 @@ enum {
|
||||||
ARG_CHANNELS,
|
ARG_CHANNELS,
|
||||||
ARG_RATE,
|
ARG_RATE,
|
||||||
ARG_PERIODCOUNT,
|
ARG_PERIODCOUNT,
|
||||||
ARG_PERIODFRAMES
|
ARG_PERIODFRAMES,
|
||||||
|
ARG_DEBUG
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GST_TYPE_ALSA_FORMAT (gst_alsa_format_get_type())
|
||||||
|
static GType
|
||||||
|
gst_alsa_format_get_type (void)
|
||||||
|
{
|
||||||
|
static GType type = 0;
|
||||||
|
static GEnumValue *values = NULL;
|
||||||
|
gint i, len = SND_PCM_FORMAT_GSM + 3;
|
||||||
|
|
||||||
|
if (values == NULL) {
|
||||||
|
/* the three: for -1, 0, and the terminating NULL */
|
||||||
|
values = g_new0 (GEnumValue, len);
|
||||||
|
|
||||||
|
for (i=0; i<len-1; i++) {
|
||||||
|
values[i].value = i-1; /* UNKNOWN is -1 */
|
||||||
|
values[i].value_name = g_strdup_printf ("%d", i-1);
|
||||||
|
values[i].value_nick = g_strdup (snd_pcm_format_name ((snd_pcm_format_t)i-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
type = g_enum_register_static ("GstAlsaFormat", values);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
gst_alsa_get_type (void)
|
gst_alsa_get_type (void)
|
||||||
{
|
{
|
||||||
static GType alsa_type = 0;
|
static GType alsa_type = 0;
|
||||||
|
|
||||||
if (!alsa_type) {
|
if (!alsa_type) {
|
||||||
static const GTypeInfo alsa_info = {
|
static const GTypeInfo alsa_info = {
|
||||||
sizeof(GstAlsaClass),
|
sizeof(GstAlsaClass),
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
sizeof(GstAlsa),
|
sizeof(GstAlsa),
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
alsa_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAlsa", &alsa_info, 0);
|
alsa_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAlsa", &alsa_info, 0);
|
||||||
}
|
}
|
||||||
return alsa_type;
|
return alsa_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
gst_alsa_sink_get_type (void)
|
gst_alsa_sink_get_type (void)
|
||||||
{
|
{
|
||||||
static GType alsa_type = 0;
|
static GType alsa_type = 0;
|
||||||
|
|
||||||
if (!alsa_type) {
|
if (!alsa_type) {
|
||||||
static const GTypeInfo alsa_info = {
|
static const GTypeInfo alsa_info = {
|
||||||
sizeof(GstAlsaClass),
|
sizeof(GstAlsaClass),
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
(GClassInitFunc)gst_alsa_class_init,
|
(GClassInitFunc)gst_alsa_class_init,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
sizeof(GstAlsa),
|
sizeof(GstAlsa),
|
||||||
0,
|
0,
|
||||||
(GInstanceInitFunc)gst_alsa_init,
|
(GInstanceInitFunc)gst_alsa_init,
|
||||||
};
|
};
|
||||||
alsa_type = g_type_register_static (GST_TYPE_ALSA, "GstAlsaSink", &alsa_info, 0);
|
alsa_type = g_type_register_static (GST_TYPE_ALSA, "GstAlsaSink", &alsa_info, 0);
|
||||||
}
|
}
|
||||||
return alsa_type;
|
return alsa_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
gst_alsa_src_get_type (void)
|
gst_alsa_src_get_type (void)
|
||||||
{
|
{
|
||||||
static GType alsa_type = 0;
|
static GType alsa_type = 0;
|
||||||
|
|
||||||
if (!alsa_type) {
|
if (!alsa_type) {
|
||||||
static const GTypeInfo alsa_info = {
|
static const GTypeInfo alsa_info = {
|
||||||
sizeof(GstAlsaClass),
|
sizeof(GstAlsaClass),
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
(GClassInitFunc)gst_alsa_class_init,
|
(GClassInitFunc)gst_alsa_class_init,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
sizeof(GstAlsa),
|
sizeof(GstAlsa),
|
||||||
0,
|
0,
|
||||||
(GInstanceInitFunc)gst_alsa_init,
|
(GInstanceInitFunc)gst_alsa_init,
|
||||||
};
|
};
|
||||||
alsa_type = g_type_register_static (GST_TYPE_ALSA, "GstAlsaSrc", &alsa_info, 0);
|
alsa_type = g_type_register_static (GST_TYPE_ALSA, "GstAlsaSrc", &alsa_info, 0);
|
||||||
}
|
}
|
||||||
return alsa_type;
|
return alsa_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPadTemplate*
|
static GstPadTemplate*
|
||||||
|
@ -163,8 +190,8 @@ gst_alsa_src_pad_factory(void)
|
||||||
|
|
||||||
if (!template)
|
if (!template)
|
||||||
template = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_SOMETIMES,
|
template = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_SOMETIMES,
|
||||||
gst_caps_new("src", "audio/raw", NULL),
|
gst_caps_new("src", "audio/raw", NULL),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
@ -176,9 +203,9 @@ gst_alsa_src_request_pad_factory(void)
|
||||||
|
|
||||||
if (!template)
|
if (!template)
|
||||||
template = gst_pad_template_new("src%d", GST_PAD_SRC, GST_PAD_REQUEST,
|
template = gst_pad_template_new("src%d", GST_PAD_SRC, GST_PAD_REQUEST,
|
||||||
gst_caps_new("src", "audio/raw",
|
gst_caps_new("src-request", "audio/raw",
|
||||||
gst_props_new("channels", GST_PROPS_INT(1), NULL)),
|
gst_props_new("channels", GST_PROPS_INT(1), NULL)),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
@ -190,8 +217,8 @@ gst_alsa_sink_pad_factory(void)
|
||||||
|
|
||||||
if (!template)
|
if (!template)
|
||||||
template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_SOMETIMES,
|
template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_SOMETIMES,
|
||||||
gst_caps_new("sink", "audio/raw", NULL),
|
gst_caps_new("sink", "audio/raw", NULL),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
@ -203,9 +230,9 @@ gst_alsa_sink_request_pad_factory(void)
|
||||||
|
|
||||||
if (!template)
|
if (!template)
|
||||||
template = gst_pad_template_new("sink%d", GST_PAD_SINK, GST_PAD_REQUEST,
|
template = gst_pad_template_new("sink%d", GST_PAD_SINK, GST_PAD_REQUEST,
|
||||||
gst_caps_new("sink-request", "audio/raw",
|
gst_caps_new("sink-request", "audio/raw",
|
||||||
gst_props_new("channels", GST_PROPS_INT(1), NULL)),
|
gst_props_new("channels", GST_PROPS_INT(1), NULL)),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
@ -226,29 +253,32 @@ gst_alsa_class_init(GstAlsaClass *klass)
|
||||||
object_class->set_property = gst_alsa_set_property;
|
object_class->set_property = gst_alsa_set_property;
|
||||||
|
|
||||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
|
||||||
g_param_spec_string("device","device","alsa device: please see README for details",
|
g_param_spec_string("device","Device","Alsa device, as defined in an asoundrc",
|
||||||
"default",
|
"default",
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FORMAT,
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FORMAT,
|
||||||
g_param_spec_int("format","format","format",
|
g_param_spec_enum("format","Format","PCM audio format",
|
||||||
0, SND_PCM_FORMAT_LAST, SND_PCM_FORMAT_S16,
|
GST_TYPE_ALSA_FORMAT, -1,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE));
|
||||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNELS,
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNELS,
|
||||||
g_param_spec_int("channels","channels","channels",
|
g_param_spec_int("channels","Channels","Number of channels",
|
||||||
1, 64, 1,
|
1, 64, 2,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_RATE,
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_RATE,
|
||||||
g_param_spec_int("rate","rate","rate",
|
g_param_spec_int("rate","Rate","Sample rate, in Hz",
|
||||||
8000, 192000, 44100,
|
8000, 192000, 44100,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PERIODCOUNT,
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PERIODCOUNT,
|
||||||
g_param_spec_int("period_count","period count","period count",
|
g_param_spec_int("period-count","Period count","Number of hardware buffers to use",
|
||||||
2, 64, 2,
|
2, 64, 2,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PERIODFRAMES,
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PERIODFRAMES,
|
||||||
g_param_spec_int("period_frames","period frames","period frames",
|
g_param_spec_int("period-frames","Period frames","Number of frames (samples on each channel) in one hardware period",
|
||||||
64, 4096, 256,
|
64, 8192, 8192,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEBUG,
|
||||||
|
g_param_spec_boolean("debug","Debug","Set to TRUE to output PCM state info",
|
||||||
|
FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
element_class->change_state = gst_alsa_change_state;
|
element_class->change_state = gst_alsa_change_state;
|
||||||
|
|
||||||
|
@ -261,23 +291,6 @@ gst_alsa_init(GstAlsa *this)
|
||||||
/* init values */
|
/* init values */
|
||||||
this->handle = NULL;
|
this->handle = NULL;
|
||||||
|
|
||||||
/* i tried to trim this down to only the essentials needed for proper
|
|
||||||
* functioning; we'll be setting this values 'in earnest' when caps come */
|
|
||||||
|
|
||||||
this->rate = 44100;
|
|
||||||
this->channels = 2;
|
|
||||||
|
|
||||||
/* i wish i could leave these to defaults, but when caps come and typically
|
|
||||||
* the number of channels doubles, you can't have the default count and size
|
|
||||||
* that alsa gives you from the pre-caps setup apply to the post-caps setup
|
|
||||||
* due to internal hw buffer size restrictions. these values seem to be
|
|
||||||
* pretty common, though, although not pushing latency limits */
|
|
||||||
this->period_count = 2;
|
|
||||||
this->period_frames = 4096;
|
|
||||||
|
|
||||||
this->device = g_strdup("default");
|
|
||||||
|
|
||||||
/* is this right? */
|
|
||||||
GST_FLAG_SET(this, GST_ELEMENT_THREAD_SUGGESTED);
|
GST_FLAG_SET(this, GST_ELEMENT_THREAD_SUGGESTED);
|
||||||
|
|
||||||
if (G_OBJECT_TYPE(this) == GST_TYPE_ALSA_SRC) {
|
if (G_OBJECT_TYPE(this) == GST_TYPE_ALSA_SRC) {
|
||||||
|
@ -293,10 +306,6 @@ gst_alsa_init(GstAlsa *this)
|
||||||
this->process = gst_alsa_sink_process;
|
this->process = gst_alsa_sink_process;
|
||||||
this->format = SND_PCM_FORMAT_UNKNOWN; /* we don't know until caps are
|
this->format = SND_PCM_FORMAT_UNKNOWN; /* we don't know until caps are
|
||||||
* set */
|
* set */
|
||||||
} else {
|
|
||||||
g_print("you cannot instantiate an object of type gstalsa. use alsasink or alsasrc instead.\n");
|
|
||||||
G_BREAKPOINT();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_ALSA_PAD(this->pads)->channel = -1;
|
GST_ALSA_PAD(this->pads)->channel = -1;
|
||||||
|
@ -305,7 +314,7 @@ gst_alsa_init(GstAlsa *this)
|
||||||
|
|
||||||
gst_element_add_pad(GST_ELEMENT(this), GST_ALSA_PAD(this->pads)->pad);
|
gst_element_add_pad(GST_ELEMENT(this), GST_ALSA_PAD(this->pads)->pad);
|
||||||
|
|
||||||
/*gst_pad_set_negotiate_function(GST_ALSA_PAD(this->pads)->pad, gst_alsa_negotiate); */
|
gst_pad_set_connect_function(GST_ALSA_PAD(this->pads)->pad, gst_alsa_connect);
|
||||||
gst_element_set_loop_function(GST_ELEMENT(this), gst_alsa_loop);
|
gst_element_set_loop_function(GST_ELEMENT(this), gst_alsa_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,11 +338,8 @@ gst_alsa_request_new_pad (GstElement *element, GstPadTemplate *templ, const gcha
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
if (sscanf(name, templ->name_template, &channel) != 1) {
|
channel = atoi (name + (strchr (templ->name_template, '%') - templ->name_template));
|
||||||
g_warning("invalid pad name %s (trying to fit with %s)", name,
|
|
||||||
templ->name_template);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
l = this->pads;
|
l = this->pads;
|
||||||
while (l) {
|
while (l) {
|
||||||
if (GST_ALSA_PAD(l)->channel == channel) {
|
if (GST_ALSA_PAD(l)->channel == channel) {
|
||||||
|
@ -352,13 +358,13 @@ gst_alsa_request_new_pad (GstElement *element, GstPadTemplate *templ, const gcha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newname = g_strdup_printf (templ->name_template, channel);
|
newname = g_strdup (name);
|
||||||
|
|
||||||
pad = g_new0(GstAlsaPad, 1);
|
pad = g_new0(GstAlsaPad, 1);
|
||||||
pad->channel = channel;
|
pad->channel = channel;
|
||||||
pad->pad = gst_pad_new_from_template (templ, newname);
|
pad->pad = gst_pad_new_from_template (templ, newname);
|
||||||
gst_element_add_pad (GST_ELEMENT (this), pad->pad);
|
gst_element_add_pad (GST_ELEMENT (this), pad->pad);
|
||||||
/*gst_pad_set_negotiate_function(pad->pad, gst_alsa_negotiate); */
|
gst_pad_set_connect_function(pad->pad, gst_alsa_connect);
|
||||||
|
|
||||||
if (this->data_interleaved && this->pads) {
|
if (this->data_interleaved && this->pads) {
|
||||||
gst_element_remove_pad (GST_ELEMENT (this), GST_ALSA_PAD(this->pads)->pad);
|
gst_element_remove_pad (GST_ELEMENT (this), GST_ALSA_PAD(this->pads)->pad);
|
||||||
|
@ -394,7 +400,7 @@ gst_alsa_set_property(GObject *object, guint prop_id, const GValue *value, GPara
|
||||||
this->device = g_strdup(g_value_get_string (value));
|
this->device = g_strdup(g_value_get_string (value));
|
||||||
break;
|
break;
|
||||||
case ARG_FORMAT:
|
case ARG_FORMAT:
|
||||||
this->format = g_value_get_int (value);
|
this->format = g_value_get_enum (value);
|
||||||
break;
|
break;
|
||||||
case ARG_CHANNELS:
|
case ARG_CHANNELS:
|
||||||
this->channels = g_value_get_int (value);
|
this->channels = g_value_get_int (value);
|
||||||
|
@ -410,6 +416,9 @@ gst_alsa_set_property(GObject *object, guint prop_id, const GValue *value, GPara
|
||||||
this->period_frames = g_value_get_int (value);
|
this->period_frames = g_value_get_int (value);
|
||||||
this->buffer_frames = this->period_count * this->period_frames;
|
this->buffer_frames = this->period_count * this->period_frames;
|
||||||
break;
|
break;
|
||||||
|
case ARG_DEBUG:
|
||||||
|
this->debug = g_value_get_boolean (value);
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
GST_DEBUG(0, "Unknown arg");
|
GST_DEBUG(0, "Unknown arg");
|
||||||
return;
|
return;
|
||||||
|
@ -439,7 +448,7 @@ gst_alsa_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec
|
||||||
g_value_set_string (value, this->device);
|
g_value_set_string (value, this->device);
|
||||||
break;
|
break;
|
||||||
case ARG_FORMAT:
|
case ARG_FORMAT:
|
||||||
g_value_set_int (value, this->format);
|
g_value_set_enum (value, this->format);
|
||||||
break;
|
break;
|
||||||
case ARG_CHANNELS:
|
case ARG_CHANNELS:
|
||||||
g_value_set_int (value, this->channels);
|
g_value_set_int (value, this->channels);
|
||||||
|
@ -453,6 +462,9 @@ gst_alsa_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec
|
||||||
case ARG_PERIODFRAMES:
|
case ARG_PERIODFRAMES:
|
||||||
g_value_set_int (value, this->period_frames);
|
g_value_set_int (value, this->period_frames);
|
||||||
break;
|
break;
|
||||||
|
case ARG_DEBUG:
|
||||||
|
g_value_set_boolean (value, this->debug);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
GST_DEBUG(0, "Unknown arg");
|
GST_DEBUG(0, "Unknown arg");
|
||||||
break;
|
break;
|
||||||
|
@ -506,7 +518,7 @@ gst_alsa_change_state(GstElement *element)
|
||||||
|
|
||||||
return GST_STATE_SUCCESS;
|
return GST_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
/* defined but not used
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_alsa_parse_caps (GstAlsa *this, GstCaps *caps)
|
gst_alsa_parse_caps (GstAlsa *this, GstCaps *caps)
|
||||||
{
|
{
|
||||||
|
@ -515,17 +527,20 @@ gst_alsa_parse_caps (GstAlsa *this, GstCaps *caps)
|
||||||
gint format = -1;
|
gint format = -1;
|
||||||
const gchar* format_name;
|
const gchar* format_name;
|
||||||
|
|
||||||
gst_caps_get_string(caps, "format", &format_name);
|
if (!gst_caps_get_string (caps, "format", &format_name))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (format_name == NULL) {
|
if (format_name == NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else if (strcmp(format_name, "int")==0) {
|
} else if (strcmp(format_name, "int")==0) {
|
||||||
gst_caps_get_int (caps, "width", &width);
|
if (!gst_caps_get (caps,
|
||||||
gst_caps_get_int (caps, "depth", &depth);
|
"width", &width,
|
||||||
|
"depth", &depth,
|
||||||
gst_caps_get_int (caps, "law", &law);
|
"law", &law,
|
||||||
gst_caps_get_int (caps, "endianness", &endianness);
|
"endianness", &endianness,
|
||||||
gst_caps_get_boolean (caps, "signed", &sign);
|
"signed", &sign,
|
||||||
|
NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (law == 0) {
|
if (law == 0) {
|
||||||
if (width == 8) {
|
if (width == 8) {
|
||||||
|
@ -571,13 +586,13 @@ gst_alsa_parse_caps (GstAlsa *this, GstCaps *caps)
|
||||||
format = SND_PCM_FORMAT_U32_BE;
|
format = SND_PCM_FORMAT_U32_BE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (law == 1) { *//* mu law *//*
|
} else if (law == 1) { /* mu law */
|
||||||
if (width == depth && width == 8 && sign == FALSE) {
|
if (width == depth && width == 8 && sign == FALSE) {
|
||||||
format = SND_PCM_FORMAT_MU_LAW;
|
format = SND_PCM_FORMAT_MU_LAW;
|
||||||
} else {
|
} else {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
} else if (law == 2) { *//* a law, ug. *//*
|
} else if (law == 2) { /* a law, ug. */
|
||||||
if (width == depth && width == 8 && sign == FALSE) {
|
if (width == depth && width == 8 && sign == FALSE) {
|
||||||
format = SND_PCM_FORMAT_A_LAW;
|
format = SND_PCM_FORMAT_A_LAW;
|
||||||
}
|
}
|
||||||
|
@ -587,22 +602,25 @@ gst_alsa_parse_caps (GstAlsa *this, GstCaps *caps)
|
||||||
} else if (strcmp(format_name, "float")==0) {
|
} else if (strcmp(format_name, "float")==0) {
|
||||||
const gchar *layout;
|
const gchar *layout;
|
||||||
|
|
||||||
gst_caps_get_string(caps, "layout", &layout);
|
if (!gst_caps_get_string (caps, "layout", &layout))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (strcmp(layout, "gfloat")==0) {
|
if (strcmp(layout, "gfloat")==0) {
|
||||||
format = SND_PCM_FORMAT_FLOAT;
|
format = SND_PCM_FORMAT_FLOAT;
|
||||||
} else {
|
} else {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
*//* if you need float64, chat w/ me on irc.gstreamer.net and i'll tell you what needs to
|
/* you need doubles? jeez... */
|
||||||
* be done. i'm 'wingo'. *//*
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->format = format;
|
this->format = format;
|
||||||
gst_caps_get_int(caps, "rate", &this->rate);
|
if (!gst_caps_get (caps,
|
||||||
gst_caps_get_int(caps, "channels", &channels);
|
"rate", &this->rate,
|
||||||
|
"channels", &channels,
|
||||||
|
NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (this->data_interleaved)
|
if (this->data_interleaved)
|
||||||
this->channels = channels;
|
this->channels = channels;
|
||||||
|
@ -611,7 +629,7 @@ gst_alsa_parse_caps (GstAlsa *this, GstCaps *caps)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
/* caps are so painful sometimes. */
|
/* caps are so painful sometimes. */
|
||||||
static GstCaps*
|
static GstCaps*
|
||||||
gst_alsa_caps (GstAlsa *this)
|
gst_alsa_caps (GstAlsa *this)
|
||||||
|
@ -721,30 +739,23 @@ gst_alsa_caps (GstAlsa *this)
|
||||||
/*
|
/*
|
||||||
* Negotiates the caps, "borrowed" from gstosssink.c
|
* Negotiates the caps, "borrowed" from gstosssink.c
|
||||||
*/
|
*/
|
||||||
#if 0
|
GstPadConnectReturn
|
||||||
GstPadNegotiateReturn
|
gst_alsa_connect(GstPad *pad, GstCaps *caps)
|
||||||
gst_alsa_negotiate(GstPad *pad, GstCaps **caps, gpointer *user_data)
|
|
||||||
{
|
{
|
||||||
GstAlsa *this;
|
GstAlsa *this;
|
||||||
gboolean need_mmap;
|
gboolean need_mmap;
|
||||||
|
|
||||||
g_return_val_if_fail (pad != NULL, GST_PAD_NEGOTIATE_FAIL);
|
g_return_val_if_fail (caps != NULL, GST_PAD_CONNECT_REFUSED);
|
||||||
g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_NEGOTIATE_FAIL);
|
g_return_val_if_fail (pad != NULL, GST_PAD_CONNECT_REFUSED);
|
||||||
|
|
||||||
this = GST_ALSA(gst_pad_get_parent(pad));
|
this = GST_ALSA(gst_pad_get_parent(pad));
|
||||||
|
|
||||||
/* we decide */
|
if (GST_CAPS_IS_FIXED (caps)) {
|
||||||
if (user_data == NULL) {
|
|
||||||
*caps = NULL;
|
|
||||||
return GST_PAD_NEGOTIATE_TRY;
|
|
||||||
}
|
|
||||||
/* have we got caps? */
|
|
||||||
else if (*caps) {
|
|
||||||
if (this->handle == NULL)
|
if (this->handle == NULL)
|
||||||
if (!gst_alsa_open_audio(this))
|
if (!gst_alsa_open_audio(this))
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
|
|
||||||
if (gst_alsa_parse_caps(this, *caps)) {
|
if (gst_alsa_parse_caps(this, caps)) {
|
||||||
need_mmap = this->mmap_open;
|
need_mmap = this->mmap_open;
|
||||||
|
|
||||||
/* sync the params */
|
/* sync the params */
|
||||||
|
@ -757,23 +768,22 @@ gst_alsa_negotiate(GstPad *pad, GstCaps **caps, gpointer *user_data)
|
||||||
/* FIXME send out another caps if nego fails */
|
/* FIXME send out another caps if nego fails */
|
||||||
|
|
||||||
if (!gst_alsa_open_audio(this))
|
if (!gst_alsa_open_audio(this))
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
|
|
||||||
if (!gst_alsa_start_audio(this))
|
if (!gst_alsa_start_audio(this))
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
|
|
||||||
if (need_mmap && !gst_alsa_get_channel_addresses(this))
|
if (need_mmap && !gst_alsa_get_channel_addresses(this))
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
|
|
||||||
return GST_PAD_NEGOTIATE_AGREE;
|
return GST_PAD_CONNECT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
return GST_PAD_CONNECT_DELAYED;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* shamelessly stolen from pbd's audioengine. thanks, paul! */
|
/* shamelessly stolen from pbd's audioengine. thanks, paul! */
|
||||||
static void
|
static void
|
||||||
|
@ -823,7 +833,7 @@ gst_alsa_loop (GstElement *element)
|
||||||
xrun_detected = FALSE;
|
xrun_detected = FALSE;
|
||||||
|
|
||||||
this->avail = snd_pcm_avail_update (this->handle);
|
this->avail = snd_pcm_avail_update (this->handle);
|
||||||
/* g_print ("snd_pcm_avail_update() = %d\n", this->avail); */
|
// g_print ("snd_pcm_avail_update() = %d\n", (int)this->avail);
|
||||||
|
|
||||||
if (this->avail < 0) {
|
if (this->avail < 0) {
|
||||||
if (this->avail == -EPIPE) {
|
if (this->avail == -EPIPE) {
|
||||||
|
@ -835,6 +845,11 @@ gst_alsa_loop (GstElement *element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* round down to nearest period_frames avail */
|
||||||
|
this->avail -= this->avail % this->period_frames;
|
||||||
|
|
||||||
|
// g_print ("snd_pcm_avail_update(), rounded down = %d\n", (int)this->avail);
|
||||||
|
|
||||||
/* pretty sophisticated eh? */
|
/* pretty sophisticated eh? */
|
||||||
if (xrun_detected)
|
if (xrun_detected)
|
||||||
g_warning ("xrun detected");
|
g_warning ("xrun detected");
|
||||||
|
@ -956,13 +971,15 @@ gst_alsa_sink_process (GstAlsa *this, snd_pcm_uframes_t frames)
|
||||||
* underestimate the amount of data we will need by peeking 'frames' only.
|
* underestimate the amount of data we will need by peeking 'frames' only.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
/* FIXME: if 0 < peek_bytes < len, play the peek_bytes */
|
||||||
|
|
||||||
if (!this->sample_bytes) {
|
if (!this->sample_bytes) {
|
||||||
if (!GST_ALSA_PAD(this->pads)->bs)
|
if (!GST_ALSA_PAD(this->pads)->bs)
|
||||||
GST_ALSA_PAD(this->pads)->bs = gst_bytestream_new(GST_ALSA_PAD(this->pads)->pad);
|
GST_ALSA_PAD(this->pads)->bs = gst_bytestream_new(GST_ALSA_PAD(this->pads)->pad);
|
||||||
|
|
||||||
if (gst_bytestream_peek_bytes(GST_ALSA_PAD(this->pads)->bs, &peeked, frames) != frames) {
|
if (gst_bytestream_peek_bytes (GST_ALSA_PAD (this->pads)->bs, &peeked, frames) != frames) {
|
||||||
g_warning("initial pull on pad %s returned NULL", GST_OBJECT_NAME(GST_ALSA_PAD(this->pads)->pad));
|
g_warning("could not make initial pull of %d bytes on pad %s:%s", (int)frames, GST_DEBUG_PAD_NAME(GST_ALSA_PAD(this->pads)->pad));
|
||||||
gst_element_set_state(GST_ELEMENT(this), GST_STATE_PAUSED);
|
gst_element_set_eos (GST_ELEMENT(this));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1156,8 +1173,9 @@ gst_alsa_set_params (GstAlsa *this)
|
||||||
g_warning("could not set sw_params: %s", snd_strerror(ret));
|
g_warning("could not set sw_params: %s", snd_strerror(ret));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_pcm_dump(this->handle, this->out);
|
if (this->debug)
|
||||||
|
snd_pcm_dump(this->handle, this->out);
|
||||||
|
|
||||||
this->access_interleaved = !(snd_pcm_hw_params_get_access (hw_param) ==
|
this->access_interleaved = !(snd_pcm_hw_params_get_access (hw_param) ==
|
||||||
SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
/* -*- c-basic-offset: 4 -*- */
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001 CodeFactory AB
|
Copyright (C) 2001 CodeFactory AB
|
||||||
Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
|
Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
|
||||||
Copyright (C) 2001 Andy Wingo <apwingo@eos.ncsu.edu>
|
Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
|
@ -113,6 +114,8 @@ struct _GstAlsa {
|
||||||
guint buffer_frames;
|
guint buffer_frames;
|
||||||
guint period_count; /* 'number of fragments' in oss-speak */
|
guint period_count; /* 'number of fragments' in oss-speak */
|
||||||
guint period_frames;
|
guint period_frames;
|
||||||
|
|
||||||
|
gboolean debug;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstAlsaClass {
|
struct _GstAlsaClass {
|
||||||
|
|
Loading…
Reference in a new issue