X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;ds=sidebyside;f=libchimara%2Fschannel.c;h=71c2727dc8100a43885dec87abdae443d01365af;hb=04fac8083a2bed8f866b608c60897c1d69b7aaf5;hp=d8c924d51373fb52330631449282e5b7f1226c72;hpb=4279063976ccd181b242172de5b45a7d8f74acc9;p=projects%2Fchimara%2Fchimara.git diff --git a/libchimara/schannel.c b/libchimara/schannel.c index d8c924d..71c2727 100644 --- a/libchimara/schannel.c +++ b/libchimara/schannel.c @@ -13,6 +13,8 @@ #include "resource.h" #include "event.h" +#define VOLUME_TIMER_RESOLUTION 1.0 /* In milliseconds */ + extern GPrivate *glk_data_key; #ifdef GSTREAMER_SOUND @@ -678,6 +680,22 @@ glk_schannel_unpause(schanid_t chan) } } +static double +volume_glk_to_gstreamer(glui32 volume_glk) +{ + return CLAMP(((double)volume_glk / 0x10000), 0.0, 10.0); +} + +static void +channel_set_volume_immediately(schanid_t chan, double volume, glui32 notify) +{ + g_object_set(chan->filter, "volume", volume, NULL); + + if(notify != 0) { + /* Send a notification */ + } +} + /** * glk_schannel_set_volume: * @chan: Channel to set the volume of. @@ -710,7 +728,46 @@ glk_schannel_unpause(schanid_t chan) void glk_schannel_set_volume(schanid_t chan, glui32 vol) { - glk_schannel_set_volume_ext(chan, vol, 0, 0); + VALID_SCHANNEL(chan, return); + /* Silently ignore out-of-range volume values */ + +#ifdef GSTREAMER_SOUND + double volume = volume_glk_to_gstreamer(vol); + channel_set_volume_immediately(chan, volume, 0); +#endif +} + +static gboolean +volume_change_timeout(schanid_t chan) +{ + GTimeVal now; + g_get_current_time(&now); + + if(now.tv_sec >= chan->target_time_sec && now.tv_usec >= chan->target_time_usec) { + /* We're done - make sure the volume is at the requested level */ + g_object_set(chan->filter, "volume", chan->target_volume, NULL); + + if(chan->volume_notify) { + /* Send a notification */ + } + return FALSE; + } + + /* Calculate the appropriate step every time - a busy system may delay or + * drop timer ticks */ + double time_left_msec = (chan->target_time_sec - now.tv_sec) * 1000.0 + + (chan->target_time_usec - now.tv_usec) / 1000.0; + double steps_left = time_left_msec / VOLUME_TIMER_RESOLUTION; + double current_volume; + g_object_get(chan->filter, "volume", ¤t_volume, NULL); + double volume_step = (chan->target_volume - current_volume) / steps_left; + + g_printerr("Time left: %.2f ms\nVolume difference: %.2f\nVolume step: %.4f\n", + time_left_msec, chan->target_volume - current_volume, volume_step); + + g_object_set(chan->filter, "volume", current_volume + volume_step, NULL); + + return TRUE; } /** @@ -758,11 +815,25 @@ glk_schannel_set_volume_ext(schanid_t chan, glui32 vol, glui32 duration, glui32 /* Silently ignore out-of-range volume values */ #ifdef GSTREAMER_SOUND - gdouble volume_gst = (gdouble)vol / 0x10000; - g_object_set(chan->filter, "volume", CLAMP(volume_gst, 0.0, 10.0), NULL); -#endif + double target_volume = volume_glk_to_gstreamer(vol); + + if(duration == 0) { + channel_set_volume_immediately(chan, target_volume, notify); + return; + } + + GTimeVal target_time; + g_get_current_time(&target_time); + g_time_val_add(&target_time, (long)duration * 1000); - /* Not implemented */ + chan->target_volume = target_volume; + chan->target_time_sec = target_time.tv_sec; + chan->target_time_usec = target_time.tv_usec; + chan->volume_notify = notify; + + /* Set up a timer for the volume */ + g_timeout_add(VOLUME_TIMER_RESOLUTION, (GSourceFunc)volume_change_timeout, chan); +#endif } /**