X-Git-Url: http://git.maemo.org/git/?p=mafwsubrenderer;a=blobdiff_plain;f=libmafw-gst-renderer%2Fmafw-gst-renderer-worker-volume.c;fp=libmafw-gst-renderer%2Fmafw-gst-renderer-worker-volume.c;h=0000000000000000000000000000000000000000;hp=31aa22bacfefffa6543316ab66e5d055643b5a7c;hb=be2c98fb83895d10ac44af7b9a9c3e00ca54bf49;hpb=c2bbb2bb3bead80144e2dda3ccd40599e4a2b48d diff --git a/libmafw-gst-renderer/mafw-gst-renderer-worker-volume.c b/libmafw-gst-renderer/mafw-gst-renderer-worker-volume.c deleted file mode 100644 index 31aa22b..0000000 --- a/libmafw-gst-renderer/mafw-gst-renderer-worker-volume.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * This file is a part of MAFW - * - * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved. - * - * Contact: Visa Smolander - * - * This library 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; version 2.1 of - * the License, or (at your option) any later version. - * - * This library 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifndef MAFW_GST_RENDERER_DISABLE_PULSE_VOLUME - -#include -#include -#include -#include - -#include "mafw-gst-renderer-worker-volume.h" -#include "config.h" - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "mafw-gst-renderer-worker-volume" - -#define MAFW_GST_RENDERER_WORKER_VOLUME_SERVER NULL - -#define MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PROPERTY "PULSE_PROP_media.role" -#define MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX "sink-input-by-media-role:" -#define MAFW_GST_RENDERER_WORKER_VOLUME_ROLE "x-maemo" - -#define MAFW_GST_RENDERER_WORKER_SET_TIMEOUT 200 - - -struct _MafwGstRendererWorkerVolume { - pa_glib_mainloop *mainloop; - pa_context *context; - gdouble pulse_volume; - gboolean pulse_mute; - MafwGstRendererWorkerVolumeChangedCb cb; - gpointer user_data; - MafwGstRendererWorkerVolumeMuteCb mute_cb; - gpointer mute_user_data; - gdouble current_volume; - gboolean current_mute; - gboolean pending_operation; - gdouble pending_operation_volume; - gboolean pending_operation_mute; - guint change_request_id; - pa_operation *pa_operation; -}; - -typedef struct { - MafwGstRendererWorkerVolume *wvolume; - MafwGstRendererWorkerVolumeInitCb cb; - gpointer user_data; -} InitCbClosure; - -#define _pa_volume_to_per_one(volume) \ - ((guint) ((((gdouble)(volume) / (gdouble) PA_VOLUME_NORM) + \ - (gdouble) 0.005) * (gdouble) 100.0) / (gdouble) 100.0) -#define _pa_volume_from_per_one(volume) \ - ((pa_volume_t)((gdouble)(volume) * (gdouble) PA_VOLUME_NORM)) - -#define _pa_operation_running(wvolume) \ - (wvolume->pa_operation != NULL && \ - pa_operation_get_state(wvolume->pa_operation) == PA_OPERATION_RUNNING) - -static void _state_cb_init(pa_context *c, void *data); - - -static gchar *_get_client_name(void) { - gchar buf[PATH_MAX]; - gchar *name = NULL; - - if (pa_get_binary_name(buf, sizeof(buf))) - name = g_strdup_printf("mafw-gst-renderer[%s]", buf); - else - name = g_strdup("mafw-gst-renderer"); - - return name; -} - -static void _ext_stream_restore_read_cb(pa_context *c, - const pa_ext_stream_restore2_info *i, - int eol, - void *userdata) -{ - MafwGstRendererWorkerVolume *wvolume = userdata; - gdouble volume; - gboolean mute; - - if (eol < 0) { - g_critical("eol parameter should not be < 1. " - "Discarding volume event"); - return; - } - - if (i == NULL || - strcmp(i->name, MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX - MAFW_GST_RENDERER_WORKER_VOLUME_ROLE) != 0) { - return; - } - - volume = _pa_volume_to_per_one(pa_cvolume_max(&i->volume)); - mute = i->mute != 0 ? TRUE : FALSE; - - if (_pa_operation_running(wvolume) || - (wvolume->pending_operation && - (wvolume->pending_operation_volume != volume -#ifdef MAFW_GST_RENDERER_ENABLE_MUTE - || wvolume->pending_operation_mute != mute -#endif - ))) { - g_debug("volume notification, but operation running, ignoring"); - return; - } - - wvolume->pulse_volume = volume; - wvolume->pulse_mute = mute; - - /* EMIT VOLUME */ - g_debug("ext stream volume is %lf (mute: %d) for role %s in device %s", - wvolume->pulse_volume, wvolume->pulse_mute, i->name, i->device); - if (!wvolume->pending_operation && - wvolume->pulse_volume != wvolume->current_volume) { - wvolume->current_volume = wvolume->pulse_volume; - if (wvolume->cb != NULL) { - g_debug("signalling volume"); - wvolume->cb(wvolume, wvolume->current_volume, - wvolume->user_data); - } - } -#ifdef MAFW_GST_RENDERER_ENABLE_MUTE - if (!wvolume->pending_operation && - wvolume->pulse_mute != wvolume->current_mute) { - wvolume->current_mute = wvolume->pulse_mute; - if (wvolume->mute_cb != NULL) { - g_debug("signalling mute"); - wvolume->mute_cb(wvolume, wvolume->current_mute, - wvolume->mute_user_data); - } - } -#endif - - wvolume->pending_operation = FALSE; -} - -static void _destroy_context(MafwGstRendererWorkerVolume *wvolume) -{ - if (wvolume->pa_operation != NULL) { - if (pa_operation_get_state(wvolume->pa_operation) == - PA_OPERATION_RUNNING) { - pa_operation_cancel(wvolume->pa_operation); - } - pa_operation_unref(wvolume->pa_operation); - wvolume->pa_operation = NULL; - } - pa_context_unref(wvolume->context); -} - -static InitCbClosure *_init_cb_closure_new(MafwGstRendererWorkerVolume *wvolume, - MafwGstRendererWorkerVolumeInitCb cb, - gpointer user_data) -{ - InitCbClosure *closure; - - closure = g_new(InitCbClosure, 1); - closure->wvolume = wvolume; - closure->cb = cb; - closure->user_data = user_data; - - return closure; -} - -static void _connect(gpointer user_data) -{ - gchar *name = NULL; - pa_mainloop_api *api = NULL; - InitCbClosure *closure = user_data; - MafwGstRendererWorkerVolume *wvolume = closure->wvolume; - - name = _get_client_name(); - - /* get the mainloop api and create a context */ - api = pa_glib_mainloop_get_api(wvolume->mainloop); - wvolume->context = pa_context_new(api, name); - g_assert(wvolume->context != NULL); - - /* register some essential callbacks */ - pa_context_set_state_callback(wvolume->context, _state_cb_init, - closure); - - g_debug("connecting to pulse"); - - g_assert(pa_context_connect(wvolume->context, - MAFW_GST_RENDERER_WORKER_VOLUME_SERVER, - PA_CONTEXT_NOAUTOSPAWN | PA_CONTEXT_NOFAIL, - NULL) >= 0); - g_free(name); -} - -static gboolean _reconnect(gpointer user_data) -{ - InitCbClosure *closure = user_data; - MafwGstRendererWorkerVolume *wvolume = closure->wvolume; - - g_warning("got disconnected from pulse, reconnecting"); - _destroy_context(wvolume); - _connect(user_data); - - return FALSE; -} - -static void -_state_cb(pa_context *c, void *data) -{ - MafwGstRendererWorkerVolume *wvolume = data; - pa_context_state_t state; - - state = pa_context_get_state(c); - - switch (state) { - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - { - InitCbClosure *closure; - - closure = _init_cb_closure_new(wvolume, NULL, NULL); - g_idle_add(_reconnect, closure); - break; - } - case PA_CONTEXT_READY: { - pa_operation *o; - - o = pa_ext_stream_restore2_read(c, _ext_stream_restore_read_cb, - wvolume); - g_assert(o != NULL); - pa_operation_unref(o); - - break; - } - default: - break; - } -} - -static void _ext_stream_restore_read_cb_init(pa_context *c, - const pa_ext_stream_restore2_info *i, - int eol, - void *userdata) -{ - InitCbClosure *closure = userdata; - - if (eol < 0) { - g_critical("eol parameter should not be < 1"); - } - - if (i == NULL || - strcmp(i->name, MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX - MAFW_GST_RENDERER_WORKER_VOLUME_ROLE) != 0) - return; - - closure->wvolume->pulse_volume = - _pa_volume_to_per_one(pa_cvolume_max(&i->volume)); - closure->wvolume->pulse_mute = i->mute != 0 ? TRUE : FALSE; - closure->wvolume->current_volume = closure->wvolume->pulse_volume; - closure->wvolume->current_mute = closure->wvolume->pulse_mute; - - /* NOT EMIT VOLUME, BUT DEBUG */ - g_debug("ext stream volume is %lf (mute: %d) for role %s in device %s", - closure->wvolume->pulse_volume, i->mute, i->name, i->device); - - if (closure->cb != NULL) { - g_debug("initialized: returning volume manager"); - closure->cb(closure->wvolume, closure->user_data); - } else { - if (closure->wvolume->cb != NULL) { - g_debug("signalling volume after reconnection"); - closure->wvolume->cb(closure->wvolume, - closure->wvolume->current_volume, - closure->wvolume->user_data); - } - if (closure->wvolume->mute_cb != NULL) { - g_debug("signalling mute after reconnection"); - closure->wvolume->mute_cb(closure->wvolume, - closure->wvolume-> - current_mute, - closure->wvolume-> - mute_user_data); - } - } - - pa_context_set_state_callback(closure->wvolume->context, _state_cb, - closure->wvolume); - - g_free(closure); -} - -static void _ext_stream_restore_subscribe_cb(pa_context *c, void *userdata) -{ - pa_operation *o; - - o = pa_ext_stream_restore2_read(c, _ext_stream_restore_read_cb, userdata); - g_assert(o != NULL); - pa_operation_unref(o); -} - -static void -_state_cb_init(pa_context *c, void *data) -{ - InitCbClosure *closure = data; - MafwGstRendererWorkerVolume *wvolume = closure->wvolume; - pa_context_state_t state; - - state = pa_context_get_state(c); - - g_debug("state: %d", state); - - switch (state) { - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - g_critical("Connection to pulse failed, reconnection in 1 " - "second"); - g_timeout_add_seconds(1, _reconnect, closure); - break; - case PA_CONTEXT_READY: { - pa_operation *o; - - g_debug("PA_CONTEXT_READY"); - - o = pa_ext_stream_restore2_read(c, - _ext_stream_restore_read_cb_init, - closure); - g_assert(o != NULL); - pa_operation_unref(o); - - pa_ext_stream_restore_set_subscribe_cb( - c, _ext_stream_restore_subscribe_cb, wvolume); - - o = pa_ext_stream_restore_subscribe(c, 1, NULL, NULL); - g_assert(o != NULL); - pa_operation_unref(o); - - break; - } - default: - break; - } -} - -static gboolean _destroy_idle(gpointer data) -{ - MafwGstRendererWorkerVolume *wvolume = data; - - g_debug("destroying"); - - _destroy_context(wvolume); - pa_glib_mainloop_free(wvolume->mainloop); - g_free(wvolume); - - return FALSE; -} - -static void -_state_cb_destroy(pa_context *c, void *data) -{ - pa_context_state_t state; - - state = pa_context_get_state(c); - - switch (state) { - case PA_CONTEXT_TERMINATED: - g_idle_add(_destroy_idle, data); - break; - case PA_CONTEXT_FAILED: - g_error("Unexpected problem in volume management"); - break; - default: - break; - } -} - -static void _success_cb(pa_context *c, int success, void *userdata) -{ - if (success == 0) { - g_critical("Setting volume to pulse operation failed"); - } -} - -static void _remove_set_timeout(MafwGstRendererWorkerVolume *wvolume) -{ - if (wvolume->change_request_id != 0) { - g_source_remove(wvolume->change_request_id); - } - wvolume->change_request_id = 0; -} - -static gboolean _set_timeout(gpointer data) -{ - pa_ext_stream_restore2_info info; - pa_ext_stream_restore2_info *infos[1]; - MafwGstRendererWorkerVolume *wvolume = data; - - if (wvolume->pending_operation) { - g_debug("setting volume ignored as there is still a pending " - "operation. Waiting till next iteration"); - } else if (wvolume->pulse_volume != wvolume->current_volume -#ifdef MAFW_GST_RENDERER_ENABLE_MUTE - || wvolume->pulse_mute != wvolume->current_mute -#endif - ) { - - info.name = MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX - MAFW_GST_RENDERER_WORKER_VOLUME_ROLE; - info.channel_map.channels = 1; - info.channel_map.map[0] = PA_CHANNEL_POSITION_MONO; - info.device = NULL; - info.volume_is_absolute = TRUE; - infos[0] = &info; - - info.mute = wvolume->current_mute; - pa_cvolume_init(&info.volume); - pa_cvolume_set(&info.volume, info.channel_map.channels, - _pa_volume_from_per_one(wvolume-> - current_volume)); - - g_debug("setting volume to %lf and mute to %d", - wvolume->current_volume, wvolume->current_mute); - - if (wvolume->pa_operation != NULL) { - pa_operation_unref(wvolume->pa_operation); - } - - wvolume->pending_operation = TRUE; - wvolume->pending_operation_volume = wvolume->current_volume; - wvolume->pending_operation_mute = wvolume->current_mute; - - wvolume->pa_operation = pa_ext_stream_restore2_write( - wvolume->context, - PA_UPDATE_REPLACE, - (const pa_ext_stream_restore2_info* - const *)infos, - 1, TRUE, _success_cb, wvolume); - - if (wvolume->pa_operation == NULL) { - g_critical("NULL operation when writing volume to " - "pulse"); - _remove_set_timeout(wvolume); - } - } else { - g_debug("removing volume timeout"); - _remove_set_timeout(wvolume); - } - - return wvolume->change_request_id != 0; -} - -void mafw_gst_renderer_worker_volume_init(GMainContext *main_context, - MafwGstRendererWorkerVolumeInitCb cb, - gpointer user_data, - MafwGstRendererWorkerVolumeChangedCb - changed_cb, - gpointer changed_user_data, - MafwGstRendererWorkerVolumeMuteCb - mute_cb, gpointer mute_user_data) -{ - MafwGstRendererWorkerVolume *wvolume = NULL; - InitCbClosure *closure; - - g_return_if_fail(cb != NULL); - - g_assert(g_setenv(MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PROPERTY, - MAFW_GST_RENDERER_WORKER_VOLUME_ROLE, FALSE)); - - g_debug("initializing volume manager"); - - wvolume = g_new0(MafwGstRendererWorkerVolume, 1); - - wvolume->pulse_volume = 1.0; - wvolume->pulse_mute = FALSE; - wvolume->cb = changed_cb; - wvolume->user_data = changed_user_data; - wvolume->mute_cb = mute_cb; - wvolume->mute_user_data = mute_user_data; - - wvolume->mainloop = pa_glib_mainloop_new(main_context); - g_assert(wvolume->mainloop != NULL); - - closure = _init_cb_closure_new(wvolume, cb, user_data); - _connect(closure); -} - -void mafw_gst_renderer_worker_volume_set(MafwGstRendererWorkerVolume *wvolume, - gdouble volume, gboolean mute) -{ - gboolean signal_volume, signal_mute; - - g_return_if_fail(wvolume != NULL); - g_return_if_fail(pa_context_get_state(wvolume->context) == - PA_CONTEXT_READY); - -#ifndef MAFW_GST_RENDERER_ENABLE_MUTE - mute = FALSE; -#endif - - signal_volume = wvolume->current_volume != volume && - wvolume->cb != NULL; - signal_mute = wvolume->current_mute != mute && wvolume->mute_cb != NULL; - - wvolume->current_volume = volume; - wvolume->current_mute = mute; - - g_debug("volume set: %lf (mute %d)", volume, mute); - - if (signal_volume) { - g_debug("signalling volume"); - wvolume->cb(wvolume, volume, wvolume->user_data); - } - - if (signal_mute) { - g_debug("signalling mute"); - wvolume->mute_cb(wvolume, mute, wvolume->mute_user_data); - } - - if ((signal_mute || signal_volume) && wvolume->change_request_id == 0) { - wvolume->change_request_id = - g_timeout_add(MAFW_GST_RENDERER_WORKER_SET_TIMEOUT, - _set_timeout, wvolume); - - _set_timeout(wvolume); - } -} - -gdouble mafw_gst_renderer_worker_volume_get( - MafwGstRendererWorkerVolume *wvolume) -{ - g_return_val_if_fail(wvolume != NULL, 0.0); - - g_debug("getting volume; %lf", wvolume->current_volume); - - return wvolume->current_volume; -} - -gboolean mafw_gst_renderer_worker_volume_is_muted( - MafwGstRendererWorkerVolume *wvolume) -{ - g_return_val_if_fail(wvolume != NULL, FALSE); - - g_debug("getting mute; %d", wvolume->current_mute); - - return wvolume->current_mute; -} - -void mafw_gst_renderer_worker_volume_destroy( - MafwGstRendererWorkerVolume *wvolume) -{ - g_return_if_fail(wvolume != NULL); - - g_debug("disconnecting"); - - pa_ext_stream_restore_set_subscribe_cb(wvolume->context, NULL, NULL); - pa_context_set_state_callback(wvolume->context, _state_cb_destroy, - wvolume); - pa_context_disconnect(wvolume->context); -} - - - -#else - - -#include "mafw-gst-renderer-worker-volume.h" - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "mafw-gst-renderer-worker-volume-fake" - -struct _MafwGstRendererWorkerVolume { - MafwGstRendererWorkerVolumeChangedCb cb; - gpointer user_data; - MafwGstRendererWorkerVolumeMuteCb mute_cb; - gpointer mute_user_data; - gdouble current_volume; - gboolean current_mute; -}; - -typedef struct { - MafwGstRendererWorkerVolume *wvolume; - MafwGstRendererWorkerVolumeInitCb cb; - gpointer user_data; -} InitCbClosure; - -static gboolean _init_cb_closure(gpointer user_data) -{ - InitCbClosure *closure = user_data; - - if (closure->cb != NULL) { - closure->cb(closure->wvolume, closure->user_data); - } - g_free(closure); - - return FALSE; -} - -void mafw_gst_renderer_worker_volume_init(GMainContext *main_context, - MafwGstRendererWorkerVolumeInitCb cb, - gpointer user_data, - MafwGstRendererWorkerVolumeChangedCb - changed_cb, - gpointer changed_user_data, - MafwGstRendererWorkerVolumeMuteCb - mute_cb, gpointer mute_user_data) -{ - MafwGstRendererWorkerVolume *wvolume = NULL; - InitCbClosure *closure; - - g_return_if_fail(cb != NULL); - - g_debug("initializing volume manager"); - - wvolume = g_new0(MafwGstRendererWorkerVolume, 1); - - wvolume->cb = changed_cb; - wvolume->user_data = changed_user_data; - wvolume->mute_cb = mute_cb; - wvolume->mute_user_data = mute_user_data; - wvolume->current_volume = 0.485; - - closure = g_new0(InitCbClosure, 1); - closure->wvolume = wvolume; - closure->cb = cb; - closure->user_data = user_data; - g_idle_add(_init_cb_closure, closure); -} - -void mafw_gst_renderer_worker_volume_set(MafwGstRendererWorkerVolume *wvolume, - gdouble volume, gboolean mute) -{ - gboolean signal_volume, signal_mute; - - g_return_if_fail(wvolume != NULL); - -#ifndef MAFW_GST_RENDERER_ENABLE_MUTE - mute = FALSE; -#endif - - signal_volume = wvolume->current_volume != volume && - wvolume->cb != NULL; - signal_mute = wvolume->current_mute != mute && wvolume->mute_cb != NULL; - - wvolume->current_volume = volume; - wvolume->current_mute = mute; - - g_debug("volume set: %lf (mute %d)", volume, mute); - - if (signal_volume) { - g_debug("signalling volume"); - wvolume->cb(wvolume, volume, wvolume->user_data); - } - - if (signal_mute) { - g_debug("signalling mute"); - wvolume->mute_cb(wvolume, mute, wvolume->mute_user_data); - } -} - -gdouble mafw_gst_renderer_worker_volume_get( - MafwGstRendererWorkerVolume *wvolume) -{ - g_return_val_if_fail(wvolume != NULL, 0.0); - - g_debug("getting volume; %lf", wvolume->current_volume); - - return wvolume->current_volume; -} - -gboolean mafw_gst_renderer_worker_volume_is_muted( - MafwGstRendererWorkerVolume *wvolume) -{ - g_return_val_if_fail(wvolume != NULL, FALSE); - - g_debug("getting mute; %d", wvolume->current_mute); - - return wvolume->current_mute; -} - -void mafw_gst_renderer_worker_volume_destroy( - MafwGstRendererWorkerVolume *wvolume) -{ - g_return_if_fail(wvolume != NULL); - - g_free(wvolume); -} - -#endif