X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=libchimara%2Fschannel.c;h=d176d7d87caf7ef04aa878340aea32943863b2a1;hb=1461483626f28b52f8f9f3cc350f9cb330579285;hp=d8c924d51373fb52330631449282e5b7f1226c72;hpb=4279063976ccd181b242172de5b45a7d8f74acc9;p=projects%2Fchimara%2Fchimara.git diff --git a/libchimara/schannel.c b/libchimara/schannel.c index d8c924d..d176d7d 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 @@ -713,6 +715,45 @@ glk_schannel_set_volume(schanid_t chan, glui32 vol) glk_schannel_set_volume_ext(chan, vol, 0, 0); } +static double +volume_glk_to_gstreamer(glui32 volume_glk) +{ + return CLAMP(((double)volume_glk / 0x10000), 0.0, 10.0); +} + +#ifdef GSTREAMER_SOUND +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) + event_throw(chan->glk, evtype_VolumeNotify, NULL, 0, chan->volume_notify); + + chan->volume_timer_id = 0; + 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_object_set(chan->filter, "volume", current_volume + volume_step, NULL); + + return TRUE; +} +#endif /* GSTREAMER_SOUND */ + /** * glk_schannel_set_volume_ext: * @chan: Channel to set the volume of. @@ -756,13 +797,35 @@ glk_schannel_set_volume_ext(schanid_t chan, glui32 vol, glui32 duration, glui32 { VALID_SCHANNEL(chan, return); /* 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 + /* Interrupt a previous volume change */ + if(chan->volume_timer_id > 0) + g_source_remove(chan->volume_timer_id); + + double target_volume = volume_glk_to_gstreamer(vol); + + if(duration == 0) { + g_object_set(chan->filter, "volume", target_volume, NULL); - /* Not implemented */ + if(notify != 0) + event_throw(chan->glk, evtype_VolumeNotify, NULL, 0, notify); + + return; + } + + GTimeVal target_time; + g_get_current_time(&target_time); + g_time_val_add(&target_time, (long)duration * 1000); + + 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 */ + chan->volume_timer_id = g_timeout_add(VOLUME_TIMER_RESOLUTION, (GSourceFunc)volume_change_timeout, chan); +#endif } /**