static GstCaps * gst_openal_src_getcaps (GstBaseSrc * basesrc, GstCaps * filter) { GstOpenalSrc *openalsrc = GST_OPENAL_SRC (basesrc); GstCaps *caps; ALCdevice *device; device = alcOpenDevice (NULL); if (device == NULL) { GstPad *pad = GST_BASE_SRC_PAD (basesrc); GstCaps *tcaps = gst_pad_get_pad_template_caps (pad); GST_ELEMENT_WARNING (openalsrc, RESOURCE, OPEN_WRITE, ("Could not open temporary device."), GST_ALC_ERROR (device)); caps = gst_caps_copy (tcaps); gst_caps_unref (tcaps); } else if (openalsrc->probed_caps) caps = gst_caps_copy (openalsrc->probed_caps); else { ALCcontext *context = alcCreateContext (device, NULL); if (context) { caps = gst_openal_helper_probe_caps (context); alcDestroyContext (context); } else { GST_ELEMENT_WARNING (openalsrc, RESOURCE, FAILED, ("Could not create temporary context."), GST_ALC_ERROR (device)); caps = NULL; } if (caps && !gst_caps_is_empty (caps)) openalsrc->probed_caps = gst_caps_copy (caps); } if (device != NULL) { if (alcCloseDevice (device) == ALC_FALSE) { GST_ELEMENT_WARNING (openalsrc, RESOURCE, CLOSE, ("Could not close temporary device."), GST_ALC_ERROR (device)); } } if (filter) { GstCaps *intersection; intersection = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); return intersection; } else { return caps; } }
static gboolean gst_openal_sink_open (GstAudioSink * audiosink) { GstOpenALSink *sink = GST_OPENAL_SINK (audiosink); if (sink->user_device) { ALCint value = -1; alcGetIntegerv (sink->user_device, ALC_ATTRIBUTES_SIZE, 1, &value); if (value > 0) { if (!sink->user_context || alcGetContextsDevice (sink->user_context) == sink->user_device) sink->default_device = sink->user_device; } } else if (sink->user_context) sink->default_device = alcGetContextsDevice (sink->user_context); else sink->default_device = alcOpenDevice (sink->device_name); if (!sink->default_device) { GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, ("Could not open device."), GST_ALC_ERROR (sink->default_device)); return FALSE; } return TRUE; }
static gboolean gst_openal_src_prepare (GstAudioSrc * audiosrc, GstAudioRingBufferSpec * spec) { GstOpenalSrc *openalsrc = GST_OPENAL_SRC (audiosrc); gst_openal_src_parse_spec (openalsrc, spec); if (openalsrc->format == AL_NONE) { GST_ELEMENT_ERROR (openalsrc, RESOURCE, SETTINGS, (NULL), ("Unable to get type %d, format %d, and %d channels", spec->type, GST_AUDIO_INFO_FORMAT (&spec->info), GST_AUDIO_INFO_CHANNELS (&spec->info))); return FALSE; } openalsrc->device = alcCaptureOpenDevice (openalsrc->default_device, openalsrc->rate, openalsrc->format, openalsrc->buffer_length); if (!openalsrc->device) { GST_ELEMENT_ERROR (openalsrc, RESOURCE, OPEN_READ, ("Could not open device."), GST_ALC_ERROR (openalsrc->device)); return FALSE; } openalsrc->default_device_name = g_strdup (alcGetString (openalsrc->device, ALC_DEVICE_SPECIFIER)); alcCaptureStart (openalsrc->device); return TRUE; }
static gboolean gst_openal_sink_open (GstAudioSink * asink) { GstOpenALSink *openal = GST_OPENAL_SINK (asink); if (openal->custom_dev) { ALCint val = -1; alcGetIntegerv (openal->custom_dev, ALC_ATTRIBUTES_SIZE, 1, &val); if (val > 0) { if (!openal->custom_ctx || alcGetContextsDevice (openal->custom_ctx) == openal->custom_dev) openal->device = openal->custom_dev; } } else if (openal->custom_ctx) openal->device = alcGetContextsDevice (openal->custom_ctx); else openal->device = alcOpenDevice (openal->devname); if (!openal->device) { GST_ELEMENT_ERROR (openal, RESOURCE, OPEN_WRITE, ("Could not open audio device for playback."), GST_ALC_ERROR (openal->device)); return FALSE; } return TRUE; }
static GstCaps * gst_openal_sink_getcaps (GstBaseSink * bsink) { GstOpenALSink *sink = GST_OPENAL_SINK (bsink); GstCaps *caps; if (sink->device == NULL) { GstPad *pad = GST_BASE_SINK_PAD (bsink); caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); } else if (sink->probed_caps) caps = gst_caps_copy (sink->probed_caps); else { if (sink->context) caps = gst_openal_helper_probe_caps (sink->context); else if (sink->custom_ctx) caps = gst_openal_helper_probe_caps (sink->custom_ctx); else { ALCcontext *ctx = alcCreateContext (sink->device, NULL); if (ctx) { caps = gst_openal_helper_probe_caps (ctx); alcDestroyContext (ctx); } else { GST_ELEMENT_WARNING (sink, RESOURCE, FAILED, ("Could not create temporary context."), GST_ALC_ERROR (sink->device)); caps = NULL; } } if (caps && !gst_caps_is_empty (caps)) sink->probed_caps = gst_caps_copy (caps); } return caps; }
static gboolean gst_openal_src_unprepare (GstAudioSrc * audiosrc) { GstOpenalSrc *openalsrc = GST_OPENAL_SRC (audiosrc); if (openalsrc->device) { alcCaptureStop (openalsrc->device); if (alcCaptureCloseDevice (openalsrc->device) == ALC_FALSE) { GST_ELEMENT_ERROR (openalsrc, RESOURCE, CLOSE, ("Could not close device."), GST_ALC_ERROR (openalsrc->device)); return FALSE; } } return TRUE; }
static GstCaps * gst_openal_sink_getcaps (GstBaseSink * basesink, GstCaps * filter) { GstOpenALSink *sink = GST_OPENAL_SINK (basesink); GstCaps *caps; if (sink->default_device == NULL) { GstPad *pad = GST_BASE_SINK_PAD (basesink); GstCaps *tcaps = gst_pad_get_pad_template_caps (pad); caps = gst_caps_copy (tcaps); gst_caps_unref (tcaps); } else if (sink->probed_caps) caps = gst_caps_copy (sink->probed_caps); else { if (sink->default_context) caps = gst_openal_helper_probe_caps (sink->default_context); else if (sink->user_context) caps = gst_openal_helper_probe_caps (sink->user_context); else { ALCcontext *context = alcCreateContext (sink->default_device, NULL); if (context) { caps = gst_openal_helper_probe_caps (context); alcDestroyContext (context); } else { GST_ELEMENT_WARNING (sink, RESOURCE, FAILED, ("Could not create temporary context."), GST_ALC_ERROR (sink->default_device)); caps = NULL; } } if (caps && !gst_caps_is_empty (caps)) sink->probed_caps = gst_caps_copy (caps); } if (filter) { GstCaps *intersection; intersection = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); return intersection; } else { return caps; } }
static gboolean gst_openal_sink_close (GstAudioSink * audiosink) { GstOpenALSink *sink = GST_OPENAL_SINK (audiosink); if (!sink->user_device && !sink->user_context) { if (alcCloseDevice (sink->default_device) == ALC_FALSE) { GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE, ("Could not close device."), GST_ALC_ERROR (sink->default_device)); return FALSE; } } sink->default_device = NULL; if (sink->probed_caps) gst_caps_unref (sink->probed_caps); sink->probed_caps = NULL; return TRUE; }
static gboolean gst_openal_sink_close (GstAudioSink * asink) { GstOpenALSink *openal = GST_OPENAL_SINK (asink); if (!openal->custom_dev && !openal->custom_ctx) { if (alcCloseDevice (openal->device) == ALC_FALSE) { GST_ELEMENT_ERROR (openal, RESOURCE, CLOSE, ("Could not close audio device."), GST_ALC_ERROR (openal->device)); return FALSE; } } openal->device = NULL; if (openal->probed_caps) gst_caps_unref (openal->probed_caps); openal->probed_caps = NULL; return TRUE; }
static gboolean gst_openal_sink_prepare (GstAudioSink * audiosink, GstAudioRingBufferSpec * spec) { GstOpenALSink *sink = GST_OPENAL_SINK (audiosink); ALCcontext *context, *old; if (sink->default_context && !gst_openal_sink_unprepare (audiosink)) return FALSE; if (sink->user_context) context = sink->user_context; else { ALCint attribs[3] = { 0, 0, 0 }; /* Don't try to change the playback frequency of an app's device */ if (!sink->user_device) { attribs[0] = ALC_FREQUENCY; attribs[1] = GST_AUDIO_INFO_RATE (&spec->info); attribs[2] = 0; } context = alcCreateContext (sink->default_device, attribs); if (!context) { GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, ("Unable to prepare device."), GST_ALC_ERROR (sink->default_device)); return FALSE; } } old = pushContext (context); if (sink->user_source) { if (!sink->user_context || !alIsSource (sink->user_source)) { GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL), ("Invalid source specified for context")); goto fail; } sink->default_source = sink->user_source; } else { ALuint source; alGenSources (1, &source); if (checkALError () != AL_NO_ERROR) { GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL), ("Unable to generate source")); goto fail; } sink->default_source = source; } gst_openal_sink_parse_spec (sink, spec); if (sink->format == AL_NONE) { GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL), ("Unable to get type %d, format %d, and %d channels", spec->type, GST_AUDIO_INFO_FORMAT (&spec->info), GST_AUDIO_INFO_CHANNELS (&spec->info))); goto fail; } sink->buffers = g_malloc (sink->buffer_count * sizeof (*sink->buffers)); if (!sink->buffers) { GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, ("Out of memory."), ("Unable to allocate buffers")); goto fail; } alGenBuffers (sink->buffer_count, sink->buffers); if (checkALError () != AL_NO_ERROR) { GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL), ("Unable to generate %d buffers", sink->buffer_count)); goto fail; } sink->buffer_idx = 0; popContext (old, context); sink->default_context = context; return TRUE; fail: if (!sink->user_source && sink->default_source) alDeleteSources (1, &sink->default_source); sink->default_source = 0; g_free (sink->buffers); sink->buffers = NULL; sink->buffer_count = 0; sink->buffer_length = 0; popContext (old, context); if (!sink->user_context) alcDestroyContext (context); return FALSE; }
static gboolean gst_openal_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) { GstOpenALSink *openal = GST_OPENAL_SINK (asink); ALCcontext *ctx, *old; if (openal->context && !gst_openal_sink_unprepare (asink)) return FALSE; if (openal->custom_ctx) ctx = openal->custom_ctx; else { ALCint attribs[3] = { 0, 0, 0 }; /* Don't try to change the playback frequency of an app's device */ if (!openal->custom_dev) { attribs[0] = ALC_FREQUENCY; attribs[1] = spec->rate; attribs[2] = 0; } ctx = alcCreateContext (openal->device, attribs); if (!ctx) { GST_ELEMENT_ERROR (openal, RESOURCE, FAILED, ("Unable to prepare device."), GST_ALC_ERROR (openal->device)); return FALSE; } } old = pushContext (ctx); if (openal->custom_sID) { if (!openal->custom_ctx || !alIsSource (openal->custom_sID)) { GST_ELEMENT_ERROR (openal, RESOURCE, NOT_FOUND, (NULL), ("Invalid source ID specified for context")); goto fail; } openal->sID = openal->custom_sID; } else { ALuint sourceID; alGenSources (1, &sourceID); if (checkALError () != AL_NO_ERROR) { GST_ELEMENT_ERROR (openal, RESOURCE, NO_SPACE_LEFT, (NULL), ("Unable to generate source")); goto fail; } openal->sID = sourceID; } gst_openal_sink_parse_spec (openal, spec); if (openal->format == AL_NONE) { GST_ELEMENT_ERROR (openal, RESOURCE, SETTINGS, (NULL), ("Unable to get type %d, format %d, and %d channels", spec->type, spec->format, spec->channels)); goto fail; } openal->bIDs = g_malloc (openal->bID_count * sizeof (*openal->bIDs)); if (!openal->bIDs) { GST_ELEMENT_ERROR (openal, RESOURCE, FAILED, ("Out of memory."), ("Unable to allocate buffer IDs")); goto fail; } alGenBuffers (openal->bID_count, openal->bIDs); if (checkALError () != AL_NO_ERROR) { GST_ELEMENT_ERROR (openal, RESOURCE, NO_SPACE_LEFT, (NULL), ("Unable to generate %d buffers", openal->bID_count)); goto fail; } openal->bID_idx = 0; popContext (old, ctx); openal->context = ctx; return TRUE; fail: if (!openal->custom_sID && openal->sID) alDeleteSources (1, &openal->sID); openal->sID = 0; g_free (openal->bIDs); openal->bIDs = NULL; openal->bID_count = 0; openal->bID_length = 0; popContext (old, ctx); if (!openal->custom_ctx) alcDestroyContext (ctx); return FALSE; }