mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-10-29 05:40:23 -04:00 
			
		
		
		
	add support for subscribing to autoload table changes
fix module-combine so that the sample rate of at least one streams is not changed from the original git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@206 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
		
							parent
							
								
									f9e2058820
								
							
						
					
					
						commit
						daf3938a9e
					
				
					 7 changed files with 51 additions and 28 deletions
				
			
		
							
								
								
									
										5
									
								
								doc/todo
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								doc/todo
									
										
									
									
									
								
							|  | @ -1,9 +1,8 @@ | ||||||
| *** $Id$ *** | *** $Id$ *** | ||||||
| 
 | 
 | ||||||
| *** 0.5 *** | *** 0.5 *** | ||||||
| - more complete pactl | - more complete pactl/parec | ||||||
| - fix tcp/native | - fix tcp/native in regard to latencies | ||||||
| - paman: add support for killing sink inputs, source outputs, clients |  | ||||||
| - add client config file | - add client config file | ||||||
| - remove autospawn stuff in conf.c | - remove autospawn stuff in conf.c | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,9 +34,11 @@ | ||||||
| #include "sound-file.h" | #include "sound-file.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
| #include "scache.h" | #include "scache.h" | ||||||
|  | #include "subscribe.h" | ||||||
| 
 | 
 | ||||||
| static void entry_free(struct pa_autoload_entry *e) { | static void entry_free(struct pa_autoload_entry *e) { | ||||||
|     assert(e); |     assert(e); | ||||||
|  |     pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_REMOVE, PA_INVALID_INDEX); | ||||||
|     pa_xfree(e->name); |     pa_xfree(e->name); | ||||||
|     pa_xfree(e->module); |     pa_xfree(e->module); | ||||||
|     pa_xfree(e->argument); |     pa_xfree(e->argument); | ||||||
|  | @ -51,6 +53,7 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) | ||||||
|         return NULL; |         return NULL; | ||||||
|      |      | ||||||
|     e = pa_xmalloc(sizeof(struct pa_autoload_entry)); |     e = pa_xmalloc(sizeof(struct pa_autoload_entry)); | ||||||
|  |     e->core = c; | ||||||
|     e->name = pa_xstrdup(name); |     e->name = pa_xstrdup(name); | ||||||
|     e->module = e->argument = NULL; |     e->module = e->argument = NULL; | ||||||
|     e->in_action = 0; |     e->in_action = 0; | ||||||
|  | @ -61,6 +64,8 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) | ||||||
|      |      | ||||||
|     pa_hashmap_put(c->autoload_hashmap, e->name, e); |     pa_hashmap_put(c->autoload_hashmap, e->name, e); | ||||||
| 
 | 
 | ||||||
|  |     pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, PA_INVALID_INDEX); | ||||||
|  |      | ||||||
|     return e; |     return e; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ | ||||||
| #include "namereg.h" | #include "namereg.h" | ||||||
| 
 | 
 | ||||||
| struct pa_autoload_entry { | struct pa_autoload_entry { | ||||||
|  |     struct pa_core *core; | ||||||
|     char *name; |     char *name; | ||||||
|     enum pa_namereg_type type; |     enum pa_namereg_type type; | ||||||
|     int in_action; |     int in_action; | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ | ||||||
| PA_MODULE_AUTHOR("Lennart Poettering") | PA_MODULE_AUTHOR("Lennart Poettering") | ||||||
| PA_MODULE_DESCRIPTION("Combine multiple sinks to one") | PA_MODULE_DESCRIPTION("Combine multiple sinks to one") | ||||||
| PA_MODULE_VERSION(PACKAGE_VERSION) | PA_MODULE_VERSION(PACKAGE_VERSION) | ||||||
| PA_MODULE_USAGE("sink_name=<name for the sink> master=<master sink> slave=<slave sinks> adjust_time") | PA_MODULE_USAGE("sink_name=<name for the sink> master=<master sink> slave=<slave sinks> adjust_time=<seconds>") | ||||||
| 
 | 
 | ||||||
| #define DEFAULT_SINK_NAME "combined" | #define DEFAULT_SINK_NAME "combined" | ||||||
| #define MEMBLOCKQ_MAXLENGTH (1024*170) | #define MEMBLOCKQ_MAXLENGTH (1024*170) | ||||||
|  | @ -61,7 +61,7 @@ struct output { | ||||||
|     struct pa_sink_input *sink_input; |     struct pa_sink_input *sink_input; | ||||||
|     size_t counter; |     size_t counter; | ||||||
|     struct pa_memblockq *memblockq; |     struct pa_memblockq *memblockq; | ||||||
|     pa_usec_t sink_latency; |     pa_usec_t total_latency; | ||||||
|     PA_LLIST_FIELDS(struct output); |     PA_LLIST_FIELDS(struct output); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -89,38 +89,44 @@ static void update_usage(struct userdata *u) { | ||||||
| 
 | 
 | ||||||
| static void adjust_rates(struct userdata *u) { | static void adjust_rates(struct userdata *u) { | ||||||
|     struct output *o; |     struct output *o; | ||||||
|     pa_usec_t max  = 0; |     pa_usec_t max_sink_latency = 0, min_total_latency = (pa_usec_t) -1, target_latency; | ||||||
|     uint32_t base_rate; |     uint32_t base_rate; | ||||||
|     assert(u && u->sink); |     assert(u && u->sink); | ||||||
| 
 | 
 | ||||||
|     for (o = u->outputs; o; o = o->next) { |     for (o = u->outputs; o; o = o->next) { | ||||||
|         o->sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0; |         uint32_t sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0; | ||||||
|  |          | ||||||
|  |         o->total_latency = sink_latency + pa_sink_input_get_latency(o->sink_input); | ||||||
|  |          | ||||||
|  |         if (sink_latency > max_sink_latency) | ||||||
|  |             max_sink_latency = sink_latency; | ||||||
| 
 | 
 | ||||||
|         if (o->sink_latency > max) |         if (o->total_latency < min_total_latency) | ||||||
|             max = o->sink_latency; |             min_total_latency = o->total_latency; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pa_log(__FILE__": [%s] maximum latency is %0.0f usec.\n", u->sink->name, (float) max); |     assert(max_sink_latency > 0 && min_total_latency != (pa_usec_t) -1); | ||||||
|  | 
 | ||||||
|  |     target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; | ||||||
|  |      | ||||||
|  |     pa_log(__FILE__": [%s] target latency is %0.0f usec.\n", u->sink->name, (float) target_latency); | ||||||
| 
 | 
 | ||||||
|     base_rate = u->sink->sample_spec.rate; |     base_rate = u->sink->sample_spec.rate; | ||||||
| 
 | 
 | ||||||
|     for (o = u->outputs; o; o = o->next) { |     for (o = u->outputs; o; o = o->next) { | ||||||
|         pa_usec_t l; |  | ||||||
|         uint32_t r = base_rate; |         uint32_t r = base_rate; | ||||||
| 
 | 
 | ||||||
|         l = o->sink_latency + pa_sink_input_get_latency(o->sink_input); |         if (o->total_latency < target_latency) | ||||||
| 
 |             r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/ 1000000); | ||||||
|         if (l < max) |         else if (o->total_latency > target_latency) | ||||||
|             r -= (uint32_t) (((((double) max-l))/u->adjust_time)*r/ 1000000); |             r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000); | ||||||
|         else if (l > max) |  | ||||||
|             r += (uint32_t) (((((double) l-max))/u->adjust_time)*r/ 1000000); |  | ||||||
| 
 | 
 | ||||||
|         if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) |         if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) | ||||||
|             pa_log(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); |             pa_log(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); | ||||||
|         else |         else { | ||||||
|             pa_log(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) l); |             pa_log(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); | ||||||
|          |             pa_sink_input_set_rate(o->sink_input, r); | ||||||
|         pa_sink_input_set_rate(o->sink_input, r); |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -108,7 +108,8 @@ enum pa_subscription_mask { | ||||||
|     PA_SUBSCRIPTION_MASK_MODULE = 16,            /**< Module events */ |     PA_SUBSCRIPTION_MASK_MODULE = 16,            /**< Module events */ | ||||||
|     PA_SUBSCRIPTION_MASK_CLIENT = 32,            /**< Client events */ |     PA_SUBSCRIPTION_MASK_CLIENT = 32,            /**< Client events */ | ||||||
|     PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64,      /**< Sample cache events */ |     PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64,      /**< Sample cache events */ | ||||||
|     PA_SUBSCRIPTION_MASK_SERVER = 128            /**< Other global server changes. \since 0.4 */ |     PA_SUBSCRIPTION_MASK_SERVER = 128,           /**< Other global server changes. \since 0.4 */ | ||||||
|  |     PA_SUBSCRIPTION_MASK_AUTOLOAD = 256          /**< Autoload table events. \since 0.5 */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Subscription event types, as used by pa_context_subscribe() */ | /** Subscription event types, as used by pa_context_subscribe() */ | ||||||
|  | @ -121,7 +122,8 @@ enum pa_subscription_event_type { | ||||||
|     PA_SUBSCRIPTION_EVENT_CLIENT = 5,         /**< Event type: Client */ |     PA_SUBSCRIPTION_EVENT_CLIENT = 5,         /**< Event type: Client */ | ||||||
|     PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6,   /**< Event type: Sample cache item */ |     PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6,   /**< Event type: Sample cache item */ | ||||||
|     PA_SUBSCRIPTION_EVENT_SERVER = 7,         /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. \since 0.4  */ |     PA_SUBSCRIPTION_EVENT_SERVER = 7,         /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. \since 0.4  */ | ||||||
|     PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7,  /**< A mask to extract the event type from an event value */ |     PA_SUBSCRIPTION_EVENT_AUTOLOAD = 8,       /**< Event type: Autoload table changes. \since 0.5 */ | ||||||
|  |     PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 15, /**< A mask to extract the event type from an event value */ | ||||||
| 
 | 
 | ||||||
|     PA_SUBSCRIPTION_EVENT_NEW = 0,            /**< A new object was created */ |     PA_SUBSCRIPTION_EVENT_NEW = 0,            /**< A new object was created */ | ||||||
|     PA_SUBSCRIPTION_EVENT_CHANGE = 16,        /**< A property of the object was modified */ |     PA_SUBSCRIPTION_EVENT_CHANGE = 16,        /**< A property of the object was modified */ | ||||||
|  |  | ||||||
|  | @ -101,6 +101,10 @@ static void do_read(struct pa_pstream *p); | ||||||
| 
 | 
 | ||||||
| static void do_something(struct pa_pstream *p) { | static void do_something(struct pa_pstream *p) { | ||||||
|     assert(p); |     assert(p); | ||||||
|  | 
 | ||||||
|  |     if (p->dead) | ||||||
|  |         return; | ||||||
|  |      | ||||||
|     p->mainloop->defer_enable(p->defer_event, 0); |     p->mainloop->defer_enable(p->defer_event, 0); | ||||||
| 
 | 
 | ||||||
|     pa_pstream_ref(p); |     pa_pstream_ref(p); | ||||||
|  | @ -213,8 +217,11 @@ static void pstream_free(struct pa_pstream *p) { | ||||||
| 
 | 
 | ||||||
| void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { | void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { | ||||||
|     struct item_info *i; |     struct item_info *i; | ||||||
|     assert(p && packet); |     assert(p && packet && p->ref >= 1); | ||||||
| 
 | 
 | ||||||
|  |     if (p->dead) | ||||||
|  |         return; | ||||||
|  |      | ||||||
| /*     pa_log(__FILE__": push-packet %p\n", packet); */ | /*     pa_log(__FILE__": push-packet %p\n", packet); */ | ||||||
|      |      | ||||||
|     i = pa_xmalloc(sizeof(struct item_info)); |     i = pa_xmalloc(sizeof(struct item_info)); | ||||||
|  | @ -227,8 +234,11 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { | ||||||
| 
 | 
 | ||||||
| void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk) { | void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk) { | ||||||
|     struct item_info *i; |     struct item_info *i; | ||||||
|     assert(p && channel != (uint32_t) -1 && chunk); |     assert(p && channel != (uint32_t) -1 && chunk && p->ref >= 1); | ||||||
| 
 | 
 | ||||||
|  |     if (p->dead) | ||||||
|  |         return; | ||||||
|  |      | ||||||
| /*     pa_log(__FILE__": push-memblock %p\n", chunk); */ | /*     pa_log(__FILE__": push-memblock %p\n", chunk); */ | ||||||
|      |      | ||||||
|     i = pa_xmalloc(sizeof(struct item_info)); |     i = pa_xmalloc(sizeof(struct item_info)); | ||||||
|  |  | ||||||
|  | @ -121,11 +121,11 @@ double pa_volume_to_dB(pa_volume_t v) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void pa_bytes_snprint(char *s, size_t l, off_t v) { | void pa_bytes_snprint(char *s, size_t l, off_t v) { | ||||||
|     if (v >= 1024*1024*1024) |     if (v >= (off_t) 1024*1024*1024) | ||||||
|         snprintf(s, l, "%0.1f GB", (double) v/1024/1024/1024); |         snprintf(s, l, "%0.1f GB", (double) v/1024/1024/1024); | ||||||
|     else if (v >= 1024*1024) |     else if (v >= (off_t) 1024*1024) | ||||||
|         snprintf(s, l, "%0.1f MB", (double) v/1024/1024); |         snprintf(s, l, "%0.1f MB", (double) v/1024/1024); | ||||||
|     else if (v >= 1024) |     else if (v >= (off_t) 1024) | ||||||
|         snprintf(s, l, "%0.1f KB", (double) v/1024); |         snprintf(s, l, "%0.1f KB", (double) v/1024); | ||||||
|     else |     else | ||||||
|         snprintf(s, l, "%u B", (unsigned) v); |         snprintf(s, l, "%u B", (unsigned) v); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lennart Poettering
						Lennart Poettering