mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	revive howl support
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@566 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
		
							parent
							
								
									361f16718f
								
							
						
					
					
						commit
						7f68c913f1
					
				
					 6 changed files with 126 additions and 106 deletions
				
			
		| 
						 | 
					@ -29,7 +29,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define HOWL_PROPERTY "howl"
 | 
					#define HOWL_PROPERTY "howl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_howl_wrapper {
 | 
					struct pa_howl_wrapper {
 | 
				
			||||||
    pa_core *core;
 | 
					    pa_core *core;
 | 
				
			||||||
    int ref;
 | 
					    int ref;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ pa_howl_wrapper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
 | 
					static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
 | 
				
			||||||
    pa_howl_wrapper *w = userdata;
 | 
					    pa_howl_wrapper *w = userdata;
 | 
				
			||||||
    assert(m && e && fd >= 0 && w && w->ref >= 1);
 | 
					    assert(m && e && fd >= 0 && w && w->ref >= 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <polypcore/core.h>
 | 
					#include <polypcore/core.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_howl_wrapper;
 | 
					typedef struct pa_howl_wrapper pa_howl_wrapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_howl_wrapper* pa_howl_wrapper_get(pa_core *c);
 | 
					pa_howl_wrapper* pa_howl_wrapper_get(pa_core *c);
 | 
				
			||||||
pa_howl_wrapper* pa_howl_wrapper_ref(pa_howl_wrapper *h);
 | 
					pa_howl_wrapper* pa_howl_wrapper_ref(pa_howl_wrapper *h);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,13 +67,13 @@ struct service {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        int valid;
 | 
					        int valid;
 | 
				
			||||||
        pa_namereg_type type;
 | 
					        pa_namereg_type_t type;
 | 
				
			||||||
        uint32_t index;
 | 
					        uint32_t index;
 | 
				
			||||||
    } loaded;
 | 
					    } loaded;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        int valid;
 | 
					        int valid;
 | 
				
			||||||
        pa_namereg_type type;
 | 
					        pa_namereg_type_t type;
 | 
				
			||||||
        uint32_t index;
 | 
					        uint32_t index;
 | 
				
			||||||
    } autoload;
 | 
					    } autoload;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -93,21 +93,19 @@ static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_stat
 | 
				
			||||||
    return SW_OKAY;
 | 
					    return SW_OKAY;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description, pa_typeid_t *ret_typeid) {
 | 
					static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description) {
 | 
				
			||||||
    assert(u && s && s->loaded.valid && ret_ss && ret_description && ret_typeid);
 | 
					    assert(u && s && s->loaded.valid && ret_ss && ret_description);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->loaded.type == PA_NAMEREG_SINK) {
 | 
					    if (s->loaded.type == PA_NAMEREG_SINK) {
 | 
				
			||||||
        pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index);
 | 
					        pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index);
 | 
				
			||||||
        assert(sink);
 | 
					        assert(sink);
 | 
				
			||||||
        *ret_ss = sink->sample_spec;
 | 
					        *ret_ss = sink->sample_spec;
 | 
				
			||||||
        *ret_description = sink->description;
 | 
					        *ret_description = sink->description;
 | 
				
			||||||
        *ret_typeid = sink->typeid;
 | 
					 | 
				
			||||||
    } else if (s->loaded.type == PA_NAMEREG_SOURCE) {
 | 
					    } else if (s->loaded.type == PA_NAMEREG_SOURCE) {
 | 
				
			||||||
        pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index);
 | 
					        pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index);
 | 
				
			||||||
        assert(source);
 | 
					        assert(source);
 | 
				
			||||||
        *ret_ss = source->sample_spec;
 | 
					        *ret_ss = source->sample_spec;
 | 
				
			||||||
        *ret_description = source->description;
 | 
					        *ret_description = source->description;
 | 
				
			||||||
        *ret_typeid = source->typeid;
 | 
					 | 
				
			||||||
    } else
 | 
					    } else
 | 
				
			||||||
        assert(0);
 | 
					        assert(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -154,10 +152,9 @@ static int publish_service(struct userdata *u, struct service *s) {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (s->loaded.valid) {
 | 
					    if (s->loaded.valid) {
 | 
				
			||||||
        char z[64], *description;
 | 
					        char z[64], *description;
 | 
				
			||||||
        pa_typeid_t typeid;
 | 
					 | 
				
			||||||
        pa_sample_spec ss;
 | 
					        pa_sample_spec ss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        get_service_data(u, s, &ss, &description, &typeid);
 | 
					        get_service_data(u, s, &ss, &description);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        snprintf(z, sizeof(z), "%u", ss.rate);
 | 
					        snprintf(z, sizeof(z), "%u", ss.rate);
 | 
				
			||||||
        sw_text_record_add_key_and_string_value(txt, "rate", z);
 | 
					        sw_text_record_add_key_and_string_value(txt, "rate", z);
 | 
				
			||||||
| 
						 | 
					@ -167,10 +164,6 @@ static int publish_service(struct userdata *u, struct service *s) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sw_text_record_add_key_and_string_value(txt, "description", description);
 | 
					        sw_text_record_add_key_and_string_value(txt, "description", description);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        snprintf(z, sizeof(z), "0x%8x", typeid);
 | 
					 | 
				
			||||||
        sw_text_record_add_key_and_string_value(txt, "typeid", z);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t,
 | 
					        if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t,
 | 
				
			||||||
                                 s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE,
 | 
					                                 s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE,
 | 
				
			||||||
                                 NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt),
 | 
					                                 NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt),
 | 
				
			||||||
| 
						 | 
					@ -210,7 +203,7 @@ finish:
 | 
				
			||||||
    return r;
 | 
					    return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct service *get_service(struct userdata *u, const char *name) {
 | 
					static struct service *get_service(struct userdata *u, const char *name) {
 | 
				
			||||||
    struct service *s;
 | 
					    struct service *s;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if ((s = pa_hashmap_get(u->services, name)))
 | 
					    if ((s = pa_hashmap_get(u->services, name)))
 | 
				
			||||||
| 
						 | 
					@ -277,55 +270,55 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
 | 
				
			||||||
    return publish_service(u, svc);
 | 
					    return publish_service(u, svc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int remove_sink(struct userdata *u, uint32_t index) {
 | 
					static int remove_sink(struct userdata *u, uint32_t idx) {
 | 
				
			||||||
    struct service *svc;
 | 
					    struct service *svc;
 | 
				
			||||||
    assert(u && index != PA_INVALID_INDEX);
 | 
					    assert(u && idx != PA_INVALID_INDEX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(svc = pa_dynarray_get(u->sink_dynarray, index)))
 | 
					    if (!(svc = pa_dynarray_get(u->sink_dynarray, idx)))
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SINK)
 | 
					    if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SINK)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    svc->loaded.valid = 0;
 | 
					    svc->loaded.valid = 0;
 | 
				
			||||||
    pa_dynarray_put(u->sink_dynarray, index, NULL);
 | 
					    pa_dynarray_put(u->sink_dynarray, idx, NULL);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return publish_service(u, svc);
 | 
					    return publish_service(u, svc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int remove_source(struct userdata *u, uint32_t index) {
 | 
					static int remove_source(struct userdata *u, uint32_t idx) {
 | 
				
			||||||
    struct service *svc;
 | 
					    struct service *svc;
 | 
				
			||||||
    assert(u && index != PA_INVALID_INDEX);
 | 
					    assert(u && idx != PA_INVALID_INDEX);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (!(svc = pa_dynarray_get(u->source_dynarray, index)))
 | 
					    if (!(svc = pa_dynarray_get(u->source_dynarray, idx)))
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE)
 | 
					    if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    svc->loaded.valid = 0;
 | 
					    svc->loaded.valid = 0;
 | 
				
			||||||
    pa_dynarray_put(u->source_dynarray, index, NULL);
 | 
					    pa_dynarray_put(u->source_dynarray, idx, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return publish_service(u, svc);
 | 
					    return publish_service(u, svc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int remove_autoload(struct userdata *u, uint32_t index) {
 | 
					static int remove_autoload(struct userdata *u, uint32_t idx) {
 | 
				
			||||||
    struct service *svc;
 | 
					    struct service *svc;
 | 
				
			||||||
    assert(u && index != PA_INVALID_INDEX);
 | 
					    assert(u && idx != PA_INVALID_INDEX);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (!(svc = pa_dynarray_get(u->autoload_dynarray, index)))
 | 
					    if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx)))
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!svc->autoload.valid)
 | 
					    if (!svc->autoload.valid)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    svc->autoload.valid = 0;
 | 
					    svc->autoload.valid = 0;
 | 
				
			||||||
    pa_dynarray_put(u->autoload_dynarray, index, NULL);
 | 
					    pa_dynarray_put(u->autoload_dynarray, idx, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return publish_service(u, svc);
 | 
					    return publish_service(u, svc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata) {
 | 
					static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
 | 
				
			||||||
    struct userdata *u = userdata;
 | 
					    struct userdata *u = userdata;
 | 
				
			||||||
    assert(u && c);
 | 
					    assert(u && c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -334,12 +327,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_
 | 
				
			||||||
            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
 | 
					            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
 | 
				
			||||||
                pa_sink *sink;
 | 
					                pa_sink *sink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ((sink = pa_idxset_get_by_index(c->sinks, index))) {
 | 
					                if ((sink = pa_idxset_get_by_index(c->sinks, idx))) {
 | 
				
			||||||
                    if (publish_sink(u, sink) < 0)
 | 
					                    if (publish_sink(u, sink) < 0)
 | 
				
			||||||
                        goto fail;
 | 
					                        goto fail;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
 | 
					            } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
 | 
				
			||||||
                if (remove_sink(u, index) < 0)
 | 
					                if (remove_sink(u, idx) < 0)
 | 
				
			||||||
                    goto fail;
 | 
					                    goto fail;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -350,12 +343,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_
 | 
				
			||||||
            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
 | 
					            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
 | 
				
			||||||
                pa_source *source;
 | 
					                pa_source *source;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                if ((source = pa_idxset_get_by_index(c->sources, index))) {
 | 
					                if ((source = pa_idxset_get_by_index(c->sources, idx))) {
 | 
				
			||||||
                    if (publish_source(u, source) < 0)
 | 
					                    if (publish_source(u, source) < 0)
 | 
				
			||||||
                        goto fail;
 | 
					                        goto fail;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
 | 
					            } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
 | 
				
			||||||
                if (remove_source(u, index) < 0)
 | 
					                if (remove_source(u, idx) < 0)
 | 
				
			||||||
                    goto fail;
 | 
					                    goto fail;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
| 
						 | 
					@ -365,12 +358,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_
 | 
				
			||||||
            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
 | 
					            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
 | 
				
			||||||
                pa_autoload_entry *autoload;
 | 
					                pa_autoload_entry *autoload;
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, index))) {
 | 
					                if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, idx))) {
 | 
				
			||||||
                    if (publish_autoload(u, autoload) < 0)
 | 
					                    if (publish_autoload(u, autoload) < 0)
 | 
				
			||||||
                        goto fail;
 | 
					                        goto fail;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
 | 
					            } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
 | 
				
			||||||
                if (remove_autoload(u, index) < 0)
 | 
					                if (remove_autoload(u, idx) < 0)
 | 
				
			||||||
                        goto fail;
 | 
					                        goto fail;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
| 
						 | 
					@ -388,7 +381,7 @@ fail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa__init(pa_core *c, pa_module*m) {
 | 
					int pa__init(pa_core *c, pa_module*m) {
 | 
				
			||||||
    struct userdata *u;
 | 
					    struct userdata *u;
 | 
				
			||||||
    uint32_t index, port = PA_NATIVE_DEFAULT_PORT;
 | 
					    uint32_t idx, port = PA_NATIVE_DEFAULT_PORT;
 | 
				
			||||||
    pa_sink *sink;
 | 
					    pa_sink *sink;
 | 
				
			||||||
    pa_source *source;
 | 
					    pa_source *source;
 | 
				
			||||||
    pa_autoload_entry *autoload;
 | 
					    pa_autoload_entry *autoload;
 | 
				
			||||||
| 
						 | 
					@ -424,16 +417,16 @@ int pa__init(pa_core *c, pa_module*m) {
 | 
				
			||||||
                                          PA_SUBSCRIPTION_MASK_SOURCE|
 | 
					                                          PA_SUBSCRIPTION_MASK_SOURCE|
 | 
				
			||||||
                                          PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u);
 | 
					                                          PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index))
 | 
					    for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx))
 | 
				
			||||||
        if (publish_sink(u, sink) < 0)
 | 
					        if (publish_sink(u, sink) < 0)
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index))
 | 
					    for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx))
 | 
				
			||||||
        if (publish_source(u, source) < 0)
 | 
					        if (publish_source(u, source) < 0)
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c->autoload_idxset)
 | 
					    if (c->autoload_idxset)
 | 
				
			||||||
        for (autoload = pa_idxset_first(c->autoload_idxset, &index); autoload; autoload = pa_idxset_next(c->autoload_idxset, &index))
 | 
					        for (autoload = pa_idxset_first(c->autoload_idxset, &idx); autoload; autoload = pa_idxset_next(c->autoload_idxset, &idx))
 | 
				
			||||||
            if (publish_autoload(u, autoload) < 0)
 | 
					            if (publish_autoload(u, autoload) < 0)
 | 
				
			||||||
                goto fail;
 | 
					                goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,19 +32,18 @@
 | 
				
			||||||
#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp."
 | 
					#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp."
 | 
				
			||||||
#define SERVICE_NAME_SERVER "_polypaudio-server._tcp."
 | 
					#define SERVICE_NAME_SERVER "_polypaudio-server._tcp."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_browser {
 | 
					struct pa_browser {
 | 
				
			||||||
    int ref;
 | 
					    int ref;
 | 
				
			||||||
    pa_mainloop_api *mainloop;
 | 
					    pa_mainloop_api *mainloop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void (*callback)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void *userdata);
 | 
					    pa_browse_cb_t callback;
 | 
				
			||||||
    void *callback_userdata;
 | 
					    void *userdata;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    sw_discovery discovery;
 | 
					    sw_discovery discovery;
 | 
				
			||||||
    pa_io_event *io_event;
 | 
					    pa_io_event *io_event;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t events, void *userdata) {
 | 
				
			||||||
static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags events, void *userdata) {
 | 
					 | 
				
			||||||
    pa_browser *b = userdata;
 | 
					    pa_browser *b = userdata;
 | 
				
			||||||
    assert(a && b && b->mainloop == a);
 | 
					    assert(a && b && b->mainloop == a);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +55,35 @@ static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_fl
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int type_equal(const char *a, const char *b) {
 | 
				
			||||||
 | 
					    size_t la, lb;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (strcasecmp(a, b) == 0)
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    la = strlen(a);
 | 
				
			||||||
 | 
					    lb = strlen(b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (la > 0 && a[la-1] == '.' && la == lb+1 && strncasecmp(a, b, la-1) == 0)
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					                                            
 | 
				
			||||||
 | 
					    if (lb > 0 && b[lb-1] == '.' && lb == la+1 && strncasecmp(a, b, lb-1) == 0)
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int map_to_opcode(const char *type, int new) {
 | 
				
			||||||
 | 
					    if (type_equal(type, SERVICE_NAME_SINK))
 | 
				
			||||||
 | 
					        return new ? PA_BROWSE_NEW_SINK : PA_BROWSE_REMOVE_SINK;
 | 
				
			||||||
 | 
					    else if (type_equal(type, SERVICE_NAME_SOURCE))
 | 
				
			||||||
 | 
					        return new ? PA_BROWSE_NEW_SOURCE : PA_BROWSE_REMOVE_SOURCE;
 | 
				
			||||||
 | 
					    else if (type_equal(type, SERVICE_NAME_SERVER))
 | 
				
			||||||
 | 
					        return new ? PA_BROWSE_NEW_SERVER : PA_BROWSE_REMOVE_SERVER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static sw_result resolve_reply(
 | 
					static sw_result resolve_reply(
 | 
				
			||||||
        sw_discovery discovery,
 | 
					        sw_discovery discovery,
 | 
				
			||||||
        sw_discovery_oid oid,
 | 
					        sw_discovery_oid oid,
 | 
				
			||||||
| 
						 | 
					@ -72,10 +100,9 @@ static sw_result resolve_reply(
 | 
				
			||||||
    pa_browser *b = extra;
 | 
					    pa_browser *b = extra;
 | 
				
			||||||
    pa_browse_info i;
 | 
					    pa_browse_info i;
 | 
				
			||||||
    char ip[256], a[256];
 | 
					    char ip[256], a[256];
 | 
				
			||||||
    pa_browse_opcode opcode;
 | 
					    int opcode;
 | 
				
			||||||
    int device_found = 0;
 | 
					    int device_found = 0;
 | 
				
			||||||
    uint32_t cookie;
 | 
					    uint32_t cookie;
 | 
				
			||||||
    pa_typeid_t typeid;
 | 
					 | 
				
			||||||
    pa_sample_spec ss;
 | 
					    pa_sample_spec ss;
 | 
				
			||||||
    int ss_valid = 0;
 | 
					    int ss_valid = 0;
 | 
				
			||||||
    sw_text_record_iterator iterator;
 | 
					    sw_text_record_iterator iterator;
 | 
				
			||||||
| 
						 | 
					@ -92,15 +119,8 @@ static sw_result resolve_reply(
 | 
				
			||||||
    if (!b->callback)
 | 
					    if (!b->callback)
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!strcmp(type, SERVICE_NAME_SINK))
 | 
					    opcode = map_to_opcode(type, 1);
 | 
				
			||||||
        opcode = PA_BROWSE_NEW_SINK;
 | 
					    assert(opcode >= 0);
 | 
				
			||||||
    else if (!strcmp(type, SERVICE_NAME_SOURCE))
 | 
					 | 
				
			||||||
        opcode = PA_BROWSE_NEW_SOURCE;
 | 
					 | 
				
			||||||
    else if (!strcmp(type, SERVICE_NAME_SERVER))
 | 
					 | 
				
			||||||
        opcode = PA_BROWSE_NEW_SERVER;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        goto fail;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    snprintf(a, sizeof(a), "tcp:%s:%u", sw_ipv4_address_name(address, ip, sizeof(ip)), port);
 | 
					    snprintf(a, sizeof(a), "tcp:%s:%u", sw_ipv4_address_name(address, ip, sizeof(ip)), port);
 | 
				
			||||||
    i.server = a;
 | 
					    i.server = a;
 | 
				
			||||||
| 
						 | 
					@ -154,12 +174,6 @@ static sw_result resolve_reply(
 | 
				
			||||||
                pa_xfree((char*) i.description);
 | 
					                pa_xfree((char*) i.description);
 | 
				
			||||||
                i.description = c;
 | 
					                i.description = c;
 | 
				
			||||||
                c = NULL;
 | 
					                c = NULL;
 | 
				
			||||||
            } else if (!strcmp(key, "typeid")) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (pa_atou(c, &typeid) < 0)
 | 
					 | 
				
			||||||
                    goto fail;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                i.typeid = &typeid;
 | 
					 | 
				
			||||||
            } else if (!strcmp(key, "channels")) {
 | 
					            } else if (!strcmp(key, "channels")) {
 | 
				
			||||||
                uint32_t ch;
 | 
					                uint32_t ch;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
| 
						 | 
					@ -195,7 +209,7 @@ static sw_result resolve_reply(
 | 
				
			||||||
        i.sample_spec = &ss;
 | 
					        i.sample_spec = &ss;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    b->callback(b, opcode, &i, b->callback_userdata);
 | 
					    b->callback(b, opcode, &i, b->userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
    pa_xfree((void*) i.device);
 | 
					    pa_xfree((void*) i.device);
 | 
				
			||||||
| 
						 | 
					@ -238,9 +252,15 @@ static sw_result browse_reply(
 | 
				
			||||||
        case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
 | 
					        case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
 | 
				
			||||||
            if (b->callback) {
 | 
					            if (b->callback) {
 | 
				
			||||||
                pa_browse_info i;
 | 
					                pa_browse_info i;
 | 
				
			||||||
 | 
					                int opcode;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
                memset(&i, 0, sizeof(i));
 | 
					                memset(&i, 0, sizeof(i));
 | 
				
			||||||
                i.name = name;
 | 
					                i.name = name;
 | 
				
			||||||
                b->callback(b, PA_BROWSE_REMOVE, &i, b->callback_userdata);
 | 
					
 | 
				
			||||||
 | 
					                opcode = map_to_opcode(type, 0);
 | 
				
			||||||
 | 
					                assert(opcode >= 0);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                b->callback(b, opcode, &i, b->userdata);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,11 +275,11 @@ pa_browser *pa_browser_new(pa_mainloop_api *mainloop) {
 | 
				
			||||||
    pa_browser *b;
 | 
					    pa_browser *b;
 | 
				
			||||||
    sw_discovery_oid oid;
 | 
					    sw_discovery_oid oid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    b = pa_xmalloc(sizeof(pa_browser));
 | 
					    b = pa_xnew(pa_browser, 1);
 | 
				
			||||||
    b->mainloop = mainloop;
 | 
					    b->mainloop = mainloop;
 | 
				
			||||||
    b->ref = 1;
 | 
					    b->ref = 1;
 | 
				
			||||||
    b->callback = NULL;
 | 
					    b->callback = NULL;
 | 
				
			||||||
    b->callback_userdata = NULL;
 | 
					    b->userdata = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (sw_discovery_init(&b->discovery) != SW_OKAY) {
 | 
					    if (sw_discovery_init(&b->discovery) != SW_OKAY) {
 | 
				
			||||||
        pa_log("sw_discovery_init() failed.\n");
 | 
					        pa_log("sw_discovery_init() failed.\n");
 | 
				
			||||||
| 
						 | 
					@ -305,9 +325,9 @@ void pa_browser_unref(pa_browser *b) {
 | 
				
			||||||
        browser_free(b);
 | 
					        browser_free(b);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_browser_set_callback(pa_browser *b, void (*cb)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void* userdata), void *userdata) {
 | 
					void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) {
 | 
				
			||||||
    assert(b);
 | 
					    assert(b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    b->callback = cb;
 | 
					    b->callback = cb;
 | 
				
			||||||
    b->callback_userdata = userdata;
 | 
					    b->userdata = userdata;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,24 +24,27 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <polyp/mainloop-api.h>
 | 
					#include <polyp/mainloop-api.h>
 | 
				
			||||||
#include <polyp/sample.h>
 | 
					#include <polyp/sample.h>
 | 
				
			||||||
 | 
					#include <polyp/channelmap.h>
 | 
				
			||||||
#include <polyp/cdecl.h>
 | 
					#include <polyp/cdecl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PA_C_DECL_BEGIN
 | 
					PA_C_DECL_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_browser;
 | 
					typedef struct pa_browser pa_browser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_browse_opcode {
 | 
					typedef enum pa_browse_opcode {
 | 
				
			||||||
    PA_BROWSE_NEW_SERVER,
 | 
					    PA_BROWSE_NEW_SERVER = 0,
 | 
				
			||||||
    PA_BROWSE_NEW_SINK,
 | 
					    PA_BROWSE_NEW_SINK,
 | 
				
			||||||
    PA_BROWSE_NEW_SOURCE,
 | 
					    PA_BROWSE_NEW_SOURCE,
 | 
				
			||||||
    PA_BROWSE_REMOVE
 | 
					    PA_BROWSE_REMOVE_SERVER,
 | 
				
			||||||
};
 | 
					    PA_BROWSE_REMOVE_SINK,
 | 
				
			||||||
 | 
					    PA_BROWSE_REMOVE_SOURCE
 | 
				
			||||||
 | 
					} pa_browse_opcode_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_browser *pa_browser_new(pa_mainloop_api *mainloop);
 | 
					pa_browser *pa_browser_new(pa_mainloop_api *mainloop);
 | 
				
			||||||
pa_browser *pa_browser_ref(pa_browser *z);
 | 
					pa_browser *pa_browser_ref(pa_browser *z);
 | 
				
			||||||
void pa_browser_unref(pa_browser *z);
 | 
					void pa_browser_unref(pa_browser *z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_browse_info {
 | 
					typedef struct pa_browse_info {
 | 
				
			||||||
    /* Unique service name */
 | 
					    /* Unique service name */
 | 
				
			||||||
    const char *name;  /* always available */
 | 
					    const char *name;  /* always available */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,11 +56,12 @@ pa_browse_info {
 | 
				
			||||||
    /* Device info */
 | 
					    /* Device info */
 | 
				
			||||||
    const char *device; /* always available when this information is of a sink/source */
 | 
					    const char *device; /* always available when this information is of a sink/source */
 | 
				
			||||||
    const char *description;  /* optional */
 | 
					    const char *description;  /* optional */
 | 
				
			||||||
    const pa_typeid_t *typeid;  /* optional */
 | 
					 | 
				
			||||||
    const pa_sample_spec *sample_spec;  /* optional */
 | 
					    const pa_sample_spec *sample_spec;  /* optional */
 | 
				
			||||||
};
 | 
					} pa_browse_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_browser_set_callback(pa_browser *z, void (*cb)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void *userdata), void *userdata);
 | 
					typedef void (*pa_browse_cb_t)(pa_browser *z, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pa_browser_set_callback(pa_browser *z, pa_browse_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PA_C_DECL_END
 | 
					PA_C_DECL_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,26 +55,21 @@ static void dump_server(const pa_browse_info *i) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dump_device(const pa_browse_info *i) {
 | 
					static void dump_device(const pa_browse_info *i) {
 | 
				
			||||||
    char t[16], ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
 | 
					    char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (i->sample_spec)
 | 
					    if (i->sample_spec)
 | 
				
			||||||
        pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec);
 | 
					        pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (i->typeid)
 | 
					 | 
				
			||||||
        pa_typeid_to_string(*i->typeid, t, sizeof(t));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    printf("device: %s\n"
 | 
					    printf("device: %s\n"
 | 
				
			||||||
           "description: %s\n"
 | 
					           "description: %s\n"
 | 
				
			||||||
           "type: %s\n"
 | 
					 | 
				
			||||||
           "sample spec: %s\n",
 | 
					           "sample spec: %s\n",
 | 
				
			||||||
           i->device,
 | 
					           i->device,
 | 
				
			||||||
           i->description ? i->description : "n/a",
 | 
					           i->description ? i->description : "n/a",
 | 
				
			||||||
           i->typeid ? t : "n/a",
 | 
					 | 
				
			||||||
           i->sample_spec ? ss : "n/a");
 | 
					           i->sample_spec ? ss : "n/a");
 | 
				
			||||||
           
 | 
					           
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_info *i, void *userdata) {
 | 
					static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata) {
 | 
				
			||||||
    assert(b && i);
 | 
					    assert(b && i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (c) {
 | 
					    switch (c) {
 | 
				
			||||||
| 
						 | 
					@ -96,8 +91,16 @@ static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_
 | 
				
			||||||
            dump_device(i);
 | 
					            dump_device(i);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        case PA_BROWSE_REMOVE:
 | 
					        case PA_BROWSE_REMOVE_SERVER:
 | 
				
			||||||
            printf("\n=> removed service <%s>\n", i->name);
 | 
					            printf("\n=> removed server <%s>\n", i->name);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case PA_BROWSE_REMOVE_SINK:
 | 
				
			||||||
 | 
					            printf("\n=> removed sink <%s>\n", i->name);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case PA_BROWSE_REMOVE_SOURCE:
 | 
				
			||||||
 | 
					            printf("\n=> removed source <%s>\n", i->name);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue