]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/source.h
volume: Rename 'sync volume' to 'deferred volume'.
[pulseaudio] / src / pulsecore / source.h
index 3cdc77aef4968927eb8198a0c50048cdf3f122cb..05f82427c8f81294f24771bbaf8578eadf18457e 100644 (file)
 ***/
 
 typedef struct pa_source pa_source;
+typedef struct pa_source_volume_change pa_source_volume_change;
 
 #include <inttypes.h>
 
+#include <pulse/def.h>
+#include <pulse/format.h>
 #include <pulse/sample.h>
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
 
 #include <pulsecore/core.h>
 #include <pulsecore/idxset.h>
-#include <pulsecore/memblock.h>
 #include <pulsecore/memchunk.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/module.h>
 #include <pulsecore/asyncmsgq.h>
 #include <pulsecore/msgobject.h>
 #include <pulsecore/rtpoll.h>
-#include <pulsecore/source-output.h>
 #include <pulsecore/card.h>
 #include <pulsecore/queue.h>
 #include <pulsecore/thread-mq.h>
+#include <pulsecore/source-output.h>
 
 #define PA_MAX_OUTPUTS_PER_SOURCE 32
 
@@ -52,6 +54,9 @@ static inline pa_bool_t PA_SOURCE_IS_LINKED(pa_source_state_t x) {
     return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE || x == PA_SOURCE_SUSPENDED;
 }
 
+/* A generic definition for void callback functions */
+typedef void(*pa_source_cb_t)(pa_source *s);
+
 struct pa_source {
     pa_msgobject parent;
 
@@ -80,16 +85,23 @@ struct pa_source {
     pa_volume_t base_volume; /* shall be constant */
     unsigned n_volume_steps; /* shall be constant */
 
-    pa_cvolume volume, soft_volume;
+    /* Also see http://pulseaudio.org/wiki/InternalVolumes */
+    pa_cvolume reference_volume; /* The volume exported and taken as reference base for relative source output volumes */
+    pa_cvolume real_volume;      /* The volume that the hardware is configured to  */
+    pa_cvolume soft_volume;      /* The internal software volume we apply to all PCM data while it passes through */
+
     pa_bool_t muted:1;
 
     pa_bool_t refresh_volume:1;
     pa_bool_t refresh_muted:1;
-
     pa_bool_t save_port:1;
     pa_bool_t save_volume:1;
     pa_bool_t save_muted:1;
 
+    /* Saved volume state while we're in passthrough mode */
+    pa_cvolume saved_volume;
+    pa_bool_t saved_save_volume:1;
+
     pa_asyncmsgq *asyncmsgq;
 
     pa_memchunk silence;
@@ -104,31 +116,59 @@ struct pa_source {
      * inhibited */
     int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */
 
-    /* Callled when the volume is queried. Called from main loop
+    /* Called when the volume is queried. Called from main loop
      * context. If this is NULL a PA_SOURCE_MESSAGE_GET_VOLUME message
      * will be sent to the IO thread instead. If refresh_volume is
-     * FALSE neither this function is called nor a message is sent. */
-    void (*get_volume)(pa_source *s);         /* ditto */
+     * FALSE neither this function is called nor a message is sent.
+     *
+     * You must use the function pa_source_set_get_volume_callback() to
+     * set this callback. */
+    pa_source_cb_t get_volume; /* may be NULL */
 
     /* Called when the volume shall be changed. Called from main loop
      * context. If this is NULL a PA_SOURCE_MESSAGE_SET_VOLUME message
-     * will be sent to the IO thread instead. */
-    void (*set_volume)(pa_source *s);         /* ditto */
+     * will be sent to the IO thread instead.
+     *
+     * You must use the function pa_source_set_set_volume_callback() to
+     * set this callback. */
+    pa_source_cb_t set_volume; /* may be NULL */
+
+    /* Source drivers that set PA_SOURCE_DEFERRED_VOLUME must provide this
+     * callback. This callback is not used with source that do not set
+     * PA_SOURCE_DEFERRED_VOLUME. This is called from the IO thread when a
+     * pending hardware volume change has to be written to the
+     * hardware. The requested volume is passed to the callback
+     * implementation in s->thread_info.current_hw_volume.
+     *
+     * The call is done inside pa_source_volume_change_apply(), which is
+     * not called automatically - it is the driver's responsibility to
+     * schedule that function to be called at the right times in the
+     * IO thread.
+     *
+     * You must use the function pa_source_set_write_volume_callback() to
+     * set this callback. */
+    pa_source_cb_t write_volume; /* may be NULL */
 
     /* Called when the mute setting is queried. Called from main loop
      * context. If this is NULL a PA_SOURCE_MESSAGE_GET_MUTE message
      * will be sent to the IO thread instead. If refresh_mute is
-     * FALSE neither this function is called nor a message is sent.*/
-    void (*get_mute)(pa_source *s);           /* ditto */
+     * FALSE neither this function is called nor a message is sent.
+     *
+     * You must use the function pa_source_set_get_mute_callback() to
+     * set this callback. */
+    pa_source_cb_t get_mute; /* may be NULL */
 
     /* Called when the mute setting shall be changed. Called from main
      * loop context. If this is NULL a PA_SOURCE_MESSAGE_SET_MUTE
-     * message will be sent to the IO thread instead. */
-    void (*set_mute)(pa_source *s);           /* ditto */
+     * message will be sent to the IO thread instead.
+     *
+     * You must use the function pa_source_set_set_mute_callback() to
+     * set this callback. */
+    pa_source_cb_t set_mute; /* may be NULL */
 
     /* Called when a the requested latency is changed. Called from IO
      * thread context. */
-    void (*update_requested_latency)(pa_source *s); /* ditto */
+    pa_source_cb_t update_requested_latency; /* may be NULL */
 
     /* Called whenever the port shall be changed. Called from main
      * thread. */
@@ -160,6 +200,21 @@ struct pa_source {
         pa_usec_t max_latency; /* An upper limit for the latencies */
 
         pa_usec_t fixed_latency; /* for sources with PA_SOURCE_DYNAMIC_LATENCY this is 0 */
+
+        /* Delayed volume change events are queued here. The events
+         * are stored in expiration order. The one expiring next is in
+         * the head of the list. */
+        PA_LLIST_HEAD(pa_source_volume_change, volume_changes);
+        pa_source_volume_change *volume_changes_tail;
+        /* This value is updated in pa_source_volume_change_apply() and
+         * used only by sources with PA_SOURCE_DEFERRED_VOLUME. */
+        pa_cvolume current_hw_volume;
+
+        /* The amount of usec volume up events are delayed and volume
+         * down events are made earlier. */
+        uint32_t volume_change_safety_margin;
+        /* Usec delay added to all volume change events, may be negative. */
+        int32_t volume_change_extra_delay;
 } thread_info;
 
     void *userdata;
@@ -172,7 +227,10 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_ADD_OUTPUT,
     PA_SOURCE_MESSAGE_REMOVE_OUTPUT,
     PA_SOURCE_MESSAGE_GET_VOLUME,
+    PA_SOURCE_MESSAGE_SET_SHARED_VOLUME,
+    PA_SOURCE_MESSAGE_SET_VOLUME_SYNCED,
     PA_SOURCE_MESSAGE_SET_VOLUME,
+    PA_SOURCE_MESSAGE_SYNC_VOLUMES,
     PA_SOURCE_MESSAGE_GET_MUTE,
     PA_SOURCE_MESSAGE_SET_MUTE,
     PA_SOURCE_MESSAGE_GET_LATENCY,
@@ -186,6 +244,8 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_GET_FIXED_LATENCY,
     PA_SOURCE_MESSAGE_GET_MAX_REWIND,
     PA_SOURCE_MESSAGE_SET_MAX_REWIND,
+    PA_SOURCE_MESSAGE_SET_PORT,
+    PA_SOURCE_MESSAGE_UPDATE_VOLUME_AND_MUTE,
     PA_SOURCE_MESSAGE_MAX
 } pa_source_message_t;
 
@@ -233,6 +293,13 @@ pa_source* pa_source_new(
         pa_source_new_data *data,
         pa_source_flags_t flags);
 
+void pa_source_set_get_volume_callback(pa_source *s, pa_source_cb_t cb);
+void pa_source_set_set_volume_callback(pa_source *s, pa_source_cb_t cb);
+void pa_source_set_write_volume_callback(pa_source *s, pa_source_cb_t cb);
+void pa_source_set_get_mute_callback(pa_source *s, pa_source_cb_t cb);
+void pa_source_set_set_mute_callback(pa_source *s, pa_source_cb_t cb);
+void pa_source_enable_decibel_volume(pa_source *s, pa_bool_t enable);
+
 void pa_source_put(pa_source *s);
 void pa_source_unlink(pa_source *s);
 
@@ -269,11 +336,17 @@ int pa_source_update_status(pa_source*s);
 int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause);
 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause);
 
+/* Use this instead of checking s->flags & PA_SOURCE_FLAT_VOLUME directly. */
+pa_bool_t pa_source_flat_volume_enabled(pa_source *s);
+
 /* Is the source in passthrough mode? (that is, is this a monitor source for a sink
  * that has a passthrough sink input connected to it. */
 pa_bool_t pa_source_is_passthrough(pa_source *s);
+/* These should be called when a source enters/leaves passthrough mode */
+void pa_source_enter_passthrough(pa_source *s);
+void pa_source_leave_passthrough(pa_source *s);
 
-void pa_source_set_volume(pa_source *source, const pa_cvolume *volume, pa_bool_t save);
+void pa_source_set_volume(pa_source *source, const pa_cvolume *volume, pa_bool_t sendmsg, pa_bool_t save);
 const pa_cvolume *pa_source_get_volume(pa_source *source, pa_bool_t force_refresh);
 
 void pa_source_set_mute(pa_source *source, pa_bool_t mute, pa_bool_t save);
@@ -315,6 +388,10 @@ void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind);
 void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency);
 void pa_source_set_fixed_latency_within_thread(pa_source *s, pa_usec_t latency);
 
+void pa_source_update_volume_and_mute(pa_source *s);
+
+pa_bool_t pa_source_volume_change_apply(pa_source *s, pa_usec_t *usec_to_next);
+
 /*** To be called exclusively by source output drivers, from IO context */
 
 void pa_source_invalidate_requested_latency(pa_source *s, pa_bool_t dynamic);