diff options
author | Lennart Poettering <lennart@poettering.net> | 2010-02-20 00:47:45 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2010-02-20 00:47:45 +0100 |
commit | d22b71af47b44c1c1d84195743c34b589e6ab19c (patch) | |
tree | efb8dc22a6c0f5712b029dcc1a6b8af11d42babd /src/gstreamer.c | |
parent | a558bbefae4e0a9f4d2b9aa539b94ae0344f6aed (diff) |
src: reindent for 8ch indenting
I am slowly moving all my projects to kernel-inspired 8ch indenting.
This will break patches that haven't been merged yet, which I am aware
of, but OTOH in times of git's --ignore-space-change shouldn't be too
problematic.
Yes, I am aware that reindenting like this sucks, but I cannot stand 4ch
indenting anymore. Sorry.
Diffstat (limited to 'src/gstreamer.c')
-rw-r--r-- | src/gstreamer.c | 819 |
1 files changed, 410 insertions, 409 deletions
diff --git a/src/gstreamer.c b/src/gstreamer.c index 54919ea..3496e6b 100644 --- a/src/gstreamer.c +++ b/src/gstreamer.c @@ -1,23 +1,25 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + /*** - This file is part of libcanberra. + This file is part of libcanberra. - Copyright 2008 Nokia Corporation and/or its subsidiary(-ies). + Copyright 2008 Nokia Corporation and/or its subsidiary(-ies). - Author: Marc-Andre Lureau <marc-andre.lureau@nokia.com> + Author: Marc-Andre Lureau <marc-andre.lureau@nokia.com> - libcanberra is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation, either version 2.1 of the - License, or (at your option) any later version. + libcanberra is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 2.1 of the + License, or (at your option) any later version. - libcanberra is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + libcanberra is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with libcanberra. If not, see - <http://www.gnu.org/licenses/>. + You should have received a copy of the GNU Lesser General Public + License along with libcanberra. If not, see + <http://www.gnu.org/licenses/>. ***/ #ifdef HAVE_CONFIG_H @@ -44,28 +46,28 @@ #include "malloc.h" struct outstanding { - CA_LLIST_FIELDS(struct outstanding); - ca_bool_t dead; - uint32_t id; - int err; - ca_finish_callback_t callback; - void *userdata; - GstElement *pipeline; - struct ca_context *context; + CA_LLIST_FIELDS(struct outstanding); + ca_bool_t dead; + uint32_t id; + int err; + ca_finish_callback_t callback; + void *userdata; + GstElement *pipeline; + struct ca_context *context; }; struct private { - ca_theme_data *theme; - ca_bool_t signal_semaphore; - sem_t semaphore; + ca_theme_data *theme; + ca_bool_t signal_semaphore; + sem_t semaphore; - GstBus *mgr_bus; + GstBus *mgr_bus; - /* Everything below protected by the outstanding_mutex */ - ca_mutex *outstanding_mutex; - ca_bool_t mgr_thread_running; - ca_bool_t semaphore_allocated; - CA_LLIST_HEAD(struct outstanding, outstanding); + /* Everything below protected by the outstanding_mutex */ + ca_mutex *outstanding_mutex; + ca_bool_t mgr_thread_running; + ca_bool_t semaphore_allocated; + CA_LLIST_HEAD(struct outstanding, outstanding); }; #define PRIVATE(c) ((struct private *) ((c)->private)) @@ -75,512 +77,511 @@ static void send_eos_msg(struct outstanding *out, int err); static void send_mgr_exit_msg (struct private *p); static void outstanding_free(struct outstanding *o) { - GstBus *bus; + GstBus *bus; - ca_assert(o); + ca_assert(o); - if (o->pipeline) { - bus = gst_pipeline_get_bus(GST_PIPELINE (o->pipeline)); - if (bus != NULL) { - gst_bus_set_sync_handler(bus, NULL, NULL); - gst_object_unref(bus); - } + if (o->pipeline) { + bus = gst_pipeline_get_bus(GST_PIPELINE (o->pipeline)); + if (bus != NULL) { + gst_bus_set_sync_handler(bus, NULL, NULL); + gst_object_unref(bus); + } - gst_object_unref(GST_OBJECT(o->pipeline)); - } + gst_object_unref(GST_OBJECT(o->pipeline)); + } - ca_free(o); + ca_free(o); } int driver_open(ca_context *c) { - GError *error = NULL; - struct private *p; - pthread_t thread; - - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(!PRIVATE(c), CA_ERROR_INVALID); - ca_return_val_if_fail(!c->driver || ca_streq(c->driver, "gstreamer"), CA_ERROR_NODRIVER); - - gst_init_check(NULL, NULL, &error); - if (error != NULL) { - g_warning("gst_init: %s ", error->message); - g_error_free(error); - return CA_ERROR_INVALID; - } - - if (!(p = ca_new0(struct private, 1))) - return CA_ERROR_OOM; - c->private = p; - - if (!(p->outstanding_mutex = ca_mutex_new())) { - driver_destroy(c); - return CA_ERROR_OOM; - } - - if (sem_init(&p->semaphore, 0, 0) < 0) { - driver_destroy(c); - return CA_ERROR_OOM; - } - p->semaphore_allocated = TRUE; - - p->mgr_bus = gst_bus_new(); - if (p->mgr_bus == NULL) { - driver_destroy(c); - return CA_ERROR_OOM; - } - gst_bus_set_flushing(p->mgr_bus, FALSE); - - /* Give a reference to the bus to the mgr thread */ - if (pthread_create(&thread, NULL, thread_func, p) < 0) { - driver_destroy(c); - return CA_ERROR_OOM; - } - p->mgr_thread_running = TRUE; - - return CA_SUCCESS; -} + GError *error = NULL; + struct private *p; + pthread_t thread; + + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(!PRIVATE(c), CA_ERROR_INVALID); + ca_return_val_if_fail(!c->driver || ca_streq(c->driver, "gstreamer"), CA_ERROR_NODRIVER); + + gst_init_check(NULL, NULL, &error); + if (error != NULL) { + g_warning("gst_init: %s ", error->message); + g_error_free(error); + return CA_ERROR_INVALID; + } -int driver_destroy(ca_context *c) { - struct private *p; - struct outstanding *out; + if (!(p = ca_new0(struct private, 1))) + return CA_ERROR_OOM; + c->private = p; - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); + if (!(p->outstanding_mutex = ca_mutex_new())) { + driver_destroy(c); + return CA_ERROR_OOM; + } - p = PRIVATE(c); + if (sem_init(&p->semaphore, 0, 0) < 0) { + driver_destroy(c); + return CA_ERROR_OOM; + } + p->semaphore_allocated = TRUE; - if (p->outstanding_mutex) { - ca_mutex_lock(p->outstanding_mutex); + p->mgr_bus = gst_bus_new(); + if (p->mgr_bus == NULL) { + driver_destroy(c); + return CA_ERROR_OOM; + } + gst_bus_set_flushing(p->mgr_bus, FALSE); - /* Tell all player threads to terminate */ - out = p->outstanding; - while (out) { - if (!out->dead) - send_eos_msg(out, CA_ERROR_DESTROYED); - out = out->next; + /* Give a reference to the bus to the mgr thread */ + if (pthread_create(&thread, NULL, thread_func, p) < 0) { + driver_destroy(c); + return CA_ERROR_OOM; } + p->mgr_thread_running = TRUE; - /* Now that we've sent EOS for all pending players, append a - * message to wait for the mgr thread to exit */ - if (p->mgr_thread_running && p->semaphore_allocated) { - send_mgr_exit_msg(p); + return CA_SUCCESS; +} - p->signal_semaphore = TRUE; - while (p->mgr_thread_running) { - ca_mutex_unlock(p->outstanding_mutex); - sem_wait(&p->semaphore); +int driver_destroy(ca_context *c) { + struct private *p; + struct outstanding *out; + + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); + + p = PRIVATE(c); + + if (p->outstanding_mutex) { ca_mutex_lock(p->outstanding_mutex); - } - } - ca_mutex_unlock(p->outstanding_mutex); - ca_mutex_free(p->outstanding_mutex); - } + /* Tell all player threads to terminate */ + out = p->outstanding; + while (out) { + if (!out->dead) + send_eos_msg(out, CA_ERROR_DESTROYED); + out = out->next; + } + + /* Now that we've sent EOS for all pending players, append a + * message to wait for the mgr thread to exit */ + if (p->mgr_thread_running && p->semaphore_allocated) { + send_mgr_exit_msg(p); + + p->signal_semaphore = TRUE; + while (p->mgr_thread_running) { + ca_mutex_unlock(p->outstanding_mutex); + sem_wait(&p->semaphore); + ca_mutex_lock(p->outstanding_mutex); + } + } + + ca_mutex_unlock(p->outstanding_mutex); + ca_mutex_free(p->outstanding_mutex); + } - if (p->mgr_bus) - g_object_unref(p->mgr_bus); + if (p->mgr_bus) + g_object_unref(p->mgr_bus); - if (p->theme) - ca_theme_data_free(p->theme); + if (p->theme) + ca_theme_data_free(p->theme); - if (p->semaphore_allocated) - sem_destroy(&p->semaphore); + if (p->semaphore_allocated) + sem_destroy(&p->semaphore); - ca_free(p); + ca_free(p); - /* no gst_deinit(), see doc */ + /* no gst_deinit(), see doc */ - return CA_SUCCESS; + return CA_SUCCESS; } int driver_change_device(ca_context *c, const char *device) { - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); - return CA_SUCCESS; + return CA_SUCCESS; } int driver_change_props(ca_context *c, ca_proplist *changed, ca_proplist *merged) { - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(changed, CA_ERROR_INVALID); - ca_return_val_if_fail(merged, CA_ERROR_INVALID); - ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(changed, CA_ERROR_INVALID); + ca_return_val_if_fail(merged, CA_ERROR_INVALID); + ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); - return CA_SUCCESS; + return CA_SUCCESS; } static void send_eos_msg(struct outstanding *out, int err) { - struct private *p; - GstMessage *m; - GstStructure *s; + struct private *p; + GstMessage *m; + GstStructure *s; - out->dead = TRUE; - out->err = err; + out->dead = TRUE; + out->err = err; - p = PRIVATE(out->context); - s = gst_structure_new("application/eos", "info", G_TYPE_POINTER, out, NULL); - m = gst_message_new_application (GST_OBJECT (out->pipeline), s); + p = PRIVATE(out->context); + s = gst_structure_new("application/eos", "info", G_TYPE_POINTER, out, NULL); + m = gst_message_new_application (GST_OBJECT (out->pipeline), s); - gst_bus_post (p->mgr_bus, m); + gst_bus_post (p->mgr_bus, m); } static GstBusSyncReply bus_cb(GstBus *bus, GstMessage *message, gpointer data) { - int err; - struct outstanding *out; - struct private *p; + int err; + struct outstanding *out; + struct private *p; - ca_return_val_if_fail(bus, GST_BUS_DROP); - ca_return_val_if_fail(message, GST_BUS_DROP); - ca_return_val_if_fail(data, GST_BUS_DROP); + ca_return_val_if_fail(bus, GST_BUS_DROP); + ca_return_val_if_fail(message, GST_BUS_DROP); + ca_return_val_if_fail(data, GST_BUS_DROP); - out = data; - p = PRIVATE(out->context); + out = data; + p = PRIVATE(out->context); - switch (GST_MESSAGE_TYPE(message)) { - /* for all elements */ + switch (GST_MESSAGE_TYPE(message)) { + /* for all elements */ case GST_MESSAGE_ERROR: - err = CA_ERROR_SYSTEM; - break; + err = CA_ERROR_SYSTEM; + break; case GST_MESSAGE_EOS: - /* only respect EOS from the toplevel pipeline */ - if (GST_OBJECT(out->pipeline) != GST_MESSAGE_SRC(message)) - return GST_BUS_PASS; + /* only respect EOS from the toplevel pipeline */ + if (GST_OBJECT(out->pipeline) != GST_MESSAGE_SRC(message)) + return GST_BUS_PASS; - err = CA_SUCCESS; - break; + err = CA_SUCCESS; + break; default: - return GST_BUS_PASS; - } + return GST_BUS_PASS; + } - /* Bin finished playback: ask the manager thread to shut it - * down, since we can't from the sync message handler */ - ca_mutex_lock(p->outstanding_mutex); - if (!out->dead) - send_eos_msg(out, err); - ca_mutex_unlock(p->outstanding_mutex); + /* Bin finished playback: ask the manager thread to shut it + * down, since we can't from the sync message handler */ + ca_mutex_lock(p->outstanding_mutex); + if (!out->dead) + send_eos_msg(out, err); + ca_mutex_unlock(p->outstanding_mutex); - return GST_BUS_PASS; + return GST_BUS_PASS; } struct ca_sound_file { - GstElement *fdsrc; + GstElement *fdsrc; }; static int ca_gst_sound_file_open(ca_sound_file **_f, const char *fn) { - int fd; - ca_sound_file *f; + int fd; + ca_sound_file *f; - ca_return_val_if_fail(_f, CA_ERROR_INVALID); - ca_return_val_if_fail(fn, CA_ERROR_INVALID); + ca_return_val_if_fail(_f, CA_ERROR_INVALID); + ca_return_val_if_fail(fn, CA_ERROR_INVALID); - if ((fd = open(fn, O_RDONLY)) == -1) - return errno == ENOENT ? CA_ERROR_NOTFOUND : CA_ERROR_SYSTEM; + if ((fd = open(fn, O_RDONLY)) == -1) + return errno == ENOENT ? CA_ERROR_NOTFOUND : CA_ERROR_SYSTEM; - if (!(f = ca_new0(ca_sound_file, 1))) { - close(fd); - return CA_ERROR_OOM; - } + if (!(f = ca_new0(ca_sound_file, 1))) { + close(fd); + return CA_ERROR_OOM; + } - if (!(f->fdsrc = gst_element_factory_make("fdsrc", NULL))) { - close(fd); - ca_free(f); - return CA_ERROR_OOM; - } + if (!(f->fdsrc = gst_element_factory_make("fdsrc", NULL))) { + close(fd); + ca_free(f); + return CA_ERROR_OOM; + } - g_object_set(GST_OBJECT(f->fdsrc), "fd", fd, NULL); - *_f = f; + g_object_set(GST_OBJECT(f->fdsrc), "fd", fd, NULL); + *_f = f; - return CA_SUCCESS; + return CA_SUCCESS; } static void on_pad_added(GstElement *element, GstPad *pad, gboolean arg1, gpointer data) { - GstStructure *structure; - GstElement *sinkelement; - GstCaps *caps; - GstPad *vpad; - const char *type; - - sinkelement = GST_ELEMENT(data); + GstStructure *structure; + GstElement *sinkelement; + GstCaps *caps; + GstPad *vpad; + const char *type; + + sinkelement = GST_ELEMENT(data); + + caps = gst_pad_get_caps(pad); + if (gst_caps_is_empty(caps) || gst_caps_is_any(caps)) { + gst_caps_unref(caps); + return; + } - caps = gst_pad_get_caps(pad); - if (gst_caps_is_empty(caps) || gst_caps_is_any(caps)) { + structure = gst_caps_get_structure(caps, 0); + type = gst_structure_get_name(structure); + if (g_str_has_prefix(type, "audio/x-raw") == TRUE) { + vpad = gst_element_get_pad(sinkelement, "sink"); + gst_pad_link(pad, vpad); + gst_object_unref(vpad); + } gst_caps_unref(caps); - return; - } - - structure = gst_caps_get_structure(caps, 0); - type = gst_structure_get_name(structure); - if (g_str_has_prefix(type, "audio/x-raw") == TRUE) { - vpad = gst_element_get_pad(sinkelement, "sink"); - gst_pad_link(pad, vpad); - gst_object_unref(vpad); - } - gst_caps_unref(caps); } static void send_mgr_exit_msg (struct private *p) { - GstMessage *m; - GstStructure *s; + GstMessage *m; + GstStructure *s; - s = gst_structure_new("application/mgr-exit", NULL); - m = gst_message_new_application (NULL, s); + s = gst_structure_new("application/mgr-exit", NULL); + m = gst_message_new_application (NULL, s); - gst_bus_post (p->mgr_bus, m); + gst_bus_post (p->mgr_bus, m); } /* Global manager thread that shuts down GStreamer pipelines when ordered */ static void* thread_func(void *userdata) { - struct private *p = userdata; - GstBus *bus = g_object_ref(p->mgr_bus); + struct private *p = userdata; + GstBus *bus = g_object_ref(p->mgr_bus); + + pthread_detach(pthread_self()); + + /* Pop messages from the manager bus until we see an exit command */ + do { + GstMessage *m = gst_bus_timed_pop(bus, GST_CLOCK_TIME_NONE); + const GstStructure *s; + const GValue *v; + struct outstanding *out; + + if (m == NULL) + break; + if (GST_MESSAGE_TYPE(m) != GST_MESSAGE_APPLICATION) { + gst_message_unref (m); + break; + } + + s = gst_message_get_structure(m); + if (gst_structure_has_name(s, "application/mgr-exit")) { + gst_message_unref (m); + break; + } + + /* Otherwise, this must be an EOS message for an outstanding pipe */ + ca_assert(gst_structure_has_name(s, "application/eos")); + v = gst_structure_get_value(s, "info"); + ca_assert(v); + out = g_value_get_pointer(v); + ca_assert(out); + + /* Set pipeline back to NULL to close things. By the time this + * completes, we can be sure bus_cb won't be called */ + if (gst_element_set_state(out->pipeline, GST_STATE_NULL) == + GST_STATE_CHANGE_FAILURE) { + gst_message_unref (m); + break; + } + if (out->callback) + out->callback(out->context, out->id, out->err, out->userdata); - pthread_detach(pthread_self()); + ca_mutex_lock(p->outstanding_mutex); + CA_LLIST_REMOVE(struct outstanding, p->outstanding, out); + outstanding_free(out); + ca_mutex_unlock(p->outstanding_mutex); - /* Pop messages from the manager bus until we see an exit command */ - do { - GstMessage *m = gst_bus_timed_pop(bus, GST_CLOCK_TIME_NONE); - const GstStructure *s; - const GValue *v; - struct outstanding *out; + gst_message_unref(m); + } while (TRUE); - if (m == NULL) - break; - if (GST_MESSAGE_TYPE(m) != GST_MESSAGE_APPLICATION) { - gst_message_unref (m); - break; - } + /* Signal the semaphore and exit */ + ca_mutex_lock(p->outstanding_mutex); + if (p->signal_semaphore) + sem_post(&p->semaphore); + p->mgr_thread_running = FALSE; + ca_mutex_unlock(p->outstanding_mutex); - s = gst_message_get_structure(m); - if (gst_structure_has_name(s, "application/mgr-exit")) { - gst_message_unref (m); - break; - } + gst_bus_set_flushing(bus, TRUE); + g_object_unref (bus); + return NULL; +} - /* Otherwise, this must be an EOS message for an outstanding pipe */ - ca_assert(gst_structure_has_name(s, "application/eos")); - v = gst_structure_get_value(s, "info"); - ca_assert(v); - out = g_value_get_pointer(v); - ca_assert(out); - - /* Set pipeline back to NULL to close things. By the time this - * completes, we can be sure bus_cb won't be called */ - if (gst_element_set_state(out->pipeline, GST_STATE_NULL) == - GST_STATE_CHANGE_FAILURE) { - gst_message_unref (m); - break; - } - if (out->callback) - out->callback(out->context, out->id, out->err, out->userdata); - ca_mutex_lock(p->outstanding_mutex); - CA_LLIST_REMOVE(struct outstanding, p->outstanding, out); - outstanding_free(out); - ca_mutex_unlock(p->outstanding_mutex); +int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_callback_t cb, void *userdata) { + struct private *p; + struct outstanding *out; + ca_sound_file *f; + GstElement *decodebin, *sink, *audioconvert, *audioresample, *abin; + GstBus *bus; + GstPad *audiopad; + int ret; + + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(proplist, CA_ERROR_INVALID); + ca_return_val_if_fail(!userdata || cb, CA_ERROR_INVALID); + + out = NULL; + f = NULL; + sink = NULL; + decodebin = NULL; + audioconvert = NULL; + audioresample = NULL; + abin = NULL; + p = PRIVATE(c); + + if ((ret = ca_lookup_sound_with_callback(&f, ca_gst_sound_file_open, NULL, &p->theme, c->props, proplist)) < 0) + goto fail; + + if (!(out = ca_new0(struct outstanding, 1))) + return CA_ERROR_OOM; + + out->id = id; + out->callback = cb; + out->userdata = userdata; + out->context = c; + + if (!(out->pipeline = gst_pipeline_new(NULL)) + || !(decodebin = gst_element_factory_make("decodebin2", NULL)) + || !(audioconvert = gst_element_factory_make("audioconvert", NULL)) + || !(audioresample = gst_element_factory_make("audioresample", NULL)) + || !(sink = gst_element_factory_make("autoaudiosink", NULL)) + || !(abin = gst_bin_new ("audiobin"))) { + + /* At this point, if there is a failure, free each plugin separately. */ + if (out->pipeline != NULL) + g_object_unref (out->pipeline); + if (decodebin != NULL) + g_object_unref(decodebin); + if (audioconvert != NULL) + g_object_unref(audioconvert); + if (audioresample != NULL) + g_object_unref(audioresample); + if (sink != NULL) + g_object_unref(sink); + if (abin != NULL) + g_object_unref(abin); + + ca_free(out); + + ret = CA_ERROR_OOM; + goto fail; + } - gst_message_unref(m); - } while (TRUE); + bus = gst_pipeline_get_bus(GST_PIPELINE (out->pipeline)); + gst_bus_set_sync_handler(bus, bus_cb, out); + gst_object_unref(bus); - /* Signal the semaphore and exit */ - ca_mutex_lock(p->outstanding_mutex); - if (p->signal_semaphore) - sem_post(&p->semaphore); - p->mgr_thread_running = FALSE; - ca_mutex_unlock(p->outstanding_mutex); + g_signal_connect(decodebin, "new-decoded-pad", + G_CALLBACK (on_pad_added), abin); + gst_bin_add_many(GST_BIN (abin), audioconvert, audioresample, sink, NULL); + gst_element_link_many(audioconvert, audioresample, sink, NULL); - gst_bus_set_flushing(bus, TRUE); - g_object_unref (bus); - return NULL; -} + audiopad = gst_element_get_pad(audioconvert, "sink"); + gst_element_add_pad(abin, gst_ghost_pad_new("sink", audiopad)); + gst_object_unref(audiopad); + gst_bin_add_many(GST_BIN (out->pipeline), + f->fdsrc, decodebin, abin, NULL); + if (!gst_element_link(f->fdsrc, decodebin)) { + /* Bin now owns the fdsrc... */ + f->fdsrc = NULL; -int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_callback_t cb, void *userdata) { - struct private *p; - struct outstanding *out; - ca_sound_file *f; - GstElement *decodebin, *sink, *audioconvert, *audioresample, *abin; - GstBus *bus; - GstPad *audiopad; - int ret; - - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(proplist, CA_ERROR_INVALID); - ca_return_val_if_fail(!userdata || cb, CA_ERROR_INVALID); - - out = NULL; - f = NULL; - sink = NULL; - decodebin = NULL; - audioconvert = NULL; - audioresample = NULL; - abin = NULL; - p = PRIVATE(c); - - if ((ret = ca_lookup_sound_with_callback(&f, ca_gst_sound_file_open, NULL, &p->theme, c->props, proplist)) < 0) - goto fail; - - if (!(out = ca_new0(struct outstanding, 1))) - return CA_ERROR_OOM; - - out->id = id; - out->callback = cb; - out->userdata = userdata; - out->context = c; - - if (!(out->pipeline = gst_pipeline_new(NULL)) - || !(decodebin = gst_element_factory_make("decodebin2", NULL)) - || !(audioconvert = gst_element_factory_make("audioconvert", NULL)) - || !(audioresample = gst_element_factory_make("audioresample", NULL)) - || !(sink = gst_element_factory_make("autoaudiosink", NULL)) - || !(abin = gst_bin_new ("audiobin"))) { - - /* At this point, if there is a failure, free each plugin separately. */ - if (out->pipeline != NULL) - g_object_unref (out->pipeline); - if (decodebin != NULL) - g_object_unref(decodebin); - if (audioconvert != NULL) - g_object_unref(audioconvert); - if (audioresample != NULL) - g_object_unref(audioresample); - if (sink != NULL) - g_object_unref(sink); - if (abin != NULL) - g_object_unref(abin); - - ca_free(out); - - ret = CA_ERROR_OOM; - goto fail; - } - - bus = gst_pipeline_get_bus(GST_PIPELINE (out->pipeline)); - gst_bus_set_sync_handler(bus, bus_cb, out); - gst_object_unref(bus); - - g_signal_connect(decodebin, "new-decoded-pad", - G_CALLBACK (on_pad_added), abin); - gst_bin_add_many(GST_BIN (abin), audioconvert, audioresample, sink, NULL); - gst_element_link_many(audioconvert, audioresample, sink, NULL); - - audiopad = gst_element_get_pad(audioconvert, "sink"); - gst_element_add_pad(abin, gst_ghost_pad_new("sink", audiopad)); - gst_object_unref(audiopad); - - gst_bin_add_many(GST_BIN (out->pipeline), - f->fdsrc, decodebin, abin, NULL); - if (!gst_element_link(f->fdsrc, decodebin)) { + outstanding_free(out); + ret = CA_ERROR_OOM; + goto fail; + } /* Bin now owns the fdsrc... */ f->fdsrc = NULL; - outstanding_free(out); - ret = CA_ERROR_OOM; - goto fail; - } - /* Bin now owns the fdsrc... */ - f->fdsrc = NULL; - - ca_free(f); - f = NULL; + ca_free(f); + f = NULL; - ca_mutex_lock(p->outstanding_mutex); - CA_LLIST_PREPEND(struct outstanding, p->outstanding, out); - ca_mutex_unlock(p->outstanding_mutex); + ca_mutex_lock(p->outstanding_mutex); + CA_LLIST_PREPEND(struct outstanding, p->outstanding, out); + ca_mutex_unlock(p->outstanding_mutex); - if (gst_element_set_state(out->pipeline, - GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { - ret = CA_ERROR_NOTAVAILABLE; - goto fail; - } + if (gst_element_set_state(out->pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + ret = CA_ERROR_NOTAVAILABLE; + goto fail; + } - return CA_SUCCESS; + return CA_SUCCESS; fail: - if (f && f->fdsrc) - gst_object_unref(f->fdsrc); + if (f && f->fdsrc) + gst_object_unref(f->fdsrc); - if (f) - ca_free(f); + if (f) + ca_free(f); - return ret; + return ret; } int driver_cancel(ca_context *c, uint32_t id) { - struct private *p; - struct outstanding *out = NULL; + struct private *p; + struct outstanding *out = NULL; + + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); + p = PRIVATE(c); - p = PRIVATE(c); + ca_mutex_lock(p->outstanding_mutex); - ca_mutex_lock(p->outstanding_mutex); + for (out = p->outstanding; out;/* out = out->next*/) { + struct outstanding *next; - for (out = p->outstanding; out;/* out = out->next*/) { - struct outstanding *next; + if (out->id != id || out->pipeline == NULL || out->dead == TRUE) { + out = out->next; + continue; + } - if (out->id != id || out->pipeline == NULL || out->dead == TRUE) - { - out = out->next; - continue; - } + if (gst_element_set_state(out->pipeline, GST_STATE_NULL) == + GST_STATE_CHANGE_FAILURE) + goto error; - if (gst_element_set_state(out->pipeline, GST_STATE_NULL) == - GST_STATE_CHANGE_FAILURE) { - goto error; + if (out->callback) + out->callback(c, out->id, CA_ERROR_CANCELED, out->userdata); + next = out->next; + CA_LLIST_REMOVE(struct outstanding, p->outstanding, out); + outstanding_free(out); + out = next; } - if (out->callback) - out->callback(c, out->id, CA_ERROR_CANCELED, out->userdata); - next = out->next; - CA_LLIST_REMOVE(struct outstanding, p->outstanding, out); - outstanding_free(out); - out = next; - } - ca_mutex_unlock(p->outstanding_mutex); + ca_mutex_unlock(p->outstanding_mutex); - return CA_SUCCESS; + return CA_SUCCESS; error: - ca_mutex_unlock(p->outstanding_mutex); - return CA_ERROR_SYSTEM; + ca_mutex_unlock(p->outstanding_mutex); + return CA_ERROR_SYSTEM; } int driver_cache(ca_context *c, ca_proplist *proplist) { - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(proplist, CA_ERROR_INVALID); - ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(proplist, CA_ERROR_INVALID); + ca_return_val_if_fail(PRIVATE(c), CA_ERROR_STATE); - return CA_ERROR_NOTSUPPORTED; + return CA_ERROR_NOTSUPPORTED; } int driver_playing(ca_context *c, uint32_t id, int *playing) { - struct private *p; - struct outstanding *out; + struct private *p; + struct outstanding *out; - ca_return_val_if_fail(c, CA_ERROR_INVALID); - ca_return_val_if_fail(c->private, CA_ERROR_STATE); - ca_return_val_if_fail(playing, CA_ERROR_INVALID); + ca_return_val_if_fail(c, CA_ERROR_INVALID); + ca_return_val_if_fail(c->private, CA_ERROR_STATE); + ca_return_val_if_fail(playing, CA_ERROR_INVALID); - p = PRIVATE(c); + p = PRIVATE(c); - *playing = 0; + *playing = 0; - ca_mutex_lock(p->outstanding_mutex); + ca_mutex_lock(p->outstanding_mutex); - for (out = p->outstanding; out; out = out->next) { + for (out = p->outstanding; out; out = out->next) { - if (out->id != id || out->pipeline == NULL || out->dead == TRUE) - continue; + if (out->id != id || out->pipeline == NULL || out->dead == TRUE) + continue; - *playing = 1; - break; - } + *playing = 1; + break; + } - ca_mutex_unlock(p->outstanding_mutex); + ca_mutex_unlock(p->outstanding_mutex); - return CA_SUCCESS; + return CA_SUCCESS; } |